├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── githubci.yml ├── .gitignore ├── Adafruit_PN532.cpp ├── Adafruit_PN532.h ├── README.md ├── examples ├── apduToBlackBerry │ ├── .esp32.test.skip │ ├── BlackBerry7 │ │ ├── .classpath │ │ ├── .project │ │ ├── .settings │ │ │ └── org.eclipse.jdt.core.prefs │ │ ├── BlackBerry_App_Descriptor.xml │ │ ├── build.xml │ │ ├── res │ │ │ └── img │ │ │ │ └── icon.png │ │ └── src │ │ │ └── mypackage │ │ │ ├── ColorMixer.java │ │ │ ├── MyApp.java │ │ │ └── MyScreen.java │ └── apduToBlackBerry.ino ├── iso14443a_uid │ └── iso14443a_uid.ino ├── iso14443as_target │ └── iso14443as_target.ino ├── mifareclassic_formatndef │ └── mifareclassic_formatndef.ino ├── mifareclassic_memdump │ └── mifareclassic_memdump.ino ├── mifareclassic_ndeftoclassic │ └── mifareclassic_ndeftoclassic.ino ├── mifareclassic_updatendef │ └── mifareclassic_updatendef.ino ├── ntag2xx_erase │ └── ntag2xx_erase.ino ├── ntag2xx_read │ └── ntag2xx_read.ino ├── ntag2xx_updatendef │ └── ntag2xx_updatendef.ino ├── readMifare │ └── readMifare.ino ├── readMifareClassic │ └── readMifareClassic.ino └── readMifareClassicIrq │ └── readMifareClassicIrq.ino ├── library.properties └── license.txt /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py main_platforms 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit PN532 Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Our handy .gitignore for automation ease 2 | Doxyfile* 3 | doxygen_sqlite3.db 4 | html 5 | -------------------------------------------------------------------------------- /Adafruit_PN532.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Adafruit_PN532.cpp 4 | 5 | @section intro_sec Introduction 6 | 7 | Driver for NXP's PN532 NFC/13.56MHz RFID Transceiver 8 | 9 | This is a library for the Adafruit PN532 NFC/RFID breakout boards 10 | This library works with the Adafruit NFC breakout 11 | ----> https://www.adafruit.com/products/364 12 | 13 | Check out the links above for our tutorials and wiring diagrams 14 | These chips use SPI or I2C to communicate. 15 | 16 | Adafruit invests time and resources providing this open source code, 17 | please support Adafruit and open-source hardware by purchasing 18 | products from Adafruit! 19 | 20 | @section author Author 21 | 22 | Adafruit Industries 23 | 24 | @section license License 25 | 26 | BSD (see license.txt) 27 | 28 | @section HISTORY 29 | 30 | v2.2 - Added startPassiveTargetIDDetection() to start card detection and 31 | readDetectedPassiveTargetID() to read it, useful when using the 32 | IRQ pin. 33 | 34 | v2.1 - Added NTAG2xx helper functions 35 | 36 | v2.0 - Refactored to add I2C support from Adafruit_NFCShield_I2C library. 37 | 38 | v1.4 - Added setPassiveActivationRetries() 39 | 40 | v1.2 - Added writeGPIO() 41 | - Added readGPIO() 42 | 43 | v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes 44 | - Added the following helper functions for text display 45 | static void PrintHex(const byte * data, const uint32_t numBytes) 46 | static void PrintHexChar(const byte * pbtData, const uint32_t 47 | numBytes) 48 | - Added the following Mifare Classic functions: 49 | bool mifareclassic_IsFirstBlock (uint32_t uiBlock) 50 | bool mifareclassic_IsTrailerBlock (uint32_t uiBlock) 51 | uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t 52 | uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) uint8_t 53 | mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) uint8_t 54 | mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) 55 | - Added the following Mifare Ultalight functions: 56 | uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 57 | */ 58 | /**************************************************************************/ 59 | 60 | #include "Adafruit_PN532.h" 61 | 62 | byte pn532ack[] = {0x00, 0x00, 0xFF, 63 | 0x00, 0xFF, 0x00}; ///< ACK message from PN532 64 | byte pn532response_firmwarevers[] = { 65 | 0x00, 0x00, 0xFF, 66 | 0x06, 0xFA, 0xD5}; ///< Expected firmware version message from PN532 67 | 68 | // Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE 69 | // related code 70 | 71 | // #define PN532DEBUG 72 | // #define MIFAREDEBUG 73 | 74 | // If using Native Port on Arduino Zero or Due define as SerialUSB 75 | #define PN532DEBUGPRINT Serial ///< Fixed name for debug Serial instance 76 | // #define PN532DEBUGPRINT SerialUSB ///< Fixed name for debug Serial instance 77 | 78 | #define PN532_PACKBUFFSIZ 64 ///< Packet buffer size in bytes 79 | byte pn532_packetbuffer[PN532_PACKBUFFSIZ]; ///< Packet buffer used in various 80 | ///< transactions 81 | 82 | /**************************************************************************/ 83 | /*! 84 | @brief Instantiates a new PN532 class using software SPI. 85 | 86 | @param clk SPI clock pin (SCK) 87 | @param miso SPI MISO pin 88 | @param mosi SPI MOSI pin 89 | @param ss SPI chip select pin (CS/SSEL) 90 | */ 91 | /**************************************************************************/ 92 | Adafruit_PN532::Adafruit_PN532(uint8_t clk, uint8_t miso, uint8_t mosi, 93 | uint8_t ss) { 94 | _cs = ss; 95 | spi_dev = new Adafruit_SPIDevice(ss, clk, miso, mosi, 1000000, 96 | SPI_BITORDER_LSBFIRST, SPI_MODE0); 97 | } 98 | 99 | /**************************************************************************/ 100 | /*! 101 | @brief Instantiates a new PN532 class using I2C. 102 | 103 | @param irq Location of the IRQ pin 104 | @param reset Location of the RSTPD_N pin 105 | @param theWire pointer to I2C bus to use 106 | */ 107 | /**************************************************************************/ 108 | Adafruit_PN532::Adafruit_PN532(uint8_t irq, uint8_t reset, TwoWire *theWire) 109 | : _irq(irq), _reset(reset) { 110 | pinMode(_irq, INPUT); 111 | pinMode(_reset, OUTPUT); 112 | i2c_dev = new Adafruit_I2CDevice(PN532_I2C_ADDRESS, theWire); 113 | } 114 | 115 | /**************************************************************************/ 116 | /*! 117 | @brief Instantiates a new PN532 class using hardware SPI. 118 | 119 | @param ss SPI chip select pin (CS/SSEL) 120 | @param theSPI pointer to the SPI bus to use 121 | */ 122 | /**************************************************************************/ 123 | Adafruit_PN532::Adafruit_PN532(uint8_t ss, SPIClass *theSPI) { 124 | _cs = ss; 125 | spi_dev = new Adafruit_SPIDevice(ss, 1000000, SPI_BITORDER_LSBFIRST, 126 | SPI_MODE0, theSPI); 127 | } 128 | 129 | /**************************************************************************/ 130 | /*! 131 | @brief Instantiates a new PN532 class using hardware UART (HSU). 132 | 133 | @param reset Location of the RSTPD_N pin 134 | @param theSer pointer to HardWare Serial bus to use 135 | */ 136 | /**************************************************************************/ 137 | Adafruit_PN532::Adafruit_PN532(uint8_t reset, HardwareSerial *theSer) 138 | : _reset(reset) { 139 | pinMode(_reset, OUTPUT); 140 | ser_dev = theSer; 141 | } 142 | 143 | /**************************************************************************/ 144 | /*! 145 | @brief Setups the HW 146 | 147 | @returns true if successful, otherwise false 148 | */ 149 | /**************************************************************************/ 150 | bool Adafruit_PN532::begin() { 151 | if (spi_dev) { 152 | // SPI initialization 153 | if (!spi_dev->begin()) { 154 | return false; 155 | } 156 | } else if (i2c_dev) { 157 | // I2C initialization 158 | // PN532 will fail address check since its asleep, so suppress 159 | if (!i2c_dev->begin(false)) { 160 | return false; 161 | } 162 | } else if (ser_dev) { 163 | ser_dev->begin(115200); 164 | // clear out anything in read buffer 165 | while (ser_dev->available()) 166 | ser_dev->read(); 167 | } else { 168 | // no interface specified 169 | return false; 170 | } 171 | reset(); // HW reset - put in known state 172 | delay(10); 173 | wakeup(); // hey! wakeup! 174 | return true; 175 | } 176 | 177 | /**************************************************************************/ 178 | /*! 179 | @brief Perform a hardware reset. Requires reset pin to have been provided. 180 | */ 181 | /**************************************************************************/ 182 | void Adafruit_PN532::reset(void) { 183 | // see Datasheet p.209, Fig.48 for timings 184 | if (_reset != -1) { 185 | digitalWrite(_reset, LOW); 186 | delay(1); // min 20ns 187 | digitalWrite(_reset, HIGH); 188 | delay(2); // max 2ms 189 | } 190 | } 191 | 192 | /**************************************************************************/ 193 | /*! 194 | @brief Wakeup from LowVbat mode into Normal Mode. 195 | */ 196 | /**************************************************************************/ 197 | void Adafruit_PN532::wakeup(void) { 198 | // interface specific wakeups - each one is unique! 199 | if (spi_dev) { 200 | // hold CS low for 2ms 201 | digitalWrite(_cs, LOW); 202 | delay(2); 203 | } else if (ser_dev) { 204 | uint8_t w[3] = {0x55, 0x00, 0x00}; 205 | ser_dev->write(w, 3); 206 | delay(2); 207 | } 208 | 209 | // PN532 will clock stretch I2C during SAMConfig as a "wakeup" 210 | 211 | // need to config SAM to stay in Normal Mode 212 | SAMConfig(); 213 | } 214 | 215 | /**************************************************************************/ 216 | /*! 217 | @brief Prints a hexadecimal value in plain characters 218 | 219 | @param data Pointer to the byte data 220 | @param numBytes Data length in bytes 221 | */ 222 | /**************************************************************************/ 223 | void Adafruit_PN532::PrintHex(const byte *data, const uint32_t numBytes) { 224 | uint32_t szPos; 225 | for (szPos = 0; szPos < numBytes; szPos++) { 226 | PN532DEBUGPRINT.print(F("0x")); 227 | // Append leading 0 for small values 228 | if (data[szPos] <= 0xF) 229 | PN532DEBUGPRINT.print(F("0")); 230 | PN532DEBUGPRINT.print(data[szPos] & 0xff, HEX); 231 | if ((numBytes > 1) && (szPos != numBytes - 1)) { 232 | PN532DEBUGPRINT.print(F(" ")); 233 | } 234 | } 235 | PN532DEBUGPRINT.println(); 236 | } 237 | 238 | /**************************************************************************/ 239 | /*! 240 | @brief Prints a hexadecimal value in plain characters, along with 241 | the char equivalents in the following format 242 | 243 | 00 00 00 00 00 00 ...... 244 | 245 | @param data Pointer to the byte data 246 | @param numBytes Data length in bytes 247 | */ 248 | /**************************************************************************/ 249 | void Adafruit_PN532::PrintHexChar(const byte *data, const uint32_t numBytes) { 250 | uint32_t szPos; 251 | for (szPos = 0; szPos < numBytes; szPos++) { 252 | // Append leading 0 for small values 253 | if (data[szPos] <= 0xF) 254 | PN532DEBUGPRINT.print(F("0")); 255 | PN532DEBUGPRINT.print(data[szPos], HEX); 256 | if ((numBytes > 1) && (szPos != numBytes - 1)) { 257 | PN532DEBUGPRINT.print(F(" ")); 258 | } 259 | } 260 | PN532DEBUGPRINT.print(F(" ")); 261 | for (szPos = 0; szPos < numBytes; szPos++) { 262 | if (data[szPos] <= 0x1F) 263 | PN532DEBUGPRINT.print(F(".")); 264 | else 265 | PN532DEBUGPRINT.print((char)data[szPos]); 266 | } 267 | PN532DEBUGPRINT.println(); 268 | } 269 | 270 | /**************************************************************************/ 271 | /*! 272 | @brief Checks the firmware version of the PN5xx chip 273 | 274 | @returns The chip's firmware version and ID 275 | */ 276 | /**************************************************************************/ 277 | uint32_t Adafruit_PN532::getFirmwareVersion(void) { 278 | uint32_t response; 279 | 280 | pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; 281 | 282 | if (!sendCommandCheckAck(pn532_packetbuffer, 1)) { 283 | return 0; 284 | } 285 | 286 | // read data packet 287 | readdata(pn532_packetbuffer, 13); 288 | 289 | // check some basic stuff 290 | if (0 != memcmp((char *)pn532_packetbuffer, 291 | (char *)pn532response_firmwarevers, 6)) { 292 | #ifdef PN532DEBUG 293 | PN532DEBUGPRINT.println(F("Firmware doesn't match!")); 294 | #endif 295 | return 0; 296 | } 297 | 298 | int offset = 7; 299 | response = pn532_packetbuffer[offset++]; 300 | response <<= 8; 301 | response |= pn532_packetbuffer[offset++]; 302 | response <<= 8; 303 | response |= pn532_packetbuffer[offset++]; 304 | response <<= 8; 305 | response |= pn532_packetbuffer[offset++]; 306 | 307 | return response; 308 | } 309 | 310 | /**************************************************************************/ 311 | /*! 312 | @brief Sends a command and waits a specified period for the ACK 313 | 314 | @param cmd Pointer to the command buffer 315 | @param cmdlen The size of the command in bytes 316 | @param timeout timeout before giving up 317 | 318 | @returns 1 if everything is OK, 0 if timeout occured before an 319 | ACK was recieved 320 | */ 321 | /**************************************************************************/ 322 | // default timeout of one second 323 | bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, 324 | uint16_t timeout) { 325 | 326 | // I2C works without using IRQ pin by polling for RDY byte 327 | // seems to work best with some delays between transactions 328 | uint8_t SLOWDOWN = 0; 329 | if (i2c_dev || spi_dev) // SPI and I2C need 1ms slow for page reads 330 | SLOWDOWN = 1; 331 | 332 | // write the command 333 | writecommand(cmd, cmdlen); 334 | 335 | // I2C TUNING 336 | delay(SLOWDOWN); 337 | 338 | // Wait for chip to say its ready! 339 | if (!waitready(timeout)) { 340 | return false; 341 | } 342 | 343 | #ifdef PN532DEBUG 344 | if (spi_dev == NULL) { 345 | PN532DEBUGPRINT.println(F("IRQ received")); 346 | } 347 | #endif 348 | 349 | // read acknowledgement 350 | if (!readack()) { 351 | #ifdef PN532DEBUG 352 | PN532DEBUGPRINT.println(F("No ACK frame received!")); 353 | #endif 354 | return false; 355 | } 356 | 357 | // I2C TUNING 358 | delay(SLOWDOWN); 359 | 360 | // Wait for chip to say its ready! 361 | if (!waitready(timeout)) { 362 | return false; 363 | } 364 | 365 | return true; // ack'd command 366 | } 367 | 368 | /**************************************************************************/ 369 | /*! 370 | @brief Writes an 8-bit value that sets the state of the PN532's GPIO 371 | pins. 372 | @param pinstate P3 pins state. 373 | 374 | @warning This function is provided exclusively for board testing and 375 | is dangerous since it will throw an error if any pin other 376 | than the ones marked "Can be used as GPIO" are modified! All 377 | pins that can not be used as GPIO should ALWAYS be left high 378 | (value = 1) or the system will become unstable and a HW reset 379 | will be required to recover the PN532. 380 | 381 | pinState[0] = P30 Can be used as GPIO 382 | pinState[1] = P31 Can be used as GPIO 383 | pinState[2] = P32 *** RESERVED (Must be 1!) *** 384 | pinState[3] = P33 Can be used as GPIO 385 | pinState[4] = P34 *** RESERVED (Must be 1!) *** 386 | pinState[5] = P35 Can be used as GPIO 387 | 388 | @return 1 if everything executed properly, 0 for an error 389 | */ 390 | /**************************************************************************/ 391 | bool Adafruit_PN532::writeGPIO(uint8_t pinstate) { 392 | // uint8_t errorbit; 393 | 394 | // Make sure pinstate does not try to toggle P32 or P34 395 | pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); 396 | 397 | // Fill command buffer 398 | pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; 399 | pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins 400 | pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by SPI) 401 | 402 | #ifdef PN532DEBUG 403 | PN532DEBUGPRINT.print(F("Writing P3 GPIO: ")); 404 | PN532DEBUGPRINT.println(pn532_packetbuffer[1], HEX); 405 | #endif 406 | 407 | // Send the WRITEGPIO command (0x0E) 408 | if (!sendCommandCheckAck(pn532_packetbuffer, 3)) 409 | return 0x0; 410 | 411 | // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 412 | // 00) 413 | readdata(pn532_packetbuffer, 8); 414 | 415 | #ifdef PN532DEBUG 416 | PN532DEBUGPRINT.print(F("Received: ")); 417 | PrintHex(pn532_packetbuffer, 8); 418 | PN532DEBUGPRINT.println(); 419 | #endif 420 | 421 | int offset = 6; 422 | return (pn532_packetbuffer[offset] == 0x0F); 423 | } 424 | 425 | /**************************************************************************/ 426 | /*! 427 | Reads the state of the PN532's GPIO pins 428 | 429 | @returns An 8-bit value containing the pin state where: 430 | 431 | pinState[0] = P30 432 | pinState[1] = P31 433 | pinState[2] = P32 434 | pinState[3] = P33 435 | pinState[4] = P34 436 | pinState[5] = P35 437 | */ 438 | /**************************************************************************/ 439 | uint8_t Adafruit_PN532::readGPIO(void) { 440 | pn532_packetbuffer[0] = PN532_COMMAND_READGPIO; 441 | 442 | // Send the READGPIO command (0x0C) 443 | if (!sendCommandCheckAck(pn532_packetbuffer, 1)) 444 | return 0x0; 445 | 446 | // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 447 | // DATACHECKSUM 00) 448 | readdata(pn532_packetbuffer, 11); 449 | 450 | /* READGPIO response should be in the following format: 451 | 452 | byte Description 453 | ------------- ------------------------------------------ 454 | b0..5 Frame header and preamble (with I2C there is an extra 0x00) 455 | b6 P3 GPIO Pins 456 | b7 P7 GPIO Pins (not used ... taken by SPI) 457 | b8 Interface Mode Pins (not used ... bus select pins) 458 | b9..10 checksum */ 459 | 460 | int p3offset = 7; 461 | 462 | #ifdef PN532DEBUG 463 | PN532DEBUGPRINT.print(F("Received: ")); 464 | PrintHex(pn532_packetbuffer, 11); 465 | PN532DEBUGPRINT.println(); 466 | PN532DEBUGPRINT.print(F("P3 GPIO: 0x")); 467 | PN532DEBUGPRINT.println(pn532_packetbuffer[p3offset], HEX); 468 | PN532DEBUGPRINT.print(F("P7 GPIO: 0x")); 469 | PN532DEBUGPRINT.println(pn532_packetbuffer[p3offset + 1], HEX); 470 | PN532DEBUGPRINT.print(F("IO GPIO: 0x")); 471 | PN532DEBUGPRINT.println(pn532_packetbuffer[p3offset + 2], HEX); 472 | // Note: You can use the IO GPIO value to detect the serial bus being used 473 | switch (pn532_packetbuffer[p3offset + 2]) { 474 | case 0x00: // Using UART 475 | PN532DEBUGPRINT.println(F("Using UART (IO = 0x00)")); 476 | break; 477 | case 0x01: // Using I2C 478 | PN532DEBUGPRINT.println(F("Using I2C (IO = 0x01)")); 479 | break; 480 | case 0x02: // Using SPI 481 | PN532DEBUGPRINT.println(F("Using SPI (IO = 0x02)")); 482 | break; 483 | } 484 | #endif 485 | 486 | return pn532_packetbuffer[p3offset]; 487 | } 488 | 489 | /**************************************************************************/ 490 | /*! 491 | @brief Configures the SAM (Secure Access Module) 492 | @return true on success, false otherwise. 493 | */ 494 | /**************************************************************************/ 495 | bool Adafruit_PN532::SAMConfig(void) { 496 | pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; 497 | pn532_packetbuffer[1] = 0x01; // normal mode; 498 | pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second 499 | pn532_packetbuffer[3] = 0x01; // use IRQ pin! 500 | 501 | if (!sendCommandCheckAck(pn532_packetbuffer, 4)) 502 | return false; 503 | 504 | // read data packet 505 | readdata(pn532_packetbuffer, 9); 506 | 507 | int offset = 6; 508 | return (pn532_packetbuffer[offset] == 0x15); 509 | } 510 | 511 | /**************************************************************************/ 512 | /*! 513 | Sets the MxRtyPassiveActivation byte of the RFConfiguration register 514 | 515 | @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout 516 | after mxRetries 517 | 518 | @returns 1 if everything executed properly, 0 for an error 519 | */ 520 | /**************************************************************************/ 521 | bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) { 522 | pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; 523 | pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) 524 | pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) 525 | pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) 526 | pn532_packetbuffer[4] = maxRetries; 527 | 528 | #ifdef MIFAREDEBUG 529 | PN532DEBUGPRINT.print(F("Setting MxRtyPassiveActivation to ")); 530 | PN532DEBUGPRINT.print(maxRetries, DEC); 531 | PN532DEBUGPRINT.println(F(" ")); 532 | #endif 533 | 534 | if (!sendCommandCheckAck(pn532_packetbuffer, 5)) 535 | return 0x0; // no ACK 536 | 537 | return 1; 538 | } 539 | 540 | /***** ISO14443A Commands ******/ 541 | 542 | /**************************************************************************/ 543 | /*! 544 | @brief Waits for an ISO14443A target to enter the field and reads 545 | its ID. 546 | 547 | @param cardbaudrate Baud rate of the card 548 | @param uid Pointer to the array that will be populated 549 | with the card's UID (up to 7 bytes) 550 | @param uidLength Pointer to the variable that will hold the 551 | length of the card's UID. 552 | @param timeout Timeout in milliseconds. 553 | 554 | @return 1 if everything executed properly, 0 for an error 555 | */ 556 | /**************************************************************************/ 557 | bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, 558 | uint8_t *uidLength, uint16_t timeout) { 559 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; 560 | pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) 561 | pn532_packetbuffer[2] = cardbaudrate; 562 | 563 | if (!sendCommandCheckAck(pn532_packetbuffer, 3, timeout)) { 564 | #ifdef PN532DEBUG 565 | PN532DEBUGPRINT.println(F("No card(s) read")); 566 | #endif 567 | return 0x0; // no cards read 568 | } 569 | 570 | return readDetectedPassiveTargetID(uid, uidLength); 571 | } 572 | 573 | /**************************************************************************/ 574 | /*! 575 | @brief Put the reader in detection mode, non blocking so interrupts 576 | must be enabled. 577 | @param cardbaudrate Baud rate of the card 578 | @return 1 if everything executed properly, 0 for an error 579 | */ 580 | /**************************************************************************/ 581 | bool Adafruit_PN532::startPassiveTargetIDDetection(uint8_t cardbaudrate) { 582 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; 583 | pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) 584 | pn532_packetbuffer[2] = cardbaudrate; 585 | 586 | return sendCommandCheckAck(pn532_packetbuffer, 3); 587 | } 588 | 589 | /**************************************************************************/ 590 | /*! 591 | Reads the ID of the passive target the reader has deteceted. 592 | 593 | @param uid Pointer to the array that will be populated 594 | with the card's UID (up to 7 bytes) 595 | @param uidLength Pointer to the variable that will hold the 596 | length of the card's UID. 597 | 598 | @returns 1 if everything executed properly, 0 for an error 599 | */ 600 | /**************************************************************************/ 601 | bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t *uid, 602 | uint8_t *uidLength) { 603 | // read data packet 604 | readdata(pn532_packetbuffer, 20); 605 | // check some basic stuff 606 | 607 | /* ISO14443A card response should be in the following format: 608 | 609 | byte Description 610 | ------------- ------------------------------------------ 611 | b0..6 Frame header and preamble 612 | b7 Tags Found 613 | b8 Tag Number (only one used in this example) 614 | b9..10 SENS_RES 615 | b11 SEL_RES 616 | b12 NFCID Length 617 | b13..NFCIDLen NFCID */ 618 | 619 | #ifdef MIFAREDEBUG 620 | PN532DEBUGPRINT.print(F("Found ")); 621 | PN532DEBUGPRINT.print(pn532_packetbuffer[7], DEC); 622 | PN532DEBUGPRINT.println(F(" tags")); 623 | #endif 624 | if (pn532_packetbuffer[7] != 1) 625 | return 0; 626 | 627 | uint16_t sens_res = pn532_packetbuffer[9]; 628 | sens_res <<= 8; 629 | sens_res |= pn532_packetbuffer[10]; 630 | #ifdef MIFAREDEBUG 631 | PN532DEBUGPRINT.print(F("ATQA: 0x")); 632 | PN532DEBUGPRINT.println(sens_res, HEX); 633 | PN532DEBUGPRINT.print(F("SAK: 0x")); 634 | PN532DEBUGPRINT.println(pn532_packetbuffer[11], HEX); 635 | #endif 636 | 637 | /* Card appears to be Mifare Classic */ 638 | *uidLength = pn532_packetbuffer[12]; 639 | #ifdef MIFAREDEBUG 640 | PN532DEBUGPRINT.print(F("UID:")); 641 | #endif 642 | for (uint8_t i = 0; i < pn532_packetbuffer[12]; i++) { 643 | uid[i] = pn532_packetbuffer[13 + i]; 644 | #ifdef MIFAREDEBUG 645 | PN532DEBUGPRINT.print(F(" 0x")); 646 | PN532DEBUGPRINT.print(uid[i], HEX); 647 | #endif 648 | } 649 | #ifdef MIFAREDEBUG 650 | PN532DEBUGPRINT.println(); 651 | #endif 652 | 653 | return 1; 654 | } 655 | 656 | /**************************************************************************/ 657 | /*! 658 | @brief Exchanges an APDU with the currently inlisted peer 659 | 660 | @param send Pointer to data to send 661 | @param sendLength Length of the data to send 662 | @param response Pointer to response data 663 | @param responseLength Pointer to the response data length 664 | @return true on success, false otherwise. 665 | */ 666 | /**************************************************************************/ 667 | bool Adafruit_PN532::inDataExchange(uint8_t *send, uint8_t sendLength, 668 | uint8_t *response, 669 | uint8_t *responseLength) { 670 | if (sendLength > PN532_PACKBUFFSIZ - 2) { 671 | #ifdef PN532DEBUG 672 | PN532DEBUGPRINT.println(F("APDU length too long for packet buffer")); 673 | #endif 674 | return false; 675 | } 676 | uint8_t i; 677 | 678 | pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE; 679 | pn532_packetbuffer[1] = _inListedTag; 680 | for (i = 0; i < sendLength; ++i) { 681 | pn532_packetbuffer[i + 2] = send[i]; 682 | } 683 | 684 | if (!sendCommandCheckAck(pn532_packetbuffer, sendLength + 2, 1000)) { 685 | #ifdef PN532DEBUG 686 | PN532DEBUGPRINT.println(F("Could not send APDU")); 687 | #endif 688 | return false; 689 | } 690 | 691 | if (!waitready(1000)) { 692 | #ifdef PN532DEBUG 693 | PN532DEBUGPRINT.println(F("Response never received for APDU...")); 694 | #endif 695 | return false; 696 | } 697 | 698 | readdata(pn532_packetbuffer, sizeof(pn532_packetbuffer)); 699 | 700 | if (pn532_packetbuffer[0] == 0 && pn532_packetbuffer[1] == 0 && 701 | pn532_packetbuffer[2] == 0xff) { 702 | uint8_t length = pn532_packetbuffer[3]; 703 | if (pn532_packetbuffer[4] != (uint8_t)(~length + 1)) { 704 | #ifdef PN532DEBUG 705 | PN532DEBUGPRINT.println(F("Length check invalid")); 706 | PN532DEBUGPRINT.println(length, HEX); 707 | PN532DEBUGPRINT.println((~length) + 1, HEX); 708 | #endif 709 | return false; 710 | } 711 | if (pn532_packetbuffer[5] == PN532_PN532TOHOST && 712 | pn532_packetbuffer[6] == PN532_RESPONSE_INDATAEXCHANGE) { 713 | if ((pn532_packetbuffer[7] & 0x3f) != 0) { 714 | #ifdef PN532DEBUG 715 | PN532DEBUGPRINT.println(F("Status code indicates an error")); 716 | #endif 717 | return false; 718 | } 719 | 720 | length -= 3; 721 | 722 | if (length > *responseLength) { 723 | length = *responseLength; // silent truncation... 724 | } 725 | 726 | for (i = 0; i < length; ++i) { 727 | response[i] = pn532_packetbuffer[8 + i]; 728 | } 729 | *responseLength = length; 730 | 731 | return true; 732 | } else { 733 | PN532DEBUGPRINT.print(F("Don't know how to handle this command: ")); 734 | PN532DEBUGPRINT.println(pn532_packetbuffer[6], HEX); 735 | return false; 736 | } 737 | } else { 738 | PN532DEBUGPRINT.println(F("Preamble missing")); 739 | return false; 740 | } 741 | } 742 | 743 | /**************************************************************************/ 744 | /*! 745 | @brief 'InLists' a passive target. PN532 acting as reader/initiator, 746 | peer acting as card/responder. 747 | @return true on success, false otherwise. 748 | */ 749 | /**************************************************************************/ 750 | bool Adafruit_PN532::inListPassiveTarget() { 751 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; 752 | pn532_packetbuffer[1] = 1; 753 | pn532_packetbuffer[2] = 0; 754 | 755 | #ifdef PN532DEBUG 756 | PN532DEBUGPRINT.print(F("About to inList passive target")); 757 | #endif 758 | 759 | if (!sendCommandCheckAck(pn532_packetbuffer, 3, 1000)) { 760 | #ifdef PN532DEBUG 761 | PN532DEBUGPRINT.println(F("Could not send inlist message")); 762 | #endif 763 | return false; 764 | } 765 | 766 | if (!waitready(30000)) { 767 | return false; 768 | } 769 | 770 | readdata(pn532_packetbuffer, sizeof(pn532_packetbuffer)); 771 | 772 | if (pn532_packetbuffer[0] == 0 && pn532_packetbuffer[1] == 0 && 773 | pn532_packetbuffer[2] == 0xff) { 774 | uint8_t length = pn532_packetbuffer[3]; 775 | if (pn532_packetbuffer[4] != (uint8_t)(~length + 1)) { 776 | #ifdef PN532DEBUG 777 | PN532DEBUGPRINT.println(F("Length check invalid")); 778 | PN532DEBUGPRINT.println(length, HEX); 779 | PN532DEBUGPRINT.println((~length) + 1, HEX); 780 | #endif 781 | return false; 782 | } 783 | if (pn532_packetbuffer[5] == PN532_PN532TOHOST && 784 | pn532_packetbuffer[6] == PN532_RESPONSE_INLISTPASSIVETARGET) { 785 | if (pn532_packetbuffer[7] != 1) { 786 | #ifdef PN532DEBUG 787 | PN532DEBUGPRINT.println(F("Unhandled number of targets inlisted")); 788 | #endif 789 | PN532DEBUGPRINT.println(F("Number of tags inlisted:")); 790 | PN532DEBUGPRINT.println(pn532_packetbuffer[7]); 791 | return false; 792 | } 793 | 794 | _inListedTag = pn532_packetbuffer[8]; 795 | PN532DEBUGPRINT.print(F("Tag number: ")); 796 | PN532DEBUGPRINT.println(_inListedTag); 797 | 798 | return true; 799 | } else { 800 | #ifdef PN532DEBUG 801 | PN532DEBUGPRINT.print(F("Unexpected response to inlist passive host")); 802 | #endif 803 | return false; 804 | } 805 | } else { 806 | #ifdef PN532DEBUG 807 | PN532DEBUGPRINT.println(F("Preamble missing")); 808 | #endif 809 | return false; 810 | } 811 | 812 | return true; 813 | } 814 | 815 | /***** Mifare Classic Functions ******/ 816 | 817 | /**************************************************************************/ 818 | /*! 819 | @brief Indicates whether the specified block number is the first block 820 | in the sector (block 0 relative to the current sector) 821 | @param uiBlock Block number to test. 822 | @return true if first block, false otherwise. 823 | */ 824 | /**************************************************************************/ 825 | bool Adafruit_PN532::mifareclassic_IsFirstBlock(uint32_t uiBlock) { 826 | // Test if we are in the small or big sectors 827 | if (uiBlock < 128) 828 | return ((uiBlock) % 4 == 0); 829 | else 830 | return ((uiBlock) % 16 == 0); 831 | } 832 | 833 | /**************************************************************************/ 834 | /*! 835 | @brief Indicates whether the specified block number is the sector 836 | trailer. 837 | @param uiBlock Block number to test. 838 | @return true if sector trailer, false otherwise. 839 | */ 840 | /**************************************************************************/ 841 | bool Adafruit_PN532::mifareclassic_IsTrailerBlock(uint32_t uiBlock) { 842 | // Test if we are in the small or big sectors 843 | if (uiBlock < 128) 844 | return ((uiBlock + 1) % 4 == 0); 845 | else 846 | return ((uiBlock + 1) % 16 == 0); 847 | } 848 | 849 | /**************************************************************************/ 850 | /*! 851 | Tries to authenticate a block of memory on a MIFARE card using the 852 | INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual 853 | for more information on sending MIFARE and other commands. 854 | 855 | @param uid Pointer to a byte array containing the card UID 856 | @param uidLen The length (in bytes) of the card's UID (Should 857 | be 4 for MIFARE Classic) 858 | @param blockNumber The block number to authenticate. (0..63 for 859 | 1KB cards, and 0..255 for 4KB cards). 860 | @param keyNumber Which key type to use during authentication 861 | (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B) 862 | @param keyData Pointer to a byte array containing the 6 byte 863 | key value 864 | 865 | @returns 1 if everything executed properly, 0 for an error 866 | */ 867 | /**************************************************************************/ 868 | uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock(uint8_t *uid, 869 | uint8_t uidLen, 870 | uint32_t blockNumber, 871 | uint8_t keyNumber, 872 | uint8_t *keyData) { 873 | // uint8_t len; 874 | uint8_t i; 875 | 876 | // Hang on to the key and uid data 877 | memcpy(_key, keyData, 6); 878 | memcpy(_uid, uid, uidLen); 879 | _uidLen = uidLen; 880 | 881 | #ifdef MIFAREDEBUG 882 | PN532DEBUGPRINT.print(F("Trying to authenticate card ")); 883 | Adafruit_PN532::PrintHex(_uid, _uidLen); 884 | PN532DEBUGPRINT.print(F("Using authentication KEY ")); 885 | PN532DEBUGPRINT.print(keyNumber ? 'B' : 'A'); 886 | PN532DEBUGPRINT.print(F(": ")); 887 | Adafruit_PN532::PrintHex(_key, 6); 888 | #endif 889 | 890 | // Prepare the authentication command // 891 | pn532_packetbuffer[0] = 892 | PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ 893 | pn532_packetbuffer[1] = 1; /* Max card numbers */ 894 | pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; 895 | pn532_packetbuffer[3] = 896 | blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ 897 | memcpy(pn532_packetbuffer + 4, _key, 6); 898 | for (i = 0; i < _uidLen; i++) { 899 | pn532_packetbuffer[10 + i] = _uid[i]; /* 4 byte card ID */ 900 | } 901 | 902 | if (!sendCommandCheckAck(pn532_packetbuffer, 10 + _uidLen)) 903 | return 0; 904 | 905 | // Read the response packet 906 | readdata(pn532_packetbuffer, 12); 907 | 908 | // check if the response is valid and we are authenticated??? 909 | // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00 910 | // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 911 | // is not good 912 | if (pn532_packetbuffer[7] != 0x00) { 913 | #ifdef PN532DEBUG 914 | PN532DEBUGPRINT.print(F("Authentification failed: ")); 915 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 12); 916 | #endif 917 | return 0; 918 | } 919 | 920 | return 1; 921 | } 922 | 923 | /**************************************************************************/ 924 | /*! 925 | Tries to read an entire 16-byte data block at the specified block 926 | address. 927 | 928 | @param blockNumber The block number to authenticate. (0..63 for 929 | 1KB cards, and 0..255 for 4KB cards). 930 | @param data Pointer to the byte array that will hold the 931 | retrieved data (if any) 932 | 933 | @returns 1 if everything executed properly, 0 for an error 934 | */ 935 | /**************************************************************************/ 936 | uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, 937 | uint8_t *data) { 938 | #ifdef MIFAREDEBUG 939 | PN532DEBUGPRINT.print(F("Trying to read 16 bytes from block ")); 940 | PN532DEBUGPRINT.println(blockNumber); 941 | #endif 942 | 943 | /* Prepare the command */ 944 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 945 | pn532_packetbuffer[1] = 1; /* Card number */ 946 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 947 | pn532_packetbuffer[3] = 948 | blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ 949 | 950 | /* Send the command */ 951 | if (!sendCommandCheckAck(pn532_packetbuffer, 4)) { 952 | #ifdef MIFAREDEBUG 953 | PN532DEBUGPRINT.println(F("Failed to receive ACK for read command")); 954 | #endif 955 | return 0; 956 | } 957 | 958 | /* Read the response packet */ 959 | readdata(pn532_packetbuffer, 26); 960 | 961 | /* If byte 8 isn't 0x00 we probably have an error */ 962 | if (pn532_packetbuffer[7] != 0x00) { 963 | #ifdef MIFAREDEBUG 964 | PN532DEBUGPRINT.println(F("Unexpected response")); 965 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 966 | #endif 967 | return 0; 968 | } 969 | 970 | /* Copy the 16 data bytes to the output buffer */ 971 | /* Block content starts at byte 9 of a valid response */ 972 | memcpy(data, pn532_packetbuffer + 8, 16); 973 | 974 | /* Display data for debug if requested */ 975 | #ifdef MIFAREDEBUG 976 | PN532DEBUGPRINT.print(F("Block ")); 977 | PN532DEBUGPRINT.println(blockNumber); 978 | Adafruit_PN532::PrintHexChar(data, 16); 979 | #endif 980 | 981 | return 1; 982 | } 983 | 984 | /**************************************************************************/ 985 | /*! 986 | Tries to write an entire 16-byte data block at the specified block 987 | address. 988 | 989 | @param blockNumber The block number to authenticate. (0..63 for 990 | 1KB cards, and 0..255 for 4KB cards). 991 | @param data The byte array that contains the data to write. 992 | 993 | @returns 1 if everything executed properly, 0 for an error 994 | */ 995 | /**************************************************************************/ 996 | uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock(uint8_t blockNumber, 997 | uint8_t *data) { 998 | #ifdef MIFAREDEBUG 999 | PN532DEBUGPRINT.print(F("Trying to write 16 bytes to block ")); 1000 | PN532DEBUGPRINT.println(blockNumber); 1001 | #endif 1002 | 1003 | /* Prepare the first command */ 1004 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1005 | pn532_packetbuffer[1] = 1; /* Card number */ 1006 | pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ 1007 | pn532_packetbuffer[3] = 1008 | blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ 1009 | memcpy(pn532_packetbuffer + 4, data, 16); /* Data Payload */ 1010 | 1011 | /* Send the command */ 1012 | if (!sendCommandCheckAck(pn532_packetbuffer, 20)) { 1013 | #ifdef MIFAREDEBUG 1014 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1015 | #endif 1016 | return 0; 1017 | } 1018 | delay(10); 1019 | 1020 | /* Read the response packet */ 1021 | readdata(pn532_packetbuffer, 26); 1022 | 1023 | return 1; 1024 | } 1025 | 1026 | /**************************************************************************/ 1027 | /*! 1028 | Formats a Mifare Classic card to store NDEF Records 1029 | 1030 | @returns 1 if everything executed properly, 0 for an error 1031 | */ 1032 | /**************************************************************************/ 1033 | uint8_t Adafruit_PN532::mifareclassic_FormatNDEF(void) { 1034 | uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 1035 | 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; 1036 | uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 1037 | 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; 1038 | uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 1039 | 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 1040 | 1041 | // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A 1042 | // for the MAD sector in NDEF records (sector 0) 1043 | 1044 | // Write block 1 and 2 to the card 1045 | if (!(mifareclassic_WriteDataBlock(1, sectorbuffer1))) 1046 | return 0; 1047 | if (!(mifareclassic_WriteDataBlock(2, sectorbuffer2))) 1048 | return 0; 1049 | // Write key A and access rights card 1050 | if (!(mifareclassic_WriteDataBlock(3, sectorbuffer3))) 1051 | return 0; 1052 | 1053 | // Seems that everything was OK (?!) 1054 | return 1; 1055 | } 1056 | 1057 | /**************************************************************************/ 1058 | /*! 1059 | Writes an NDEF URI Record to the specified sector (1..15) 1060 | 1061 | Note that this function assumes that the Mifare Classic card is 1062 | already formatted to work as an "NFC Forum Tag" and uses a MAD1 1063 | file system. You can use the NXP TagWriter app on Android to 1064 | properly format cards for this. 1065 | 1066 | @param sectorNumber The sector that the URI record should be written 1067 | to (can be 1..15 for a 1K card) 1068 | @param uriIdentifier The uri identifier code (0 = none, 0x01 = 1069 | "http://www.", etc.) 1070 | @param url The uri text to write (max 38 characters). 1071 | 1072 | @returns 1 if everything executed properly, 0 for an error 1073 | */ 1074 | /**************************************************************************/ 1075 | uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI(uint8_t sectorNumber, 1076 | uint8_t uriIdentifier, 1077 | const char *url) { 1078 | // Figure out how long the string is 1079 | uint8_t len = strlen(url); 1080 | 1081 | // Make sure we're within a 1K limit for the sector number 1082 | if ((sectorNumber < 1) || (sectorNumber > 15)) 1083 | return 0; 1084 | 1085 | // Make sure the URI payload is between 1 and 38 chars 1086 | if ((len < 1) || (len > 38)) 1087 | return 0; 1088 | 1089 | // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A 1090 | // in NDEF records 1091 | 1092 | // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) 1093 | uint8_t sectorbuffer1[16] = {0x00, 1094 | 0x00, 1095 | 0x03, 1096 | (uint8_t)(len + 5), 1097 | 0xD1, 1098 | 0x01, 1099 | (uint8_t)(len + 1), 1100 | 0x55, 1101 | uriIdentifier, 1102 | 0x00, 1103 | 0x00, 1104 | 0x00, 1105 | 0x00, 1106 | 0x00, 1107 | 0x00, 1108 | 0x00}; 1109 | uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 1111 | uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 1113 | uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 1114 | 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 1115 | if (len <= 6) { 1116 | // Unlikely we'll get a url this short, but why not ... 1117 | memcpy(sectorbuffer1 + 9, url, len); 1118 | sectorbuffer1[len + 9] = 0xFE; 1119 | } else if (len == 7) { 1120 | // 0xFE needs to be wrapped around to next block 1121 | memcpy(sectorbuffer1 + 9, url, len); 1122 | sectorbuffer2[0] = 0xFE; 1123 | } else if ((len > 7) && (len <= 22)) { 1124 | // Url fits in two blocks 1125 | memcpy(sectorbuffer1 + 9, url, 7); 1126 | memcpy(sectorbuffer2, url + 7, len - 7); 1127 | sectorbuffer2[len - 7] = 0xFE; 1128 | } else if (len == 23) { 1129 | // 0xFE needs to be wrapped around to final block 1130 | memcpy(sectorbuffer1 + 9, url, 7); 1131 | memcpy(sectorbuffer2, url + 7, len - 7); 1132 | sectorbuffer3[0] = 0xFE; 1133 | } else { 1134 | // Url fits in three blocks 1135 | memcpy(sectorbuffer1 + 9, url, 7); 1136 | memcpy(sectorbuffer2, url + 7, 16); 1137 | memcpy(sectorbuffer3, url + 23, len - 24); 1138 | sectorbuffer3[len - 22] = 0xFE; 1139 | } 1140 | 1141 | // Now write all three blocks back to the card 1142 | if (!(mifareclassic_WriteDataBlock(sectorNumber * 4, sectorbuffer1))) 1143 | return 0; 1144 | if (!(mifareclassic_WriteDataBlock((sectorNumber * 4) + 1, sectorbuffer2))) 1145 | return 0; 1146 | if (!(mifareclassic_WriteDataBlock((sectorNumber * 4) + 2, sectorbuffer3))) 1147 | return 0; 1148 | if (!(mifareclassic_WriteDataBlock((sectorNumber * 4) + 3, sectorbuffer4))) 1149 | return 0; 1150 | 1151 | // Seems that everything was OK (?!) 1152 | return 1; 1153 | } 1154 | 1155 | /***** Mifare Ultralight Functions ******/ 1156 | 1157 | /**************************************************************************/ 1158 | /*! 1159 | @brief Tries to read an entire 4-byte page at the specified address. 1160 | 1161 | @param page The page number (0..63 in most cases) 1162 | @param buffer Pointer to the byte array that will hold the 1163 | retrieved data (if any) 1164 | @return 1 on success, 0 on error. 1165 | */ 1166 | /**************************************************************************/ 1167 | uint8_t Adafruit_PN532::mifareultralight_ReadPage(uint8_t page, 1168 | uint8_t *buffer) { 1169 | if (page >= 64) { 1170 | #ifdef MIFAREDEBUG 1171 | PN532DEBUGPRINT.println(F("Page value out of range")); 1172 | #endif 1173 | return 0; 1174 | } 1175 | 1176 | #ifdef MIFAREDEBUG 1177 | PN532DEBUGPRINT.print(F("Reading page ")); 1178 | PN532DEBUGPRINT.println(page); 1179 | #endif 1180 | 1181 | /* Prepare the command */ 1182 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1183 | pn532_packetbuffer[1] = 1; /* Card number */ 1184 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 1185 | pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ 1186 | 1187 | /* Send the command */ 1188 | if (!sendCommandCheckAck(pn532_packetbuffer, 4)) { 1189 | #ifdef MIFAREDEBUG 1190 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1191 | #endif 1192 | return 0; 1193 | } 1194 | 1195 | /* Read the response packet */ 1196 | readdata(pn532_packetbuffer, 26); 1197 | #ifdef MIFAREDEBUG 1198 | PN532DEBUGPRINT.println(F("Received: ")); 1199 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1200 | #endif 1201 | 1202 | /* If byte 8 isn't 0x00 we probably have an error */ 1203 | if (pn532_packetbuffer[7] == 0x00) { 1204 | /* Copy the 4 data bytes to the output buffer */ 1205 | /* Block content starts at byte 9 of a valid response */ 1206 | /* Note that the command actually reads 16 byte or 4 */ 1207 | /* pages at a time ... we simply discard the last 12 */ 1208 | /* bytes */ 1209 | memcpy(buffer, pn532_packetbuffer + 8, 4); 1210 | } else { 1211 | #ifdef MIFAREDEBUG 1212 | PN532DEBUGPRINT.println(F("Unexpected response reading block: ")); 1213 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1214 | #endif 1215 | return 0; 1216 | } 1217 | 1218 | /* Display data for debug if requested */ 1219 | #ifdef MIFAREDEBUG 1220 | PN532DEBUGPRINT.print(F("Page ")); 1221 | PN532DEBUGPRINT.print(page); 1222 | PN532DEBUGPRINT.println(F(":")); 1223 | Adafruit_PN532::PrintHexChar(buffer, 4); 1224 | #endif 1225 | 1226 | // Return OK signal 1227 | return 1; 1228 | } 1229 | 1230 | /**************************************************************************/ 1231 | /*! 1232 | Tries to write an entire 4-byte page at the specified block 1233 | address. 1234 | 1235 | @param page The page number to write. (0..63 for most cases) 1236 | @param data The byte array that contains the data to write. 1237 | Should be exactly 4 bytes long. 1238 | 1239 | @returns 1 if everything executed properly, 0 for an error 1240 | */ 1241 | /**************************************************************************/ 1242 | uint8_t Adafruit_PN532::mifareultralight_WritePage(uint8_t page, 1243 | uint8_t *data) { 1244 | 1245 | if (page >= 64) { 1246 | #ifdef MIFAREDEBUG 1247 | PN532DEBUGPRINT.println(F("Page value out of range")); 1248 | #endif 1249 | // Return Failed Signal 1250 | return 0; 1251 | } 1252 | 1253 | #ifdef MIFAREDEBUG 1254 | PN532DEBUGPRINT.print(F("Trying to write 4 byte page")); 1255 | PN532DEBUGPRINT.println(page); 1256 | #endif 1257 | 1258 | /* Prepare the first command */ 1259 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1260 | pn532_packetbuffer[1] = 1; /* Card number */ 1261 | pn532_packetbuffer[2] = 1262 | MIFARE_ULTRALIGHT_CMD_WRITE; /* Mifare Ultralight Write command = 0xA2 */ 1263 | pn532_packetbuffer[3] = page; /* Page Number (0..63 for most cases) */ 1264 | memcpy(pn532_packetbuffer + 4, data, 4); /* Data Payload */ 1265 | 1266 | /* Send the command */ 1267 | if (!sendCommandCheckAck(pn532_packetbuffer, 8)) { 1268 | #ifdef MIFAREDEBUG 1269 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1270 | #endif 1271 | 1272 | // Return Failed Signal 1273 | return 0; 1274 | } 1275 | delay(10); 1276 | 1277 | /* Read the response packet */ 1278 | readdata(pn532_packetbuffer, 26); 1279 | 1280 | // Return OK Signal 1281 | return 1; 1282 | } 1283 | 1284 | /***** NTAG2xx Functions ******/ 1285 | 1286 | /**************************************************************************/ 1287 | /*! 1288 | @brief Tries to read an entire 4-byte page at the specified address. 1289 | 1290 | @param page The page number (0..63 in most cases) 1291 | @param buffer Pointer to the byte array that will hold the 1292 | retrieved data (if any) 1293 | @return 1 on success, 0 on error. 1294 | */ 1295 | /**************************************************************************/ 1296 | uint8_t Adafruit_PN532::ntag2xx_ReadPage(uint8_t page, uint8_t *buffer) { 1297 | // TAG Type PAGES USER START USER STOP 1298 | // -------- ----- ---------- --------- 1299 | // NTAG 203 42 4 39 1300 | // NTAG 213 45 4 39 1301 | // NTAG 215 135 4 129 1302 | // NTAG 216 231 4 225 1303 | 1304 | if (page >= 231) { 1305 | #ifdef MIFAREDEBUG 1306 | PN532DEBUGPRINT.println(F("Page value out of range")); 1307 | #endif 1308 | return 0; 1309 | } 1310 | 1311 | #ifdef MIFAREDEBUG 1312 | PN532DEBUGPRINT.print(F("Reading page ")); 1313 | PN532DEBUGPRINT.println(page); 1314 | #endif 1315 | 1316 | /* Prepare the command */ 1317 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1318 | pn532_packetbuffer[1] = 1; /* Card number */ 1319 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 1320 | pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ 1321 | 1322 | /* Send the command */ 1323 | if (!sendCommandCheckAck(pn532_packetbuffer, 4)) { 1324 | #ifdef MIFAREDEBUG 1325 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1326 | #endif 1327 | return 0; 1328 | } 1329 | 1330 | /* Read the response packet */ 1331 | readdata(pn532_packetbuffer, 26); 1332 | #ifdef MIFAREDEBUG 1333 | PN532DEBUGPRINT.println(F("Received: ")); 1334 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1335 | #endif 1336 | 1337 | /* If byte 8 isn't 0x00 we probably have an error */ 1338 | if (pn532_packetbuffer[7] == 0x00) { 1339 | /* Copy the 4 data bytes to the output buffer */ 1340 | /* Block content starts at byte 9 of a valid response */ 1341 | /* Note that the command actually reads 16 byte or 4 */ 1342 | /* pages at a time ... we simply discard the last 12 */ 1343 | /* bytes */ 1344 | memcpy(buffer, pn532_packetbuffer + 8, 4); 1345 | } else { 1346 | #ifdef MIFAREDEBUG 1347 | PN532DEBUGPRINT.println(F("Unexpected response reading block: ")); 1348 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1349 | #endif 1350 | return 0; 1351 | } 1352 | 1353 | /* Display data for debug if requested */ 1354 | #ifdef MIFAREDEBUG 1355 | PN532DEBUGPRINT.print(F("Page ")); 1356 | PN532DEBUGPRINT.print(page); 1357 | PN532DEBUGPRINT.println(F(":")); 1358 | Adafruit_PN532::PrintHexChar(buffer, 4); 1359 | #endif 1360 | 1361 | // Return OK signal 1362 | return 1; 1363 | } 1364 | 1365 | /**************************************************************************/ 1366 | /*! 1367 | Tries to write an entire 4-byte page at the specified block 1368 | address. 1369 | 1370 | @param page The page number to write. (0..63 for most cases) 1371 | @param data The byte array that contains the data to write. 1372 | Should be exactly 4 bytes long. 1373 | 1374 | @returns 1 if everything executed properly, 0 for an error 1375 | */ 1376 | /**************************************************************************/ 1377 | uint8_t Adafruit_PN532::ntag2xx_WritePage(uint8_t page, uint8_t *data) { 1378 | // TAG Type PAGES USER START USER STOP 1379 | // -------- ----- ---------- --------- 1380 | // NTAG 203 42 4 39 1381 | // NTAG 213 45 4 39 1382 | // NTAG 215 135 4 129 1383 | // NTAG 216 231 4 225 1384 | 1385 | if ((page < 4) || (page > 225)) { 1386 | #ifdef MIFAREDEBUG 1387 | PN532DEBUGPRINT.println(F("Page value out of range")); 1388 | #endif 1389 | // Return Failed Signal 1390 | return 0; 1391 | } 1392 | 1393 | #ifdef MIFAREDEBUG 1394 | PN532DEBUGPRINT.print(F("Trying to write 4 byte page")); 1395 | PN532DEBUGPRINT.println(page); 1396 | #endif 1397 | 1398 | /* Prepare the first command */ 1399 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1400 | pn532_packetbuffer[1] = 1; /* Card number */ 1401 | pn532_packetbuffer[2] = 1402 | MIFARE_ULTRALIGHT_CMD_WRITE; /* Mifare Ultralight Write command = 0xA2 */ 1403 | pn532_packetbuffer[3] = page; /* Page Number (0..63 for most cases) */ 1404 | memcpy(pn532_packetbuffer + 4, data, 4); /* Data Payload */ 1405 | 1406 | /* Send the command */ 1407 | if (!sendCommandCheckAck(pn532_packetbuffer, 8)) { 1408 | #ifdef MIFAREDEBUG 1409 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1410 | #endif 1411 | 1412 | // Return Failed Signal 1413 | return 0; 1414 | } 1415 | delay(10); 1416 | 1417 | /* Read the response packet */ 1418 | readdata(pn532_packetbuffer, 26); 1419 | 1420 | // Return OK Signal 1421 | return 1; 1422 | } 1423 | 1424 | /**************************************************************************/ 1425 | /*! 1426 | Writes an NDEF URI Record starting at the specified page (4..nn) 1427 | 1428 | Note that this function assumes that the NTAG2xx card is 1429 | already formatted to work as an "NFC Forum Tag". 1430 | 1431 | @param uriIdentifier The uri identifier code (0 = none, 0x01 = 1432 | "http://www.", etc.) 1433 | @param url The uri text to write (null-terminated string). 1434 | @param dataLen The size of the data area for overflow checks. 1435 | 1436 | @returns 1 if everything executed properly, 0 for an error 1437 | */ 1438 | /**************************************************************************/ 1439 | uint8_t Adafruit_PN532::ntag2xx_WriteNDEFURI(uint8_t uriIdentifier, char *url, 1440 | uint8_t dataLen) { 1441 | uint8_t pageBuffer[4] = {0, 0, 0, 0}; 1442 | 1443 | // Remove NDEF record overhead from the URI data (pageHeader below) 1444 | uint8_t wrapperSize = 12; 1445 | 1446 | // Figure out how long the string is 1447 | uint8_t len = strlen(url); 1448 | 1449 | // Make sure the URI payload will fit in dataLen (include 0xFE trailer) 1450 | if ((len < 1) || (len + 1 > (dataLen - wrapperSize))) 1451 | return 0; 1452 | 1453 | // Setup the record header 1454 | // See NFCForum-TS-Type-2-Tag_1.1.pdf for details 1455 | uint8_t pageHeader[12] = { 1456 | /* NDEF Lock Control TLV (must be first and always present) */ 1457 | 0x01, /* Tag Field (0x01 = Lock Control TLV) */ 1458 | 0x03, /* Payload Length (always 3) */ 1459 | 0xA0, /* The position inside the tag of the lock bytes (upper 4 = page 1460 | address, lower 4 = byte offset) */ 1461 | 0x10, /* Size in bits of the lock area */ 1462 | 0x44, /* Size in bytes of a page and the number of bytes each lock bit can 1463 | lock (4 bit + 4 bits) */ 1464 | /* NDEF Message TLV - URI Record */ 1465 | 0x03, /* Tag Field (0x03 = NDEF Message) */ 1466 | (uint8_t)(len + 5), /* Payload Length (not including 0xFE trailer) */ 1467 | 0xD1, /* NDEF Record Header (TNF=0x1:Well known record + SR + ME + MB) */ 1468 | 0x01, /* Type Length for the record type indicator */ 1469 | (uint8_t)(len + 1), /* Payload len */ 1470 | 0x55, /* Record Type Indicator (0x55 or 'U' = URI Record) */ 1471 | uriIdentifier /* URI Prefix (ex. 0x01 = "http://www.") */ 1472 | }; 1473 | 1474 | // Write 12 byte header (three pages of data starting at page 4) 1475 | memcpy(pageBuffer, pageHeader, 4); 1476 | if (!(ntag2xx_WritePage(4, pageBuffer))) 1477 | return 0; 1478 | memcpy(pageBuffer, pageHeader + 4, 4); 1479 | if (!(ntag2xx_WritePage(5, pageBuffer))) 1480 | return 0; 1481 | memcpy(pageBuffer, pageHeader + 8, 4); 1482 | if (!(ntag2xx_WritePage(6, pageBuffer))) 1483 | return 0; 1484 | 1485 | // Write URI (starting at page 7) 1486 | uint8_t currentPage = 7; 1487 | char *urlcopy = url; 1488 | while (len) { 1489 | if (len < 4) { 1490 | memset(pageBuffer, 0, 4); 1491 | memcpy(pageBuffer, urlcopy, len); 1492 | pageBuffer[len] = 0xFE; // NDEF record footer 1493 | if (!(ntag2xx_WritePage(currentPage, pageBuffer))) 1494 | return 0; 1495 | // DONE! 1496 | return 1; 1497 | } else if (len == 4) { 1498 | memcpy(pageBuffer, urlcopy, len); 1499 | if (!(ntag2xx_WritePage(currentPage, pageBuffer))) 1500 | return 0; 1501 | memset(pageBuffer, 0, 4); 1502 | pageBuffer[0] = 0xFE; // NDEF record footer 1503 | currentPage++; 1504 | if (!(ntag2xx_WritePage(currentPage, pageBuffer))) 1505 | return 0; 1506 | // DONE! 1507 | return 1; 1508 | } else { 1509 | // More than one page of data left 1510 | memcpy(pageBuffer, urlcopy, 4); 1511 | if (!(ntag2xx_WritePage(currentPage, pageBuffer))) 1512 | return 0; 1513 | currentPage++; 1514 | urlcopy += 4; 1515 | len -= 4; 1516 | } 1517 | } 1518 | 1519 | // Seems that everything was OK (?!) 1520 | return 1; 1521 | } 1522 | 1523 | /************** high level communication functions (handles both I2C and SPI) */ 1524 | 1525 | /**************************************************************************/ 1526 | /*! 1527 | @brief Tries to read the SPI or I2C ACK signal 1528 | */ 1529 | /**************************************************************************/ 1530 | bool Adafruit_PN532::readack() { 1531 | uint8_t ackbuff[6]; 1532 | 1533 | if (spi_dev) { 1534 | uint8_t cmd = PN532_SPI_DATAREAD; 1535 | spi_dev->write_then_read(&cmd, 1, ackbuff, 6); 1536 | } else if (i2c_dev || ser_dev) { 1537 | readdata(ackbuff, 6); 1538 | } 1539 | 1540 | return (0 == memcmp((char *)ackbuff, (char *)pn532ack, 6)); 1541 | } 1542 | 1543 | /**************************************************************************/ 1544 | /*! 1545 | @brief Return true if the PN532 is ready with a response. 1546 | */ 1547 | /**************************************************************************/ 1548 | bool Adafruit_PN532::isready() { 1549 | if (spi_dev) { 1550 | // SPI ready check via Status Request 1551 | uint8_t cmd = PN532_SPI_STATREAD; 1552 | uint8_t reply; 1553 | spi_dev->write_then_read(&cmd, 1, &reply, 1); 1554 | return reply == PN532_SPI_READY; 1555 | } else if (i2c_dev) { 1556 | // I2C ready check via reading RDY byte 1557 | uint8_t rdy[1]; 1558 | i2c_dev->read(rdy, 1); 1559 | return rdy[0] == PN532_I2C_READY; 1560 | } else if (ser_dev) { 1561 | // Serial ready check based on non-zero read buffer 1562 | return (ser_dev->available() != 0); 1563 | } else if (_irq != -1) { 1564 | uint8_t x = digitalRead(_irq); 1565 | return x == 0; 1566 | } 1567 | return false; 1568 | } 1569 | 1570 | /**************************************************************************/ 1571 | /*! 1572 | @brief Waits until the PN532 is ready. 1573 | 1574 | @param timeout Timeout before giving up 1575 | */ 1576 | /**************************************************************************/ 1577 | bool Adafruit_PN532::waitready(uint16_t timeout) { 1578 | uint16_t timer = 0; 1579 | while (!isready()) { 1580 | if (timeout != 0) { 1581 | timer += 10; 1582 | if (timer > timeout) { 1583 | #ifdef PN532DEBUG 1584 | PN532DEBUGPRINT.println("TIMEOUT!"); 1585 | #endif 1586 | return false; 1587 | } 1588 | } 1589 | delay(10); 1590 | } 1591 | return true; 1592 | } 1593 | 1594 | /**************************************************************************/ 1595 | /*! 1596 | @brief Reads n bytes of data from the PN532 via SPI or I2C. 1597 | 1598 | @param buff Pointer to the buffer where data will be written 1599 | @param n Number of bytes to be read 1600 | */ 1601 | /**************************************************************************/ 1602 | void Adafruit_PN532::readdata(uint8_t *buff, uint8_t n) { 1603 | if (spi_dev) { 1604 | // SPI read 1605 | uint8_t cmd = PN532_SPI_DATAREAD; 1606 | spi_dev->write_then_read(&cmd, 1, buff, n); 1607 | } else if (i2c_dev) { 1608 | // I2C read 1609 | uint8_t rbuff[n + 1]; // +1 for leading RDY byte 1610 | i2c_dev->read(rbuff, n + 1); 1611 | for (uint8_t i = 0; i < n; i++) { 1612 | buff[i] = rbuff[i + 1]; 1613 | } 1614 | } else if (ser_dev) { 1615 | // Serial read 1616 | ser_dev->readBytes(buff, n); 1617 | } 1618 | #ifdef PN532DEBUG 1619 | PN532DEBUGPRINT.print(F("Reading: ")); 1620 | for (uint8_t i = 0; i < n; i++) { 1621 | PN532DEBUGPRINT.print(F(" 0x")); 1622 | PN532DEBUGPRINT.print(buff[i], HEX); 1623 | } 1624 | PN532DEBUGPRINT.println(); 1625 | #endif 1626 | } 1627 | 1628 | /**************************************************************************/ 1629 | /*! 1630 | @brief set the PN532 as iso14443a Target behaving as a SmartCard 1631 | @return true on success, false otherwise. 1632 | @note Author: Salvador Mendoza (salmg.net) new functions: 1633 | -AsTarget 1634 | -getDataTarget 1635 | -setDataTarget 1636 | */ 1637 | /**************************************************************************/ 1638 | uint8_t Adafruit_PN532::AsTarget() { 1639 | pn532_packetbuffer[0] = 0x8C; 1640 | uint8_t target[] = { 1641 | 0x8C, // INIT AS TARGET 1642 | 0x00, // MODE -> BITFIELD 1643 | 0x08, 0x00, // SENS_RES - MIFARE PARAMS 1644 | 0xdc, 0x44, 0x20, // NFCID1T 1645 | 0x60, // SEL_RES 1646 | 0x01, 0xfe, // NFCID2T MUST START WITH 01fe - FELICA PARAMS - POL_RES 1647 | 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xc0, 1648 | 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, // PAD 1649 | 0xff, 0xff, // SYSTEM CODE 1650 | 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 1651 | 0x33, 0x22, 0x11, 0x01, 0x00, // NFCID3t MAX 47 BYTES ATR_RES 1652 | 0x0d, 0x52, 0x46, 0x49, 0x44, 0x49, 0x4f, 1653 | 0x74, 0x20, 0x50, 0x4e, 0x35, 0x33, 0x32 // HISTORICAL BYTES 1654 | }; 1655 | if (!sendCommandCheckAck(target, sizeof(target))) 1656 | return false; 1657 | 1658 | // read data packet 1659 | readdata(pn532_packetbuffer, 8); 1660 | 1661 | int offset = 6; 1662 | return (pn532_packetbuffer[offset] == 0x15); 1663 | } 1664 | /**************************************************************************/ 1665 | /*! 1666 | @brief Retrieve response from the emulation mode 1667 | 1668 | @param cmd = data 1669 | @param cmdlen = data length 1670 | @return true on success, false otherwise. 1671 | */ 1672 | /**************************************************************************/ 1673 | uint8_t Adafruit_PN532::getDataTarget(uint8_t *cmd, uint8_t *cmdlen) { 1674 | uint8_t length; 1675 | pn532_packetbuffer[0] = 0x86; 1676 | if (!sendCommandCheckAck(pn532_packetbuffer, 1, 1000)) { 1677 | PN532DEBUGPRINT.println(F("Error en ack")); 1678 | return false; 1679 | } 1680 | 1681 | // read data packet 1682 | readdata(pn532_packetbuffer, 64); 1683 | length = pn532_packetbuffer[3] - 3; 1684 | 1685 | // if (length > *responseLength) {// Bug, should avoid it in the reading 1686 | // target data 1687 | // length = *responseLength; // silent truncation... 1688 | //} 1689 | 1690 | for (int i = 0; i < length; ++i) { 1691 | cmd[i] = pn532_packetbuffer[8 + i]; 1692 | } 1693 | *cmdlen = length; 1694 | return true; 1695 | } 1696 | 1697 | /**************************************************************************/ 1698 | /*! 1699 | @brief Set data in PN532 in the emulation mode 1700 | 1701 | @param cmd = data 1702 | @param cmdlen = data length 1703 | @return true on success, false otherwise. 1704 | */ 1705 | /**************************************************************************/ 1706 | uint8_t Adafruit_PN532::setDataTarget(uint8_t *cmd, uint8_t cmdlen) { 1707 | uint8_t length; 1708 | // cmd1[0] = 0x8E; Must! 1709 | 1710 | if (!sendCommandCheckAck(cmd, cmdlen)) 1711 | return false; 1712 | 1713 | // read data packet 1714 | readdata(pn532_packetbuffer, 8); 1715 | length = pn532_packetbuffer[3] - 3; 1716 | for (int i = 0; i < length; ++i) { 1717 | cmd[i] = pn532_packetbuffer[8 + i]; 1718 | } 1719 | // cmdl = 0 1720 | cmdlen = length; 1721 | 1722 | int offset = 6; 1723 | return (pn532_packetbuffer[offset] == 0x15); 1724 | } 1725 | 1726 | /**************************************************************************/ 1727 | /*! 1728 | @brief Writes a command to the PN532, automatically inserting the 1729 | preamble and required frame details (checksum, len, etc.) 1730 | 1731 | @param cmd Pointer to the command buffer 1732 | @param cmdlen Command length in bytes 1733 | */ 1734 | /**************************************************************************/ 1735 | void Adafruit_PN532::writecommand(uint8_t *cmd, uint8_t cmdlen) { 1736 | if (spi_dev) { 1737 | // SPI command write. 1738 | uint8_t checksum; 1739 | uint8_t packet[9 + cmdlen]; 1740 | uint8_t *p = packet; 1741 | cmdlen++; 1742 | 1743 | p[0] = PN532_SPI_DATAWRITE; 1744 | p++; 1745 | 1746 | p[0] = PN532_PREAMBLE; 1747 | p++; 1748 | p[0] = PN532_STARTCODE1; 1749 | p++; 1750 | p[0] = PN532_STARTCODE2; 1751 | p++; 1752 | checksum = PN532_PREAMBLE + PN532_STARTCODE1 + PN532_STARTCODE2; 1753 | 1754 | p[0] = cmdlen; 1755 | p++; 1756 | p[0] = ~cmdlen + 1; 1757 | p++; 1758 | 1759 | p[0] = PN532_HOSTTOPN532; 1760 | p++; 1761 | checksum += PN532_HOSTTOPN532; 1762 | 1763 | for (uint8_t i = 0; i < cmdlen - 1; i++) { 1764 | p[0] = cmd[i]; 1765 | p++; 1766 | checksum += cmd[i]; 1767 | } 1768 | 1769 | p[0] = ~checksum; 1770 | p++; 1771 | p[0] = PN532_POSTAMBLE; 1772 | p++; 1773 | 1774 | #ifdef PN532DEBUG 1775 | Serial.print("Sending : "); 1776 | for (int i = 1; i < 8 + cmdlen; i++) { 1777 | Serial.print("0x"); 1778 | Serial.print(packet[i], HEX); 1779 | Serial.print(", "); 1780 | } 1781 | Serial.println(); 1782 | #endif 1783 | 1784 | spi_dev->write(packet, 8 + cmdlen); 1785 | } else if (i2c_dev || ser_dev) { 1786 | // I2C or Serial command write. 1787 | uint8_t packet[8 + cmdlen]; 1788 | uint8_t LEN = cmdlen + 1; 1789 | 1790 | packet[0] = PN532_PREAMBLE; 1791 | packet[1] = PN532_STARTCODE1; 1792 | packet[2] = PN532_STARTCODE2; 1793 | packet[3] = LEN; 1794 | packet[4] = ~LEN + 1; 1795 | packet[5] = PN532_HOSTTOPN532; 1796 | uint8_t sum = 0; 1797 | for (uint8_t i = 0; i < cmdlen; i++) { 1798 | packet[6 + i] = cmd[i]; 1799 | sum += cmd[i]; 1800 | } 1801 | packet[6 + cmdlen] = ~(PN532_HOSTTOPN532 + sum) + 1; 1802 | packet[7 + cmdlen] = PN532_POSTAMBLE; 1803 | 1804 | #ifdef PN532DEBUG 1805 | Serial.print("Sending : "); 1806 | for (int i = 1; i < 8 + cmdlen; i++) { 1807 | Serial.print("0x"); 1808 | Serial.print(packet[i], HEX); 1809 | Serial.print(", "); 1810 | } 1811 | Serial.println(); 1812 | #endif 1813 | 1814 | if (i2c_dev) { 1815 | i2c_dev->write(packet, 8 + cmdlen); 1816 | } else { 1817 | ser_dev->write(packet, 8 + cmdlen); 1818 | } 1819 | } 1820 | } 1821 | -------------------------------------------------------------------------------- /Adafruit_PN532.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Adafruit_PN532.h 4 | 5 | v2.0 - Refactored to add I2C support from Adafruit_NFCShield_I2C library. 6 | 7 | v1.1 - Added full command list 8 | - Added 'verbose' mode flag to constructor to toggle debug output 9 | - Changed readPassiveTargetID() to return variable length values 10 | */ 11 | /**************************************************************************/ 12 | 13 | #ifndef ADAFRUIT_PN532_H 14 | #define ADAFRUIT_PN532_H 15 | 16 | #include "Arduino.h" 17 | 18 | #include 19 | #include 20 | 21 | #define PN532_PREAMBLE (0x00) ///< Command sequence start, byte 1/3 22 | #define PN532_STARTCODE1 (0x00) ///< Command sequence start, byte 2/3 23 | #define PN532_STARTCODE2 (0xFF) ///< Command sequence start, byte 3/3 24 | #define PN532_POSTAMBLE (0x00) ///< EOD 25 | 26 | #define PN532_HOSTTOPN532 (0xD4) ///< Host-to-PN532 27 | #define PN532_PN532TOHOST (0xD5) ///< PN532-to-host 28 | 29 | // PN532 Commands 30 | #define PN532_COMMAND_DIAGNOSE (0x00) ///< Diagnose 31 | #define PN532_COMMAND_GETFIRMWAREVERSION (0x02) ///< Get firmware version 32 | #define PN532_COMMAND_GETGENERALSTATUS (0x04) ///< Get general status 33 | #define PN532_COMMAND_READREGISTER (0x06) ///< Read register 34 | #define PN532_COMMAND_WRITEREGISTER (0x08) ///< Write register 35 | #define PN532_COMMAND_READGPIO (0x0C) ///< Read GPIO 36 | #define PN532_COMMAND_WRITEGPIO (0x0E) ///< Write GPIO 37 | #define PN532_COMMAND_SETSERIALBAUDRATE (0x10) ///< Set serial baud rate 38 | #define PN532_COMMAND_SETPARAMETERS (0x12) ///< Set parameters 39 | #define PN532_COMMAND_SAMCONFIGURATION (0x14) ///< SAM configuration 40 | #define PN532_COMMAND_POWERDOWN (0x16) ///< Power down 41 | #define PN532_COMMAND_RFCONFIGURATION (0x32) ///< RF config 42 | #define PN532_COMMAND_RFREGULATIONTEST (0x58) ///< RF regulation test 43 | #define PN532_COMMAND_INJUMPFORDEP (0x56) ///< Jump for DEP 44 | #define PN532_COMMAND_INJUMPFORPSL (0x46) ///< Jump for PSL 45 | #define PN532_COMMAND_INLISTPASSIVETARGET (0x4A) ///< List passive target 46 | #define PN532_COMMAND_INATR (0x50) ///< ATR 47 | #define PN532_COMMAND_INPSL (0x4E) ///< PSL 48 | #define PN532_COMMAND_INDATAEXCHANGE (0x40) ///< Data exchange 49 | #define PN532_COMMAND_INCOMMUNICATETHRU (0x42) ///< Communicate through 50 | #define PN532_COMMAND_INDESELECT (0x44) ///< Deselect 51 | #define PN532_COMMAND_INRELEASE (0x52) ///< Release 52 | #define PN532_COMMAND_INSELECT (0x54) ///< Select 53 | #define PN532_COMMAND_INAUTOPOLL (0x60) ///< Auto poll 54 | #define PN532_COMMAND_TGINITASTARGET (0x8C) ///< Init as target 55 | #define PN532_COMMAND_TGSETGENERALBYTES (0x92) ///< Set general bytes 56 | #define PN532_COMMAND_TGGETDATA (0x86) ///< Get data 57 | #define PN532_COMMAND_TGSETDATA (0x8E) ///< Set data 58 | #define PN532_COMMAND_TGSETMETADATA (0x94) ///< Set metadata 59 | #define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88) ///< Get initiator command 60 | #define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90) ///< Response to initiator 61 | #define PN532_COMMAND_TGGETTARGETSTATUS (0x8A) ///< Get target status 62 | 63 | #define PN532_RESPONSE_INDATAEXCHANGE (0x41) ///< Data exchange 64 | #define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B) ///< List passive target 65 | 66 | #define PN532_WAKEUP (0x55) ///< Wake 67 | 68 | #define PN532_SPI_STATREAD (0x02) ///< Stat read 69 | #define PN532_SPI_DATAWRITE (0x01) ///< Data write 70 | #define PN532_SPI_DATAREAD (0x03) ///< Data read 71 | #define PN532_SPI_READY (0x01) ///< Ready 72 | 73 | #define PN532_I2C_ADDRESS (0x48 >> 1) ///< Default I2C address 74 | #define PN532_I2C_READBIT (0x01) ///< Read bit 75 | #define PN532_I2C_BUSY (0x00) ///< Busy 76 | #define PN532_I2C_READY (0x01) ///< Ready 77 | #define PN532_I2C_READYTIMEOUT (20) ///< Ready timeout 78 | 79 | #define PN532_MIFARE_ISO14443A (0x00) ///< MiFare 80 | 81 | // Mifare Commands 82 | #define MIFARE_CMD_AUTH_A (0x60) ///< Auth A 83 | #define MIFARE_CMD_AUTH_B (0x61) ///< Auth B 84 | #define MIFARE_CMD_READ (0x30) ///< Read 85 | #define MIFARE_CMD_WRITE (0xA0) ///< Write 86 | #define MIFARE_CMD_TRANSFER (0xB0) ///< Transfer 87 | #define MIFARE_CMD_DECREMENT (0xC0) ///< Decrement 88 | #define MIFARE_CMD_INCREMENT (0xC1) ///< Increment 89 | #define MIFARE_CMD_STORE (0xC2) ///< Store 90 | #define MIFARE_ULTRALIGHT_CMD_WRITE (0xA2) ///< Write (MiFare Ultralight) 91 | 92 | // Prefixes for NDEF Records (to identify record type) 93 | #define NDEF_URIPREFIX_NONE (0x00) ///< No prefix 94 | #define NDEF_URIPREFIX_HTTP_WWWDOT (0x01) ///< HTTP www. prefix 95 | #define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02) ///< HTTPS www. prefix 96 | #define NDEF_URIPREFIX_HTTP (0x03) ///< HTTP prefix 97 | #define NDEF_URIPREFIX_HTTPS (0x04) ///< HTTPS prefix 98 | #define NDEF_URIPREFIX_TEL (0x05) ///< Tel prefix 99 | #define NDEF_URIPREFIX_MAILTO (0x06) ///< Mailto prefix 100 | #define NDEF_URIPREFIX_FTP_ANONAT (0x07) ///< FTP 101 | #define NDEF_URIPREFIX_FTP_FTPDOT (0x08) ///< FTP dot 102 | #define NDEF_URIPREFIX_FTPS (0x09) ///< FTPS 103 | #define NDEF_URIPREFIX_SFTP (0x0A) ///< SFTP 104 | #define NDEF_URIPREFIX_SMB (0x0B) ///< SMB 105 | #define NDEF_URIPREFIX_NFS (0x0C) ///< NFS 106 | #define NDEF_URIPREFIX_FTP (0x0D) ///< FTP 107 | #define NDEF_URIPREFIX_DAV (0x0E) ///< DAV 108 | #define NDEF_URIPREFIX_NEWS (0x0F) ///< NEWS 109 | #define NDEF_URIPREFIX_TELNET (0x10) ///< Telnet prefix 110 | #define NDEF_URIPREFIX_IMAP (0x11) ///< IMAP prefix 111 | #define NDEF_URIPREFIX_RTSP (0x12) ///< RTSP 112 | #define NDEF_URIPREFIX_URN (0x13) ///< URN 113 | #define NDEF_URIPREFIX_POP (0x14) ///< POP 114 | #define NDEF_URIPREFIX_SIP (0x15) ///< SIP 115 | #define NDEF_URIPREFIX_SIPS (0x16) ///< SIPS 116 | #define NDEF_URIPREFIX_TFTP (0x17) ///< TFPT 117 | #define NDEF_URIPREFIX_BTSPP (0x18) ///< BTSPP 118 | #define NDEF_URIPREFIX_BTL2CAP (0x19) ///< BTL2CAP 119 | #define NDEF_URIPREFIX_BTGOEP (0x1A) ///< BTGOEP 120 | #define NDEF_URIPREFIX_TCPOBEX (0x1B) ///< TCPOBEX 121 | #define NDEF_URIPREFIX_IRDAOBEX (0x1C) ///< IRDAOBEX 122 | #define NDEF_URIPREFIX_FILE (0x1D) ///< File 123 | #define NDEF_URIPREFIX_URN_EPC_ID (0x1E) ///< URN EPC ID 124 | #define NDEF_URIPREFIX_URN_EPC_TAG (0x1F) ///< URN EPC tag 125 | #define NDEF_URIPREFIX_URN_EPC_PAT (0x20) ///< URN EPC pat 126 | #define NDEF_URIPREFIX_URN_EPC_RAW (0x21) ///< URN EPC raw 127 | #define NDEF_URIPREFIX_URN_EPC (0x22) ///< URN EPC 128 | #define NDEF_URIPREFIX_URN_NFC (0x23) ///< URN NFC 129 | 130 | #define PN532_GPIO_VALIDATIONBIT (0x80) ///< GPIO validation bit 131 | #define PN532_GPIO_P30 (0) ///< GPIO 30 132 | #define PN532_GPIO_P31 (1) ///< GPIO 31 133 | #define PN532_GPIO_P32 (2) ///< GPIO 32 134 | #define PN532_GPIO_P33 (3) ///< GPIO 33 135 | #define PN532_GPIO_P34 (4) ///< GPIO 34 136 | #define PN532_GPIO_P35 (5) ///< GPIO 35 137 | 138 | /** 139 | * @brief Class for working with Adafruit PN532 NFC/RFID breakout boards. 140 | */ 141 | class Adafruit_PN532 { 142 | public: 143 | Adafruit_PN532(uint8_t clk, uint8_t miso, uint8_t mosi, 144 | uint8_t ss); // Software SPI 145 | Adafruit_PN532(uint8_t ss, SPIClass *theSPI = &SPI); // Hardware SPI 146 | Adafruit_PN532(uint8_t irq, uint8_t reset, 147 | TwoWire *theWire = &Wire); // Hardware I2C 148 | Adafruit_PN532(uint8_t reset, HardwareSerial *theSer); // Hardware UART 149 | bool begin(void); 150 | 151 | void reset(void); 152 | void wakeup(void); 153 | 154 | // Generic PN532 functions 155 | bool SAMConfig(void); 156 | uint32_t getFirmwareVersion(void); 157 | bool sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, 158 | uint16_t timeout = 100); 159 | bool writeGPIO(uint8_t pinstate); 160 | uint8_t readGPIO(void); 161 | bool setPassiveActivationRetries(uint8_t maxRetries); 162 | 163 | // ISO14443A functions 164 | bool readPassiveTargetID( 165 | uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, 166 | uint16_t timeout = 0); // timeout 0 means no timeout - will block forever. 167 | bool startPassiveTargetIDDetection(uint8_t cardbaudrate); 168 | bool readDetectedPassiveTargetID(uint8_t *uid, uint8_t *uidLength); 169 | bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, 170 | uint8_t *responseLength); 171 | bool inListPassiveTarget(); 172 | uint8_t AsTarget(); 173 | uint8_t getDataTarget(uint8_t *cmd, uint8_t *cmdlen); 174 | uint8_t setDataTarget(uint8_t *cmd, uint8_t cmdlen); 175 | 176 | // Mifare Classic functions 177 | bool mifareclassic_IsFirstBlock(uint32_t uiBlock); 178 | bool mifareclassic_IsTrailerBlock(uint32_t uiBlock); 179 | uint8_t mifareclassic_AuthenticateBlock(uint8_t *uid, uint8_t uidLen, 180 | uint32_t blockNumber, 181 | uint8_t keyNumber, uint8_t *keyData); 182 | uint8_t mifareclassic_ReadDataBlock(uint8_t blockNumber, uint8_t *data); 183 | uint8_t mifareclassic_WriteDataBlock(uint8_t blockNumber, uint8_t *data); 184 | uint8_t mifareclassic_FormatNDEF(void); 185 | uint8_t mifareclassic_WriteNDEFURI(uint8_t sectorNumber, 186 | uint8_t uriIdentifier, const char *url); 187 | 188 | // Mifare Ultralight functions 189 | uint8_t mifareultralight_ReadPage(uint8_t page, uint8_t *buffer); 190 | uint8_t mifareultralight_WritePage(uint8_t page, uint8_t *data); 191 | 192 | // NTAG2xx functions 193 | uint8_t ntag2xx_ReadPage(uint8_t page, uint8_t *buffer); 194 | uint8_t ntag2xx_WritePage(uint8_t page, uint8_t *data); 195 | uint8_t ntag2xx_WriteNDEFURI(uint8_t uriIdentifier, char *url, 196 | uint8_t dataLen); 197 | 198 | // Help functions to display formatted text 199 | static void PrintHex(const byte *data, const uint32_t numBytes); 200 | static void PrintHexChar(const byte *pbtData, const uint32_t numBytes); 201 | 202 | private: 203 | int8_t _irq = -1, _reset = -1, _cs = -1; 204 | int8_t _uid[7]; // ISO14443A uid 205 | int8_t _uidLen; // uid len 206 | int8_t _key[6]; // Mifare Classic key 207 | int8_t _inListedTag; // Tg number of inlisted tag. 208 | 209 | // Low level communication functions that handle both SPI and I2C. 210 | void readdata(uint8_t *buff, uint8_t n); 211 | void writecommand(uint8_t *cmd, uint8_t cmdlen); 212 | bool isready(); 213 | bool waitready(uint16_t timeout); 214 | bool readack(); 215 | 216 | Adafruit_SPIDevice *spi_dev = NULL; 217 | Adafruit_I2CDevice *i2c_dev = NULL; 218 | HardwareSerial *ser_dev = NULL; 219 | }; 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit-PN532 [![Build Status](https://github.com/adafruit/Adafruit-PN532/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit-PN532/actions) 2 | 3 | 4 | This is a library for the Adafruit PN532 NFC/RFID breakout boards 5 | This library works with the Adafruit NFC breakout 6 | 7 | * https://www.adafruit.com/products/364 8 | 9 | Check out the links above for our tutorials and wiring diagrams 10 | These chips use I2C or SPI to communicate. 11 | 12 | # Dependencies 13 | * [Adafruit_BusIO](https://github.com/adafruit/Adafruit_BusIO) 14 | 15 | 16 | # Contributing 17 | 18 | Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit-PN532/blob/master/CODE_OF_CONDUCT.md>) 19 | before contributing to help this project stay welcoming. 20 | 21 | ## Documentation and doxygen 22 | Documentation is produced by doxygen. Contributions should include documentation for any new code added. 23 | 24 | Some examples of how to use doxygen can be found in these guide pages: 25 | 26 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen 27 | 28 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips 29 | 30 | ## Formatting and clang-format 31 | This library uses [`clang-format`](https://releases.llvm.org/download.html) to standardize the formatting of `.cpp` and `.h` files. 32 | Contributions should be formatted using `clang-format`: 33 | 34 | The `-i` flag will make the changes to the file. 35 | ```bash 36 | clang-format -i *.cpp *.h 37 | ``` 38 | If you prefer to make the changes yourself, running `clang-format` without the `-i` flag will print out a formatted version of the file. You can save this to a file and diff it against the original to see the changes. 39 | 40 | Note that the formatting output by `clang-format` is what the automated formatting checker will expect. Any diffs from this formatting will result in a failed build until they are addressed. Using the `-i` flag is highly recommended. 41 | 42 | ### clang-format resources 43 | * [Binary builds and source available on the LLVM downloads page](https://releases.llvm.org/download.html) 44 | * [Documentation and IDE integration](https://clang.llvm.org/docs/ClangFormat.html) 45 | Adafruit invests time and resources providing this open source code, 46 | please support Adafruit and open-source hardware by purchasing 47 | products from Adafruit! 48 | 49 | Written by Limor Fried/Ladyada & Kevin Townsend for Adafruit Industries. 50 | BSD license, check license.txt for more information 51 | All text above must be included in any redistribution 52 | 53 | To install, use the Arduino Library Manager and search for "Adafruit PN532" and install the library. Adafruit BusIO library is also required 54 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/.esp32.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-PN532/bf9f3f31961474fdbca23cb57d604c7f27269baf/examples/apduToBlackBerry/.esp32.test.skip -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | TargetEmulation 4 | 5 | 6 | 7 | 8 | 9 | net.rim.ejde.internal.builder.BlackBerryPreprocessBuilder 10 | 11 | 12 | 13 | 14 | net.rim.ejde.internal.builder.BlackBerryResourcesBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | 25 | net.rim.ejde.BlackBerryPreProcessNature 26 | net.rim.ejde.BlackBerryProjectCoreNature 27 | org.eclipse.jdt.core.javanature 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Fri Jun 22 00:02:13 EDT 2012 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.4 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore 12 | org.eclipse.jdt.core.compiler.source=1.3 13 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/BlackBerry_App_Descriptor.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/build.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/res/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-PN532/bf9f3f31961474fdbca23cb57d604c7f27269baf/examples/apduToBlackBerry/BlackBerry7/res/img/icon.png -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/src/mypackage/ColorMixer.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2011, 2012, 2013 Research In Motion Limited. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | **/ 16 | package mypackage; 17 | 18 | import net.rim.device.api.ui.Field; 19 | import net.rim.device.api.ui.Graphics; 20 | import net.rim.device.api.ui.TouchEvent; 21 | 22 | public class ColorMixer extends Field { 23 | private static final int[] colors = new int[] { 0xff0000, 0xff00, 0xff }; 24 | private int barGap = 5; 25 | 26 | private int barHeight = 64; 27 | private int color; 28 | private MyScreen owner; 29 | 30 | private double r, g, b; 31 | 32 | public ColorMixer(MyScreen owner) { 33 | this.owner = owner; 34 | } 35 | 36 | protected void layout(int width, int height) { 37 | setExtent(640, barHeight * 3 + barGap * 2); 38 | } 39 | 40 | protected void paint(Graphics graphics) { 41 | int barWidth = getWidth() - barHeight * 3 - barGap * 3; 42 | double[] values = new double[] { r, g, b }; 43 | 44 | // Draw color sliders 45 | for (int i = 0; i < 3; ++i) { 46 | int top = i * (barHeight + barGap); 47 | int toDraw = (int) (values[i] * barWidth + 0.5); 48 | graphics.setColor(0); 49 | graphics.fillRect(toDraw, top, barWidth - toDraw, barHeight); 50 | 51 | graphics.setColor(colors[i]); 52 | graphics.fillRect(0, top, toDraw, barHeight); 53 | 54 | graphics.setColor(0x7f7f7f); 55 | graphics.drawRect(0, top, barWidth, barHeight); 56 | } 57 | 58 | // Draw mixed down color 59 | int boxWidth = barHeight * 3 + barGap * 2; 60 | graphics.setColor(color); 61 | graphics.fillRect(getWidth() - 1 - boxWidth, 0, boxWidth, boxWidth); 62 | 63 | graphics.setColor(0x7f7f7f); 64 | graphics.drawRect(getWidth() - 1 - boxWidth, 0, boxWidth, boxWidth); 65 | } 66 | 67 | public void setColor(int color) { 68 | if (color != this.color) { 69 | this.color = color; 70 | r = ((color >> 16) & 0xff) / 255.0; 71 | g = ((color >> 8) & 0xff) / 255.0; 72 | b = (color & 0xff) / 255.0; 73 | invalidate(); 74 | } 75 | } 76 | 77 | private void setPart(int which, double value) { 78 | double source = which == 0 ? r : which == 1 ? g : b; 79 | if (value == source) { 80 | return; 81 | } 82 | int bv = (int) (value * 255 + 0.5); 83 | bv &= 0xff; 84 | if (which == 0) { 85 | r = value; 86 | color &= 0xffff; 87 | color |= bv << 16; 88 | } else if (which == 1) { 89 | g = value; 90 | color &= 0xff00ff; 91 | color |= bv << 8; 92 | } else { 93 | b = value; 94 | color &= 0xffff00; 95 | color |= bv; 96 | } 97 | owner.setColor(color); 98 | invalidate(); 99 | } 100 | 101 | private int touchTarget = -1; 102 | 103 | protected boolean touchEvent(TouchEvent message) { 104 | int event = message.getEvent(); 105 | 106 | int x = message.getX(1); 107 | int y = message.getY(1); 108 | 109 | int barWidth = getWidth() - barHeight * 3 - barGap * 3; 110 | 111 | if (event == TouchEvent.UP) { 112 | touchTarget = -1; 113 | return false; 114 | } else if (event == TouchEvent.DOWN) { 115 | if (y < -5 || y > getWidth() + 5) { 116 | return false; 117 | } 118 | 119 | if (x <= barWidth) { 120 | for (int i = 0; i < 3; ++i) { 121 | if (y < 0) { 122 | break; 123 | } 124 | if (y < barHeight) { 125 | touchTarget = i; 126 | break; 127 | } 128 | y -= barHeight; 129 | y -= barGap; 130 | } 131 | } else { 132 | return false; 133 | } 134 | } 135 | 136 | if (touchTarget == -1) { 137 | return false; 138 | } 139 | 140 | double newValue = 1.0 * x / barWidth; 141 | if (newValue < 0) { 142 | newValue = 0; 143 | } 144 | if (newValue > 1) { 145 | newValue = 1; 146 | } 147 | 148 | setPart(touchTarget, newValue); 149 | 150 | return true; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/src/mypackage/MyApp.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2011, 2012, 2013 Research In Motion Limited. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | **/ 16 | package mypackage; 17 | 18 | import net.rim.device.api.ui.UiApplication; 19 | 20 | /** 21 | * This class extends the UiApplication class, providing a 22 | * graphical user interface. 23 | */ 24 | public class MyApp extends UiApplication 25 | { 26 | /** 27 | * Entry point for application 28 | * @param args Command line arguments (not used) 29 | */ 30 | public static void main(String[] args) 31 | { 32 | // Create a new instance of the application and make the currently 33 | // running thread the application's event dispatch thread. 34 | MyApp theApp = new MyApp(); 35 | theApp.enterEventDispatcher(); 36 | } 37 | 38 | 39 | /** 40 | * Creates a new MyApp object 41 | */ 42 | public MyApp() 43 | { 44 | // Push a screen onto the UI stack for rendering. 45 | pushScreen(new MyScreen()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/src/mypackage/MyScreen.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2011, 2012, 2013 Research In Motion Limited. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | **/ 16 | package mypackage; 17 | 18 | import net.rim.device.api.io.nfc.NFCException; 19 | import net.rim.device.api.io.nfc.emulation.VirtualISO14443Part4TargetCallback; 20 | import net.rim.device.api.io.nfc.emulation.VirtualISO14443Part4TypeATarget; 21 | import net.rim.device.api.ui.Field; 22 | import net.rim.device.api.ui.FieldChangeListener; 23 | import net.rim.device.api.ui.component.CheckboxField; 24 | import net.rim.device.api.ui.component.LabelField; 25 | import net.rim.device.api.ui.container.MainScreen; 26 | import net.rim.device.api.ui.decor.BackgroundFactory; 27 | 28 | /** 29 | * A class extending the MainScreen class, which provides default standard 30 | * behavior for BlackBerry GUI applications. 31 | */ 32 | public final class MyScreen extends MainScreen implements 33 | VirtualISO14443Part4TargetCallback, FieldChangeListener { 34 | 35 | private int color = 0x7f7f7f; 36 | 37 | private boolean colorQueued = false; 38 | private CheckboxField colorQueueLocked; 39 | private VirtualISO14443Part4TypeATarget emulated; 40 | private ColorMixer mixer; 41 | 42 | private LabelField status; 43 | 44 | /** 45 | * Creates a new MyScreen object 46 | */ 47 | public MyScreen() { 48 | // Set the displayed title of the screen 49 | setTitle("Colour Control Setter"); 50 | setBackground(BackgroundFactory.createSolidBackground(0x3f3f3f)); 51 | 52 | add(new LabelField("")); 53 | add(colorQueueLocked = new CheckboxField("Lock Color", false)); 54 | colorQueueLocked.setChangeListener(this); 55 | 56 | add(mixer = new ColorMixer(this)); 57 | mixer.setColor(0x7f7f7f); 58 | 59 | add(status = new LabelField("")); 60 | 61 | try { 62 | emulated = new VirtualISO14443Part4TypeATarget(this, "10451045", 63 | null); 64 | log("created"); 65 | emulated.startEmulation(); 66 | log("emulating"); 67 | } catch (NFCException e) { 68 | log("Failed to listen"); 69 | status.setText(e.getClass().getName() + " " + e.getMessage()); 70 | e.printStackTrace(); 71 | } 72 | } 73 | 74 | // private TextField textField; 75 | 76 | public void fieldChanged(Field field, int context) { 77 | if (colorQueueLocked.getChecked()) { 78 | setColor(color); 79 | } else { 80 | colorQueued = false; 81 | status.setText(""); 82 | } 83 | } 84 | 85 | private boolean isColorQueueLocked() { 86 | return colorQueueLocked.getChecked(); 87 | } 88 | 89 | protected void log(String message) { 90 | System.out.println("SUPERDUPER: " + message); 91 | // textField.setText(textField.getText() + "\n" + message); 92 | } 93 | 94 | public void onVirtualTargetEvent(int targetEvent) { 95 | log("Target event: " + targetEvent); 96 | } 97 | 98 | public byte[] processCommand(byte[] command) { 99 | byte[] toReturn = processCommandInternal(command); 100 | String message = "[" + toString(command) + "," + toString(toReturn) 101 | + "]"; 102 | // status.setText(message); 103 | // log(message); 104 | return toReturn; 105 | } 106 | 107 | private byte[] processCommandInternal(byte[] command) { 108 | if (command == null) { 109 | return new byte[0]; 110 | } 111 | int messageType = command[0] & 0xff; 112 | switch (messageType) { 113 | case 1: 114 | if (command.length == 4) { 115 | int colorIn = (command[1] & 0xff) << 16; 116 | colorIn |= (command[2] & 0xff) << 8; 117 | colorIn |= (command[3] & 0xff); 118 | 119 | if (colorIn != color) { 120 | if (colorQueued) { 121 | 122 | byte[] toReturn = new byte[4]; 123 | toReturn[0] = 1; 124 | toReturn[1] = (byte) (color >> 16); 125 | toReturn[2] = (byte) (color >> 8); 126 | toReturn[3] = (byte) color; 127 | 128 | if (!isColorQueueLocked()) { 129 | colorQueued = false; 130 | status.setText(""); 131 | } 132 | 133 | return toReturn; 134 | } else { 135 | this.color = colorIn; 136 | mixer.setColor(colorIn); 137 | } 138 | } 139 | } 140 | break; 141 | } 142 | return new byte[] { 0 }; 143 | } 144 | 145 | public void setColor(int color) { 146 | colorQueued = true; 147 | this.color = color; 148 | status.setText("#" + toHex(color)); 149 | } 150 | 151 | private String toHex(int i) { 152 | String toReturn = "000000" + Integer.toString(i, 16); 153 | return toReturn.substring(toReturn.length() - 6); 154 | } 155 | 156 | private String toString(byte[] command) { 157 | String toReturn = ""; 158 | for (int i = 0; i < command.length; ++i) { 159 | toReturn += Integer.toString(command[i] & 0xff, 16) + " "; 160 | } 161 | return toReturn; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/apduToBlackBerry.ino: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2011, 2012, 2013 Research In Motion Limited. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | **/ 16 | #include 17 | #include 18 | #include 19 | 20 | // If using the breakout with SPI, define the pins for SPI communication. 21 | #define PN532_SCK (2) 22 | #define PN532_MOSI (3) 23 | #define PN532_SS (4) 24 | #define PN532_MISO (5) 25 | 26 | // If using the breakout or shield with I2C, define just the pins connected 27 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 28 | #define PN532_IRQ (2) 29 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 30 | 31 | // Uncomment just _one_ line below depending on how your breakout or shield 32 | // is connected to the Arduino: 33 | 34 | // Use this line for a breakout with a SPI connection: 35 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 36 | 37 | // Use this line for a breakout with a hardware SPI connection. Note that 38 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 39 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 40 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 41 | //Adafruit_PN532 nfc(PN532_SS); 42 | 43 | // Or use this line for a breakout or shield with an I2C connection: 44 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 45 | 46 | // PWM LED will be on the following PINs. 47 | #define R_PIN (9) 48 | #define G_PIN (10) 49 | #define B_PIN (11) 50 | 51 | // Initial values of RGB. 52 | uint8_t r = 0x00; 53 | uint8_t g = 0x00; 54 | uint8_t b = 0x7f; 55 | 56 | /** 57 | * Write the current color to the output pins. 58 | */ 59 | void showColor() { 60 | analogWrite(R_PIN,r); 61 | analogWrite(G_PIN,g); 62 | analogWrite(B_PIN,b); 63 | } 64 | 65 | 66 | void setup() { 67 | Serial.begin(115200); 68 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 69 | 70 | pinMode(R_PIN,OUTPUT); 71 | pinMode(G_PIN,OUTPUT); 72 | pinMode(B_PIN,OUTPUT); 73 | showColor(); 74 | 75 | nfc.begin(); 76 | 77 | uint32_t versiondata = nfc.getFirmwareVersion(); 78 | if (! versiondata) { 79 | Serial.println("Did not find the shield - locking up"); 80 | while (true) { 81 | } 82 | } 83 | 84 | Serial.print("Found chip PN5"); 85 | Serial.println((versiondata>>24) & 0xFF, HEX); 86 | Serial.print("Firmware ver. "); 87 | Serial.print((versiondata>>16) & 0xFF, DEC); 88 | Serial.print('.'); 89 | Serial.println((versiondata>>8) & 0xFF, DEC); 90 | 91 | nfc.begin(); 92 | } 93 | 94 | uint8_t message[4]; 95 | 96 | void loop(void) { 97 | uint8_t i; 98 | 99 | // Serial.println("Listening..."); 100 | if (nfc.inListPassiveTarget()) { 101 | // Serial.println("Something's there..."); 102 | while(true) { 103 | message[0] = 1; 104 | message[1] = r; 105 | message[2] = g; 106 | message[3] = b; 107 | uint8_t responseLength = sizeof(message); 108 | if (nfc.inDataExchange(message,sizeof(message),message,&responseLength)) { 109 | uint8_t command = message[0]; 110 | switch(command) { 111 | case 0: 112 | // NOP 113 | break; 114 | case 1: 115 | if (responseLength==4) { 116 | r = message[1]; 117 | g = message[2]; 118 | b = message[3]; 119 | showColor(); 120 | //Serial.print("Read a color: "); 121 | //for (i=0; i<3; ++i) { 122 | // Serial.print(message[i+1],HEX); 123 | // Serial.print(' '); 124 | //} 125 | //Serial.println(); 126 | } 127 | else { 128 | //Serial.println("Doesn't seem to be a color..."); 129 | } 130 | break; 131 | default: 132 | //Serial.print("Unknown command "); 133 | //Serial.println(message[0]); 134 | ; 135 | } 136 | delay(10); 137 | } 138 | else { 139 | //Serial.println("It's gone..."); 140 | break; 141 | } 142 | } 143 | } 144 | else { 145 | //Serial.print("Trying again..."); 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /examples/iso14443a_uid/iso14443a_uid.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file iso14443a_uid.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | This example will attempt to connect to an ISO14443A 8 | card or tag and retrieve some basic information about it 9 | that can be used to determine what type of card it is. 10 | 11 | Note that you need the baud rate to be 115200 because we need to print 12 | out the data and read from the card at the same time! 13 | 14 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 15 | This library works with the Adafruit NFC breakout 16 | ----> https://www.adafruit.com/products/364 17 | 18 | Check out the links above for our tutorials and wiring diagrams 19 | These chips use SPI or I2C to communicate. 20 | 21 | Adafruit invests time and resources providing this open source code, 22 | please support Adafruit and open-source hardware by purchasing 23 | products from Adafruit! 24 | 25 | */ 26 | /**************************************************************************/ 27 | #include 28 | #include 29 | #include 30 | 31 | // If using the breakout with SPI, define the pins for SPI communication. 32 | #define PN532_SCK (2) 33 | #define PN532_MOSI (3) 34 | #define PN532_SS (4) 35 | #define PN532_MISO (5) 36 | 37 | // If using the breakout or shield with I2C, define just the pins connected 38 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 39 | #define PN532_IRQ (2) 40 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 41 | 42 | // Uncomment just _one_ line below depending on how your breakout or shield 43 | // is connected to the Arduino: 44 | 45 | // Use this line for a breakout with a SPI connection: 46 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 47 | 48 | // Use this line for a breakout with a hardware SPI connection. Note that 49 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 50 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 51 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 52 | //Adafruit_PN532 nfc(PN532_SS); 53 | 54 | // Or use this line for a breakout or shield with an I2C connection: 55 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 56 | 57 | void setup(void) { 58 | Serial.begin(115200); 59 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 60 | Serial.println("Hello!"); 61 | 62 | nfc.begin(); 63 | 64 | uint32_t versiondata = nfc.getFirmwareVersion(); 65 | if (! versiondata) { 66 | Serial.print("Didn't find PN53x board"); 67 | while (1); // halt 68 | } 69 | 70 | // Got ok data, print it out! 71 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 72 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 73 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 74 | 75 | // Set the max number of retry attempts to read from a card 76 | // This prevents us from waiting forever for a card, which is 77 | // the default behaviour of the PN532. 78 | nfc.setPassiveActivationRetries(0xFF); 79 | 80 | Serial.println("Waiting for an ISO14443A card"); 81 | } 82 | 83 | void loop(void) { 84 | boolean success; 85 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 86 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 87 | 88 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 89 | // 'uid' will be populated with the UID, and uidLength will indicate 90 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 91 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); 92 | 93 | if (success) { 94 | Serial.println("Found a card!"); 95 | Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 96 | Serial.print("UID Value: "); 97 | for (uint8_t i=0; i < uidLength; i++) 98 | { 99 | Serial.print(" 0x");Serial.print(uid[i], HEX); 100 | } 101 | Serial.println(""); 102 | // Wait 1 second before continuing 103 | delay(1000); 104 | } 105 | else 106 | { 107 | // PN532 probably timed out waiting for a card 108 | Serial.println("Timed out waiting for a card"); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/iso14443as_target/iso14443as_target.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file iso14443as_target.pde 4 | @original Adafruit Industries 5 | @modified Salvador Mendoza(@Netxing) 6 | @license BSD (see license.txt) 7 | 8 | This example will attempt to mimic an ISO14443A smart card 9 | and retrieve some basic information from a PoS or terminal, 10 | this can be used to establish a communication process. 11 | 12 | Note that you need the baud rate to be 115200 because we need to print 13 | out the data and read from the card at the same time! 14 | 15 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 16 | This library works with the Adafruit NFC breakout 17 | ----> https://www.adafruit.com/products/364 18 | 19 | Check out the links above for our tutorials and wiring diagrams 20 | These chips use SPI or I2C to communicate. 21 | 22 | Adafruit invests time and resources providing this open source code, 23 | please support Adafruit and open-source hardware by purchasing 24 | products from Adafruit! 25 | 26 | */ 27 | /**************************************************************************/ 28 | #include 29 | #include 30 | #include 31 | 32 | // If using the breakout with SPI, define the pins for SPI communication. 33 | #define PN532_SCK (2) 34 | #define PN532_MOSI (3) 35 | #define PN532_SS (4) 36 | #define PN532_MISO (5) 37 | 38 | // If using the breakout or shield with I2C, define just the pins connected 39 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 40 | #define PN532_IRQ (2) 41 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 42 | 43 | // Uncomment just _one_ line below depending on how your breakout or shield 44 | // is connected to the Arduino: 45 | 46 | // Use this line for a breakout with a SPI connection: 47 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 48 | 49 | // Use this line for a breakout with a hardware SPI connection. Note that 50 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 51 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 52 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 53 | //Adafruit_PN532 nfc(PN532_SS); 54 | 55 | // Or use this line for a breakout or shield with an I2C connection: 56 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 57 | 58 | void setup(void) { 59 | Serial.begin(115200); 60 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 61 | 62 | Serial.println("Hello!"); 63 | 64 | nfc.begin(); 65 | 66 | uint32_t versiondata = nfc.getFirmwareVersion(); 67 | if (! versiondata) { 68 | Serial.print("Didn't find PN53x board"); 69 | while (1); // halt 70 | } 71 | 72 | // Got ok data, print it out! 73 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 74 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 75 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 76 | 77 | // Set the max number of retry attempts to read from a card 78 | // This prevents us from waiting forever for a card, which is 79 | // the default behaviour of the PN532. 80 | nfc.setPassiveActivationRetries(0xFF); 81 | 82 | Serial.println("As Target... Approach the NFC PN532 Board to a PoS or terminal!"); 83 | delay(200); 84 | } 85 | 86 | void loop(void) { 87 | uint8_t apdubuffer[255] = {}, apdulen = 0; 88 | uint8_t ppse[] = {0x8E, 0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00}; 89 | nfc.AsTarget(); 90 | (void)nfc.getDataTarget(apdubuffer, &apdulen); //Read initial APDU 91 | if (apdulen>0){ 92 | for (uint8_t i = 0; i < apdulen; i++){ 93 | Serial.print(" 0x"); Serial.print(apdubuffer[i], HEX); 94 | } 95 | Serial.println(""); 96 | } 97 | nfc.setDataTarget(ppse, sizeof(ppse)); //Mimic a smart card response with a PPSE APDU 98 | nfc.getDataTarget(apdubuffer, &apdulen); //Read respond from the PoS or Terminal 99 | if (apdulen>0){ 100 | for (uint8_t i = 0; i < apdulen; i++){ 101 | Serial.print(" 0x"); Serial.print(apdubuffer[i], HEX); 102 | } 103 | Serial.println(""); 104 | } 105 | delay(1000); 106 | } 107 | -------------------------------------------------------------------------------- /examples/mifareclassic_formatndef/mifareclassic_formatndef.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file mifareclassic_formatndef.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | This example attempts to format a clean Mifare Classic 1K card as 8 | an NFC Forum tag (to store NDEF messages that can be read by any 9 | NFC enabled Android phone, etc.) 10 | 11 | Note that you need the baud rate to be 115200 because we need to print 12 | out the data and read from the card at the same time! 13 | 14 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 15 | This library works with the Adafruit NFC Shield 16 | ----> https://www.adafruit.com/products/789 17 | 18 | Check out the links above for our tutorials and wiring diagrams 19 | These chips use SPI or I2C to communicate 20 | 21 | Adafruit invests time and resources providing this open source code, 22 | please support Adafruit and open-source hardware by purchasing 23 | products from Adafruit! 24 | 25 | */ 26 | /**************************************************************************/ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | // If using the breakout with SPI, define the pins for SPI communication. 33 | #define PN532_SCK (2) 34 | #define PN532_MOSI (3) 35 | #define PN532_SS (4) 36 | #define PN532_MISO (5) 37 | 38 | // If using the breakout or shield with I2C, define just the pins connected 39 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 40 | #define PN532_IRQ (2) 41 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 42 | 43 | // Uncomment just _one_ line below depending on how your breakout or shield 44 | // is connected to the Arduino: 45 | 46 | // Use this line for a breakout with a SPI connection: 47 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 48 | 49 | // Use this line for a breakout with a hardware SPI connection. Note that 50 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 51 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 52 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 53 | //Adafruit_PN532 nfc(PN532_SS); 54 | 55 | // Or use this line for a breakout or shield with an I2C connection: 56 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 57 | 58 | /* 59 | We can encode many different kinds of pointers to the card, 60 | from a URL, to an Email address, to a phone number, and many more 61 | check the library header .h file to see the large # of supported 62 | prefixes! 63 | */ 64 | // For a http://www. url: 65 | const char * url = "adafruit.com"; 66 | uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT; 67 | 68 | // for an email address 69 | //const char * url = "mail@example.com"; 70 | //uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO; 71 | 72 | // for a phone number 73 | //const char * url = "+1 212 555 1212"; 74 | //uint8_t ndefprefix = NDEF_URIPREFIX_TEL; 75 | 76 | 77 | void setup(void) { 78 | Serial.begin(115200); 79 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 80 | 81 | Serial.println("Looking for PN532..."); 82 | 83 | nfc.begin(); 84 | 85 | uint32_t versiondata = nfc.getFirmwareVersion(); 86 | if (! versiondata) { 87 | Serial.print("Didn't find PN53x board"); 88 | while (1); // halt 89 | } 90 | 91 | // Got ok data, print it out! 92 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 93 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 94 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 95 | } 96 | 97 | void loop(void) { 98 | uint8_t success; // Flag to check if there was an error with the PN532 99 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 100 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 101 | 102 | // Use the default key 103 | uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 104 | 105 | Serial.println(""); 106 | Serial.println("PLEASE NOTE: Formatting your card for NDEF records will change the"); 107 | Serial.println("authentication keys. To reformat your NDEF tag as a clean Mifare"); 108 | Serial.println("Classic tag, use the mifareclassic_ndeftoclassic example!"); 109 | Serial.println(""); 110 | Serial.println("Place your Mifare Classic card on the reader to format with NDEF"); 111 | Serial.println("and press any key to continue ..."); 112 | // Wait for user input before proceeding 113 | while (!Serial.available()); 114 | // a key was pressed1 115 | while (Serial.available()) Serial.read(); 116 | 117 | // Wait for an ISO14443A type card (Mifare, etc.). When one is found 118 | // 'uid' will be populated with the UID, and uidLength will indicate 119 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 120 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 121 | 122 | if (success) 123 | { 124 | // Display some basic information about the card 125 | Serial.println("Found an ISO14443A card"); 126 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 127 | Serial.print(" UID Value: "); 128 | nfc.PrintHex(uid, uidLength); 129 | Serial.println(""); 130 | 131 | // Make sure this is a Mifare Classic card 132 | if (uidLength != 4) 133 | { 134 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 135 | return; 136 | } 137 | 138 | // We probably have a Mifare Classic card ... 139 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 140 | 141 | // Try to format the card for NDEF data 142 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 0, 0, keya); 143 | if (!success) 144 | { 145 | Serial.println("Unable to authenticate block 0 to enable card formatting!"); 146 | return; 147 | } 148 | success = nfc.mifareclassic_FormatNDEF(); 149 | if (!success) 150 | { 151 | Serial.println("Unable to format the card for NDEF"); 152 | return; 153 | } 154 | 155 | Serial.println("Card has been formatted for NDEF data using MAD1"); 156 | 157 | // Try to authenticate block 4 (first block of sector 1) using our key 158 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keya); 159 | 160 | // Make sure the authentification process didn't fail 161 | if (!success) 162 | { 163 | Serial.println("Authentication failed."); 164 | return; 165 | } 166 | 167 | // Try to write a URL 168 | Serial.println("Writing URI to sector 1 as an NDEF Message"); 169 | 170 | // Authenticated seems to have worked 171 | // Try to write an NDEF record to sector 1 172 | // Use 0x01 for the URI Identifier Code to prepend "http://www." 173 | // to the url (and save some space). For information on URI ID Codes 174 | // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef 175 | if (strlen(url) > 38) 176 | { 177 | // The length is also checked in the WriteNDEFURI function, but lets 178 | // warn users here just in case they change the value and it's bigger 179 | // than it should be 180 | Serial.println("URI is too long ... must be less than 38 characters long"); 181 | return; 182 | } 183 | 184 | // URI is within size limits ... write it to the card and report success/failure 185 | success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url); 186 | if (success) 187 | { 188 | Serial.println("NDEF URI Record written to sector 1"); 189 | } 190 | else 191 | { 192 | Serial.println("NDEF Record creation failed! :("); 193 | } 194 | } 195 | 196 | // Wait a bit before trying again 197 | Serial.println("\n\nDone!"); 198 | delay(1000); 199 | Serial.flush(); 200 | while(Serial.available()) Serial.read(); 201 | } 202 | -------------------------------------------------------------------------------- /examples/mifareclassic_memdump/mifareclassic_memdump.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file mifareclassic_memdump.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | This example attempts to dump the contents of a Mifare Classic 1K card 8 | 9 | Note that you need the baud rate to be 115200 because we need to print 10 | out the data and read from the card at the same time! 11 | 12 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 13 | This library works with the Adafruit NFC breakout 14 | ----> https://www.adafruit.com/products/364 15 | 16 | Check out the links above for our tutorials and wiring diagrams 17 | These chips use SPI or I2C to communicate 18 | 19 | Adafruit invests time and resources providing this open source code, 20 | please support Adafruit and open-source hardware by purchasing 21 | products from Adafruit! 22 | 23 | */ 24 | /**************************************************************************/ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | // If using the breakout with SPI, define the pins for SPI communication. 31 | #define PN532_SCK (2) 32 | #define PN532_MOSI (3) 33 | #define PN532_SS (4) 34 | #define PN532_MISO (5) 35 | 36 | // If using the breakout or shield with I2C, define just the pins connected 37 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 38 | #define PN532_IRQ (2) 39 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 40 | 41 | // Uncomment just _one_ line below depending on how your breakout or shield 42 | // is connected to the Arduino: 43 | 44 | // Use this line for a breakout with a SPI connection: 45 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 46 | 47 | // Use this line for a breakout with a hardware SPI connection. Note that 48 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 49 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 50 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 51 | //Adafruit_PN532 nfc(PN532_SS); 52 | 53 | // Or use this line for a breakout or shield with an I2C connection: 54 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 55 | 56 | void setup(void) { 57 | // has to be fast to dump the entire memory contents! 58 | Serial.begin(115200); 59 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 60 | 61 | Serial.println("Looking for PN532..."); 62 | 63 | nfc.begin(); 64 | 65 | uint32_t versiondata = nfc.getFirmwareVersion(); 66 | if (! versiondata) { 67 | Serial.print("Didn't find PN53x board"); 68 | while (1); // halt 69 | } 70 | // Got ok data, print it out! 71 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 72 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 73 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 74 | 75 | Serial.println("Waiting for an ISO14443A Card ..."); 76 | } 77 | 78 | 79 | void loop(void) { 80 | uint8_t success; // Flag to check if there was an error with the PN532 81 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 82 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 83 | uint8_t currentblock; // Counter to keep track of which block we're on 84 | bool authenticated = false; // Flag to indicate if the sector is authenticated 85 | uint8_t data[16]; // Array to store block data during reads 86 | 87 | // Keyb on NDEF and Mifare Classic should be the same 88 | uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 89 | 90 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 91 | // 'uid' will be populated with the UID, and uidLength will indicate 92 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 93 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 94 | 95 | if (success) { 96 | // Display some basic information about the card 97 | Serial.println("Found an ISO14443A card"); 98 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 99 | Serial.print(" UID Value: "); 100 | nfc.PrintHex(uid, uidLength); 101 | Serial.println(""); 102 | 103 | if (uidLength == 4) 104 | { 105 | // We probably have a Mifare Classic card ... 106 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 107 | 108 | // Now we try to go through all 16 sectors (each having 4 blocks) 109 | // authenticating each sector, and then dumping the blocks 110 | for (currentblock = 0; currentblock < 64; currentblock++) 111 | { 112 | // Check if this is a new block so that we can reauthenticate 113 | if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false; 114 | 115 | // If the sector hasn't been authenticated, do so first 116 | if (!authenticated) 117 | { 118 | // Starting of a new sector ... try to to authenticate 119 | Serial.print("------------------------Sector ");Serial.print(currentblock/4, DEC);Serial.println("-------------------------"); 120 | if (currentblock == 0) 121 | { 122 | // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!) 123 | // or 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 for NDEF formatted cards using key a, 124 | // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF) 125 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal); 126 | } 127 | else 128 | { 129 | // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!) 130 | // or 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 for NDEF formatted cards using key a, 131 | // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF) 132 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal); 133 | } 134 | if (success) 135 | { 136 | authenticated = true; 137 | } 138 | else 139 | { 140 | Serial.println("Authentication error"); 141 | } 142 | } 143 | // If we're still not authenticated just skip the block 144 | if (!authenticated) 145 | { 146 | Serial.print("Block ");Serial.print(currentblock, DEC);Serial.println(" unable to authenticate"); 147 | } 148 | else 149 | { 150 | // Authenticated ... we should be able to read the block now 151 | // Dump the data into the 'data' array 152 | success = nfc.mifareclassic_ReadDataBlock(currentblock, data); 153 | if (success) 154 | { 155 | // Read successful 156 | Serial.print("Block ");Serial.print(currentblock, DEC); 157 | if (currentblock < 10) 158 | { 159 | Serial.print(" "); 160 | } 161 | else 162 | { 163 | Serial.print(" "); 164 | } 165 | // Dump the raw data 166 | nfc.PrintHexChar(data, 16); 167 | } 168 | else 169 | { 170 | // Oops ... something happened 171 | Serial.print("Block ");Serial.print(currentblock, DEC); 172 | Serial.println(" unable to read this block"); 173 | } 174 | } 175 | } 176 | } 177 | else 178 | { 179 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 180 | } 181 | } 182 | // Wait a bit before trying again 183 | Serial.println("\n\nSend a character to run the mem dumper again!"); 184 | Serial.flush(); 185 | while (!Serial.available()); 186 | while (Serial.available()) { 187 | Serial.read(); 188 | } 189 | Serial.flush(); 190 | } 191 | -------------------------------------------------------------------------------- /examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file mifareclassic_ndeftoclassic.pde 4 | @author KTOWN (Adafruit Industries) 5 | @license BSD (see license.txt) 6 | 7 | This examples attempts to take a Mifare Classic 1K card that has been 8 | formatted for NDEF messages using mifareclassic_formatndef, and resets 9 | the authentication keys back to the Mifare Classic defaults 10 | 11 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 12 | This library works with the Adafruit NFC Shield 13 | ----> https://www.adafruit.com/products/789 14 | 15 | Check out the links above for our tutorials and wiring diagrams 16 | These chips use SPI or I2C to communicate 17 | 18 | Adafruit invests time and resources providing this open source code, 19 | please support Adafruit and open-source hardware by purchasing 20 | products from Adafruit! 21 | 22 | */ 23 | /**************************************************************************/ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | // If using the breakout with SPI, define the pins for SPI communication. 30 | #define PN532_SCK (2) 31 | #define PN532_MOSI (3) 32 | #define PN532_SS (4) 33 | #define PN532_MISO (5) 34 | 35 | // If using the breakout or shield with I2C, define just the pins connected 36 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 37 | #define PN532_IRQ (2) 38 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 39 | 40 | // Uncomment just _one_ line below depending on how your breakout or shield 41 | // is connected to the Arduino: 42 | 43 | // Use this line for a breakout with a SPI connection: 44 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 45 | 46 | // Use this line for a breakout with a hardware SPI connection. Note that 47 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 48 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 49 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 50 | //Adafruit_PN532 nfc(PN532_SS); 51 | 52 | // Or use this line for a breakout or shield with an I2C connection: 53 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 54 | 55 | #define NR_SHORTSECTOR (32) // Number of short sectors on Mifare 1K/4K 56 | #define NR_LONGSECTOR (8) // Number of long sectors on Mifare 4K 57 | #define NR_BLOCK_OF_SHORTSECTOR (4) // Number of blocks in a short sector 58 | #define NR_BLOCK_OF_LONGSECTOR (16) // Number of blocks in a long sector 59 | 60 | // Determine the sector trailer block based on sector number 61 | #define BLOCK_NUMBER_OF_SECTOR_TRAILER(sector) (((sector)>24) & 0xFF, HEX); 90 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 91 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 92 | } 93 | 94 | void loop(void) { 95 | uint8_t success; // Flag to check if there was an error with the PN532 96 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 97 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 98 | uint8_t blockBuffer[16]; // Buffer to store block contents 99 | uint8_t blankAccessBits[3] = { 0xff, 0x07, 0x80 }; 100 | uint8_t idx = 0; 101 | uint8_t numOfSector = 16; // Assume Mifare Classic 1K for now (16 4-block sectors) 102 | 103 | Serial.println("Place your NDEF formatted Mifare Classic 1K card on the reader"); 104 | Serial.println("and press any key to continue ..."); 105 | 106 | // Wait for user input before proceeding 107 | while (!Serial.available()); 108 | while (Serial.available()) Serial.read(); 109 | 110 | // Wait for an ISO14443A type card (Mifare, etc.). When one is found 111 | // 'uid' will be populated with the UID, and uidLength will indicate 112 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 113 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 114 | 115 | if (success) 116 | { 117 | // We seem to have a tag ... 118 | // Display some basic information about it 119 | Serial.println("Found an ISO14443A card/tag"); 120 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 121 | Serial.print(" UID Value: "); 122 | nfc.PrintHex(uid, uidLength); 123 | Serial.println(""); 124 | 125 | // Make sure this is a Mifare Classic card 126 | if (uidLength != 4) 127 | { 128 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 129 | return; 130 | } 131 | 132 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 133 | Serial.println(""); 134 | Serial.println("Reformatting card for Mifare Classic (please don't touch it!) ... "); 135 | 136 | // Now run through the card sector by sector 137 | for (idx = 0; idx < numOfSector; idx++) 138 | { 139 | // Step 1: Authenticate the current sector using key B 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 140 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), 1, (uint8_t *)KEY_DEFAULT_KEYAB); 141 | if (!success) 142 | { 143 | Serial.print("Authentication failed for sector "); Serial.println(numOfSector); 144 | return; 145 | } 146 | 147 | // Step 2: Write to the other blocks 148 | if (idx == 16) 149 | { 150 | memset(blockBuffer, 0, sizeof(blockBuffer)); 151 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer))) 152 | { 153 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 154 | return; 155 | } 156 | } 157 | if ((idx == 0) || (idx == 16)) 158 | { 159 | memset(blockBuffer, 0, sizeof(blockBuffer)); 160 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer))) 161 | { 162 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 163 | return; 164 | } 165 | } 166 | else 167 | { 168 | memset(blockBuffer, 0, sizeof(blockBuffer)); 169 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer))) 170 | { 171 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 172 | return; 173 | } 174 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer))) 175 | { 176 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 177 | return; 178 | } 179 | } 180 | memset(blockBuffer, 0, sizeof(blockBuffer)); 181 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, blockBuffer))) 182 | { 183 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 184 | return; 185 | } 186 | 187 | // Step 3: Reset both keys to 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 188 | memcpy(blockBuffer, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB)); 189 | memcpy(blockBuffer + 6, blankAccessBits, sizeof(blankAccessBits)); 190 | blockBuffer[9] = 0x69; 191 | memcpy(blockBuffer + 10, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB)); 192 | 193 | // Step 4: Write the trailer block 194 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), blockBuffer))) 195 | { 196 | Serial.print("Unable to write trailer block of sector "); Serial.println(numOfSector); 197 | return; 198 | } 199 | } 200 | } 201 | 202 | // Wait a bit before trying again 203 | Serial.println("\n\nDone!"); 204 | delay(1000); 205 | Serial.flush(); 206 | while(Serial.available()) Serial.read(); 207 | } 208 | -------------------------------------------------------------------------------- /examples/mifareclassic_updatendef/mifareclassic_updatendef.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file mifareclassic_updatendef.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | Updates a sector that is already formatted for NDEF (using 8 | mifareclassic_formatndef.pde for example), inserting a new url 9 | 10 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 11 | This library works with the Adafruit NFC Shield 12 | ----> https://www.adafruit.com/products/789 13 | 14 | Check out the links above for our tutorials and wiring diagrams 15 | These chips use SPI or I2C to communicate 16 | 17 | Adafruit invests time and resources providing this open source code, 18 | please support Adafruit and open-source hardware by purchasing 19 | products from Adafruit! 20 | 21 | */ 22 | /**************************************************************************/ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | // If using the breakout with SPI, define the pins for SPI communication. 29 | #define PN532_SCK (2) 30 | #define PN532_MOSI (3) 31 | #define PN532_SS (4) 32 | #define PN532_MISO (5) 33 | 34 | // If using the breakout or shield with I2C, define just the pins connected 35 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 36 | #define PN532_IRQ (2) 37 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 38 | 39 | // Uncomment just _one_ line below depending on how your breakout or shield 40 | // is connected to the Arduino: 41 | 42 | // Use this line for a breakout with a SPI connection: 43 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 44 | 45 | // Use this line for a breakout with a hardware SPI connection. Note that 46 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 47 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 48 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 49 | //Adafruit_PN532 nfc(PN532_SS); 50 | 51 | // Or use this line for a breakout or shield with an I2C connection: 52 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 53 | 54 | /* 55 | We can encode many different kinds of pointers to the card, 56 | from a URL, to an Email address, to a phone number, and many more 57 | check the library header .h file to see the large # of supported 58 | prefixes! 59 | */ 60 | // For a http://www. url: 61 | const char * url = "adafruit.com/blog/"; 62 | uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT; 63 | 64 | // for an email address 65 | //const char * url = "mail@example.com"; 66 | //uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO; 67 | 68 | // for a phone number 69 | //const char * url = "+1 212 555 1212"; 70 | //uint8_t ndefprefix = NDEF_URIPREFIX_TEL; 71 | 72 | 73 | void setup(void) { 74 | Serial.begin(115200); 75 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 76 | 77 | Serial.println("Looking for PN532..."); 78 | 79 | nfc.begin(); 80 | 81 | uint32_t versiondata = nfc.getFirmwareVersion(); 82 | if (! versiondata) { 83 | Serial.print("Didn't find PN53x board"); 84 | while (1); // halt 85 | } 86 | 87 | // Got ok data, print it out! 88 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 89 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 90 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 91 | } 92 | 93 | void loop(void) { 94 | uint8_t success; // Flag to check if there was an error with the PN532 95 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 96 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 97 | 98 | // Use the default NDEF keys (these would have have set by mifareclassic_formatndef.pde!) 99 | uint8_t keyb[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }; 100 | 101 | Serial.println("Place your NDEF formatted Mifare Classic card on the reader to update the"); 102 | Serial.println("NDEF record and press any key to continue ..."); 103 | // Wait for user input before proceeding 104 | while (!Serial.available()); 105 | // a key was pressed1 106 | while (Serial.available()) Serial.read(); 107 | 108 | // Wait for an ISO14443A type card (Mifare, etc.). When one is found 109 | // 'uid' will be populated with the UID, and uidLength will indicate 110 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 111 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 112 | 113 | if (success) 114 | { 115 | // Display some basic information about the card 116 | Serial.println("Found an ISO14443A card"); 117 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 118 | Serial.print(" UID Value: "); 119 | nfc.PrintHex(uid, uidLength); 120 | Serial.println(""); 121 | 122 | // Make sure this is a Mifare Classic card 123 | if (uidLength != 4) 124 | { 125 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 126 | return; 127 | } 128 | 129 | // We probably have a Mifare Classic card ... 130 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 131 | 132 | // Check if this is an NDEF card (using first block of sector 1 from mifareclassic_formatndef.pde) 133 | // Must authenticate on the first key using 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 134 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keyb); 135 | if (!success) 136 | { 137 | Serial.println("Unable to authenticate block 4 ... is this card NDEF formatted?"); 138 | return; 139 | } 140 | 141 | Serial.println("Authentication succeeded (seems to be an NDEF/NFC Forum tag) ..."); 142 | 143 | // Authenticated seems to have worked 144 | // Try to write an NDEF record to sector 1 145 | // Use 0x01 for the URI Identifier Code to prepend "http://www." 146 | // to the url (and save some space). For information on URI ID Codes 147 | // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef 148 | if (strlen(url) > 38) 149 | { 150 | // The length is also checked in the WriteNDEFURI function, but lets 151 | // warn users here just in case they change the value and it's bigger 152 | // than it should be 153 | Serial.println("URI is too long ... must be less than 38 characters!"); 154 | return; 155 | } 156 | 157 | Serial.println("Updating sector 1 with URI as NDEF Message"); 158 | 159 | // URI is within size limits ... write it to the card and report success/failure 160 | success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url); 161 | if (success) 162 | { 163 | Serial.println("NDEF URI Record written to sector 1"); 164 | Serial.println(""); 165 | } 166 | else 167 | { 168 | Serial.println("NDEF Record creation failed! :("); 169 | } 170 | } 171 | 172 | // Wait a bit before trying again 173 | Serial.println("\n\nDone!"); 174 | delay(1000); 175 | Serial.flush(); 176 | while(Serial.available()) Serial.read(); 177 | } 178 | -------------------------------------------------------------------------------- /examples/ntag2xx_erase/ntag2xx_erase.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file ntag2xx_erase.pde 4 | @author KTOWN (Adafruit Industries) 5 | @license BSD (see license.txt) 6 | 7 | This example will wait for any NTAG203 or NTAG213 card or tag, 8 | and will attempt to erase the user data section of the card (setting 9 | all user bytes to 0x00) 10 | 11 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 12 | This library works with the Adafruit NFC breakout 13 | ----> https://www.adafruit.com/products/364 14 | 15 | Check out the links above for our tutorials and wiring diagrams 16 | These chips use SPI or I2C to communicate. 17 | 18 | Adafruit invests time and resources providing this open source code, 19 | please support Adafruit and open-source hardware by purchasing 20 | products from Adafruit! 21 | */ 22 | /**************************************************************************/ 23 | #include 24 | #include 25 | #include 26 | 27 | // If using the breakout with SPI, define the pins for SPI communication. 28 | #define PN532_SCK (2) 29 | #define PN532_MOSI (3) 30 | #define PN532_SS (4) 31 | #define PN532_MISO (5) 32 | 33 | // If using the breakout or shield with I2C, define just the pins connected 34 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 35 | #define PN532_IRQ (2) 36 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 37 | 38 | // Uncomment just _one_ line below depending on how your breakout or shield 39 | // is connected to the Arduino: 40 | 41 | // Use this line for a breakout with a software SPI connection (recommended): 42 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 43 | 44 | // Use this line for a breakout with a hardware SPI connection. Note that 45 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 46 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 47 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 48 | //Adafruit_PN532 nfc(PN532_SS); 49 | 50 | // Or use this line for a breakout or shield with an I2C connection: 51 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 52 | 53 | void setup(void) { 54 | Serial.begin(115200); 55 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 56 | 57 | Serial.println("Hello!"); 58 | 59 | nfc.begin(); 60 | 61 | uint32_t versiondata = nfc.getFirmwareVersion(); 62 | if (! versiondata) { 63 | Serial.print("Didn't find PN53x board"); 64 | while (1); // halt 65 | } 66 | // Got ok data, print it out! 67 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 68 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 69 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 70 | 71 | Serial.println("Waiting for an ISO14443A Card ..."); 72 | } 73 | 74 | void loop(void) { 75 | uint8_t success; 76 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 77 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 78 | 79 | // Wait for an NTAG203 card. When one is found 'uid' will be populated with 80 | // the UID, and uidLength will indicate the size of the UUID (normally 7) 81 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 82 | 83 | if (success) { 84 | // Display some basic information about the card 85 | Serial.println("Found an ISO14443A card"); 86 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 87 | Serial.print(" UID Value: "); 88 | nfc.PrintHex(uid, uidLength); 89 | Serial.println(""); 90 | 91 | if (uidLength == 7) 92 | { 93 | uint8_t data[32]; 94 | 95 | // We probably have an NTAG2xx card (though it could be Ultralight as well) 96 | Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); 97 | 98 | // NTAG2x3 cards have 39*4 bytes of user pages (156 user bytes), 99 | // starting at page 4 ... larger cards just add pages to the end of 100 | // this range: 101 | 102 | // See: http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf 103 | 104 | // TAG Type PAGES USER START USER STOP 105 | // -------- ----- ---------- --------- 106 | // NTAG 203 42 4 39 107 | // NTAG 213 45 4 39 108 | // NTAG 215 135 4 129 109 | // NTAG 216 231 4 225 110 | 111 | Serial.println(""); 112 | Serial.println("Writing 0x00 0x00 0x00 0x00 to pages 4..39"); 113 | Serial.println(""); 114 | for (uint8_t i = 4; i < 39; i++) 115 | { 116 | memset(data, 0, 4); 117 | success = nfc.ntag2xx_WritePage(i, data); 118 | 119 | // Display the current page number 120 | Serial.print("Page "); 121 | if (i < 10) 122 | { 123 | Serial.print("0"); 124 | Serial.print(i); 125 | } 126 | else 127 | { 128 | Serial.print(i); 129 | } 130 | Serial.print(": "); 131 | 132 | // Display the results, depending on 'success' 133 | if (success) 134 | { 135 | Serial.println("Erased"); 136 | } 137 | else 138 | { 139 | Serial.println("Unable to write to the requested page!"); 140 | } 141 | } 142 | } 143 | else 144 | { 145 | Serial.println("This doesn't seem to be an NTAG203 tag (UUID length != 7 bytes)!"); 146 | } 147 | 148 | // Wait a bit before trying again 149 | Serial.println("\n\nSend a character to scan another tag!"); 150 | Serial.flush(); 151 | while (!Serial.available()); 152 | while (Serial.available()) { 153 | Serial.read(); 154 | } 155 | Serial.flush(); 156 | } 157 | } 158 | 159 | -------------------------------------------------------------------------------- /examples/ntag2xx_read/ntag2xx_read.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file readntag203.pde 4 | @author KTOWN (Adafruit Industries) 5 | @license BSD (see license.txt) 6 | 7 | This example will wait for any NTAG203 or NTAG213 card or tag, 8 | and will attempt to read from it. 9 | 10 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 11 | This library works with the Adafruit NFC breakout 12 | ----> https://www.adafruit.com/products/364 13 | 14 | Check out the links above for our tutorials and wiring diagrams 15 | These chips use SPI or I2C to communicate. 16 | 17 | Adafruit invests time and resources providing this open source code, 18 | please support Adafruit and open-source hardware by purchasing 19 | products from Adafruit! 20 | */ 21 | /**************************************************************************/ 22 | #include 23 | #include 24 | #include 25 | 26 | // If using the breakout with SPI, define the pins for SPI communication. 27 | #define PN532_SCK (2) 28 | #define PN532_MOSI (3) 29 | #define PN532_SS (4) 30 | #define PN532_MISO (5) 31 | 32 | // If using the breakout or shield with I2C, define just the pins connected 33 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 34 | #define PN532_IRQ (2) 35 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 36 | 37 | // Uncomment just _one_ line below depending on how your breakout or shield 38 | // is connected to the Arduino: 39 | 40 | // Use this line for a breakout with a software SPI connection (recommended): 41 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 42 | 43 | // Use this line for a breakout with a hardware SPI connection. Note that 44 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 45 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 46 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 47 | //Adafruit_PN532 nfc(PN532_SS); 48 | 49 | // Or use this line for a breakout or shield with an I2C connection: 50 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 51 | 52 | 53 | void setup(void) { 54 | Serial.begin(115200); 55 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 56 | 57 | Serial.println("Hello!"); 58 | 59 | nfc.begin(); 60 | 61 | uint32_t versiondata = nfc.getFirmwareVersion(); 62 | if (! versiondata) { 63 | Serial.print("Didn't find PN53x board"); 64 | while (1); // halt 65 | } 66 | // Got ok data, print it out! 67 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 68 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 69 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 70 | 71 | Serial.println("Waiting for an ISO14443A Card ..."); 72 | } 73 | 74 | void loop(void) { 75 | uint8_t success; 76 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 77 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 78 | 79 | // Wait for an NTAG203 card. When one is found 'uid' will be populated with 80 | // the UID, and uidLength will indicate the size of the UUID (normally 7) 81 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 82 | 83 | if (success) { 84 | // Display some basic information about the card 85 | Serial.println("Found an ISO14443A card"); 86 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 87 | Serial.print(" UID Value: "); 88 | nfc.PrintHex(uid, uidLength); 89 | Serial.println(""); 90 | 91 | if (uidLength == 7) 92 | { 93 | uint8_t data[32]; 94 | 95 | // We probably have an NTAG2xx card (though it could be Ultralight as well) 96 | Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); 97 | 98 | // NTAG2x3 cards have 39*4 bytes of user pages (156 user bytes), 99 | // starting at page 4 ... larger cards just add pages to the end of 100 | // this range: 101 | 102 | // See: http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf 103 | 104 | // TAG Type PAGES USER START USER STOP 105 | // -------- ----- ---------- --------- 106 | // NTAG 203 42 4 39 107 | // NTAG 213 45 4 39 108 | // NTAG 215 135 4 129 109 | // NTAG 216 231 4 225 110 | 111 | for (uint8_t i = 0; i < 42; i++) 112 | { 113 | success = nfc.ntag2xx_ReadPage(i, data); 114 | 115 | // Display the current page number 116 | Serial.print("PAGE "); 117 | if (i < 10) 118 | { 119 | Serial.print("0"); 120 | Serial.print(i); 121 | } 122 | else 123 | { 124 | Serial.print(i); 125 | } 126 | Serial.print(": "); 127 | 128 | // Display the results, depending on 'success' 129 | if (success) 130 | { 131 | // Dump the page data 132 | nfc.PrintHexChar(data, 4); 133 | } 134 | else 135 | { 136 | Serial.println("Unable to read the requested page!"); 137 | } 138 | } 139 | } 140 | else 141 | { 142 | Serial.println("This doesn't seem to be an NTAG203 tag (UUID length != 7 bytes)!"); 143 | } 144 | 145 | // Wait a bit before trying again 146 | Serial.println("\n\nSend a character to scan another tag!"); 147 | Serial.flush(); 148 | while (!Serial.available()); 149 | while (Serial.available()) { 150 | Serial.read(); 151 | } 152 | Serial.flush(); 153 | } 154 | } 155 | 156 | -------------------------------------------------------------------------------- /examples/ntag2xx_updatendef/ntag2xx_updatendef.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file ntag2xx_updatendef.pde 4 | @author KTOWN (Adafruit Industries) 5 | @license BSD (see license.txt) 6 | 7 | This example will wait for any NTAG203 or NTAG213 card or tag, 8 | and will attempt to add or update an NDEF URI at the start of the 9 | tag's memory. 10 | 11 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 12 | This library works with the Adafruit NFC breakout 13 | ----> https://www.adafruit.com/products/364 14 | 15 | Check out the links above for our tutorials and wiring diagrams 16 | These chips use SPI or I2C to communicate. 17 | 18 | Adafruit invests time and resources providing this open source code, 19 | please support Adafruit and open-source hardware by purchasing 20 | products from Adafruit! 21 | */ 22 | /**************************************************************************/ 23 | #include 24 | #include 25 | #include 26 | 27 | // If using the breakout with SPI, define the pins for SPI communication. 28 | #define PN532_SCK (2) 29 | #define PN532_MOSI (3) 30 | #define PN532_SS (4) 31 | #define PN532_MISO (5) 32 | 33 | // If using the breakout or shield with I2C, define just the pins connected 34 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 35 | #define PN532_IRQ (2) 36 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 37 | 38 | // Uncomment just _one_ line below depending on how your breakout or shield 39 | // is connected to the Arduino: 40 | 41 | // Use this line for a breakout with a software SPI connection (recommended): 42 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 43 | 44 | // Use this line for a breakout with a hardware SPI connection. Note that 45 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 46 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 47 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 48 | //Adafruit_PN532 nfc(PN532_SS); 49 | 50 | // Or use this line for a breakout or shield with an I2C connection: 51 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 52 | 53 | /* 54 | We can encode many different kinds of pointers to the card, 55 | from a URL, to an Email address, to a phone number, and many more 56 | check the library header .h file to see the large # of supported 57 | prefixes! 58 | */ 59 | // For a http://www. url: 60 | char * url = "adafruit.com/blog/"; 61 | uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT; 62 | 63 | // for an email address 64 | //char * url = "mail@example.com"; 65 | //uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO; 66 | 67 | // for a phone number 68 | //char * url = "+1 212 555 1212"; 69 | //uint8_t ndefprefix = NDEF_URIPREFIX_TEL; 70 | 71 | void setup(void) { 72 | Serial.begin(115200); 73 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 74 | 75 | Serial.println("Hello!"); 76 | 77 | nfc.begin(); 78 | 79 | uint32_t versiondata = nfc.getFirmwareVersion(); 80 | if (! versiondata) { 81 | Serial.print("Didn't find PN53x board"); 82 | while (1); // halt 83 | } 84 | // Got ok data, print it out! 85 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 86 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 87 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 88 | } 89 | 90 | void loop(void) 91 | { 92 | uint8_t success; 93 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 94 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 95 | uint8_t dataLength; 96 | 97 | // Require some user feedback before running this example! 98 | Serial.println("\r\nPlace your NDEF formatted NTAG2xx tag on the reader to update the"); 99 | Serial.println("NDEF record and press any key to continue ...\r\n"); 100 | // Wait for user input before proceeding 101 | while (!Serial.available()); 102 | // a key was pressed1 103 | while (Serial.available()) Serial.read(); 104 | 105 | // 1.) Wait for an NTAG203 card. When one is found 'uid' will be populated with 106 | // the UID, and uidLength will indicate the size of the UID (normally 7) 107 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 108 | 109 | // It seems we found a valid ISO14443A Tag! 110 | if (success) 111 | { 112 | // 2.) Display some basic information about the card 113 | Serial.println("Found an ISO14443A card"); 114 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 115 | Serial.print(" UID Value: "); 116 | nfc.PrintHex(uid, uidLength); 117 | Serial.println(""); 118 | 119 | if (uidLength != 7) 120 | { 121 | Serial.println("This doesn't seem to be an NTAG203 tag (UUID length != 7 bytes)!"); 122 | } 123 | else 124 | { 125 | uint8_t data[32]; 126 | 127 | // We probably have an NTAG2xx card (though it could be Ultralight as well) 128 | Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); 129 | 130 | // NTAG2x3 cards have 39*4 bytes of user pages (156 user bytes), 131 | // starting at page 4 ... larger cards just add pages to the end of 132 | // this range: 133 | 134 | // See: http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf 135 | 136 | // TAG Type PAGES USER START USER STOP 137 | // -------- ----- ---------- --------- 138 | // NTAG 203 42 4 39 139 | // NTAG 213 45 4 39 140 | // NTAG 215 135 4 129 141 | // NTAG 216 231 4 225 142 | 143 | 144 | // 3.) Check if the NDEF Capability Container (CC) bits are already set 145 | // in OTP memory (page 3) 146 | memset(data, 0, 4); 147 | success = nfc.ntag2xx_ReadPage(3, data); 148 | if (!success) 149 | { 150 | Serial.println("Unable to read the Capability Container (page 3)"); 151 | return; 152 | } 153 | else 154 | { 155 | // If the tag has already been formatted as NDEF, byte 0 should be: 156 | // Byte 0 = Magic Number (0xE1) 157 | // Byte 1 = NDEF Version (Should be 0x10) 158 | // Byte 2 = Data Area Size (value * 8 bytes) 159 | // Byte 3 = Read/Write Access (0x00 for full read and write) 160 | if (!((data[0] == 0xE1) && (data[1] == 0x10))) 161 | { 162 | Serial.println("This doesn't seem to be an NDEF formatted tag."); 163 | Serial.println("Page 3 should start with 0xE1 0x10."); 164 | } 165 | else 166 | { 167 | // 4.) Determine and display the data area size 168 | dataLength = data[2]*8; 169 | Serial.print("Tag is NDEF formatted. Data area size = "); 170 | Serial.print(dataLength); 171 | Serial.println(" bytes"); 172 | 173 | // 5.) Erase the old data area 174 | Serial.print("Erasing previous data area "); 175 | for (uint8_t i = 4; i < (dataLength/4)+4; i++) 176 | { 177 | memset(data, 0, 4); 178 | success = nfc.ntag2xx_WritePage(i, data); 179 | Serial.print("."); 180 | if (!success) 181 | { 182 | Serial.println(" ERROR!"); 183 | return; 184 | } 185 | } 186 | Serial.println(" DONE!"); 187 | 188 | // 6.) Try to add a new NDEF URI record 189 | Serial.print("Writing URI as NDEF Record ... "); 190 | success = nfc.ntag2xx_WriteNDEFURI(ndefprefix, url, dataLength); 191 | if (success) 192 | { 193 | Serial.println("DONE!"); 194 | } 195 | else 196 | { 197 | Serial.println("ERROR! (URI length?)"); 198 | } 199 | 200 | } // CC contents NDEF record check 201 | } // CC page read check 202 | } // UUID length check 203 | 204 | // Wait a bit before trying again 205 | Serial.flush(); 206 | while (!Serial.available()); 207 | while (Serial.available()) { 208 | Serial.read(); 209 | } 210 | Serial.flush(); 211 | } // Start waiting for a new ISO14443A tag 212 | } -------------------------------------------------------------------------------- /examples/readMifare/readMifare.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file readMifare.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | This example will wait for any ISO14443A card or tag, and 8 | depending on the size of the UID will attempt to read from it. 9 | 10 | If the card has a 4-byte UID it is probably a Mifare 11 | Classic card, and the following steps are taken: 12 | 13 | - Authenticate block 4 (the first block of Sector 1) using 14 | the default KEYA of 0XFF 0XFF 0XFF 0XFF 0XFF 0XFF 15 | - If authentication succeeds, we can then read any of the 16 | 4 blocks in that sector (though only block 4 is read here) 17 | 18 | If the card has a 7-byte UID it is probably a Mifare 19 | Ultralight card, and the 4 byte pages can be read directly. 20 | Page 4 is read by default since this is the first 'general- 21 | purpose' page on the tags. 22 | 23 | 24 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 25 | This library works with the Adafruit NFC breakout 26 | ----> https://www.adafruit.com/products/364 27 | 28 | Check out the links above for our tutorials and wiring diagrams 29 | These chips use SPI or I2C to communicate. 30 | 31 | Adafruit invests time and resources providing this open source code, 32 | please support Adafruit and open-source hardware by purchasing 33 | products from Adafruit! 34 | 35 | */ 36 | /**************************************************************************/ 37 | #include 38 | #include 39 | #include 40 | 41 | // If using the breakout with SPI, define the pins for SPI communication. 42 | #define PN532_SCK (2) 43 | #define PN532_MOSI (3) 44 | #define PN532_SS (4) 45 | #define PN532_MISO (5) 46 | 47 | // If using the breakout or shield with I2C, define just the pins connected 48 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 49 | #define PN532_IRQ (2) 50 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 51 | 52 | // Uncomment just _one_ line below depending on how your breakout or shield 53 | // is connected to the Arduino: 54 | 55 | // Use this line for a breakout with a software SPI connection (recommended): 56 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 57 | 58 | // Use this line for a breakout with a hardware SPI connection. Note that 59 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 60 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 61 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 62 | //Adafruit_PN532 nfc(PN532_SS); 63 | 64 | // Or use this line for a breakout or shield with an I2C connection: 65 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 66 | 67 | // Or use hardware Serial: 68 | //Adafruit_PN532 nfc(PN532_RESET, &Serial1); 69 | 70 | void setup(void) { 71 | Serial.begin(115200); 72 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 73 | 74 | Serial.println("Hello!"); 75 | 76 | nfc.begin(); 77 | 78 | uint32_t versiondata = nfc.getFirmwareVersion(); 79 | if (! versiondata) { 80 | Serial.print("Didn't find PN53x board"); 81 | while (1); // halt 82 | } 83 | // Got ok data, print it out! 84 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 85 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 86 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 87 | 88 | Serial.println("Waiting for an ISO14443A Card ..."); 89 | } 90 | 91 | 92 | void loop(void) { 93 | uint8_t success; 94 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 95 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 96 | 97 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 98 | // 'uid' will be populated with the UID, and uidLength will indicate 99 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 100 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 101 | 102 | if (success) { 103 | // Display some basic information about the card 104 | Serial.println("Found an ISO14443A card"); 105 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 106 | Serial.print(" UID Value: "); 107 | nfc.PrintHex(uid, uidLength); 108 | Serial.println(""); 109 | 110 | if (uidLength == 4) 111 | { 112 | // We probably have a Mifare Classic card ... 113 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 114 | 115 | // Now we need to try to authenticate it for read/write access 116 | // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 117 | Serial.println("Trying to authenticate block 4 with default KEYA value"); 118 | uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 119 | 120 | // Start with block 4 (the first block of sector 1) since sector 0 121 | // contains the manufacturer data and it's probably better just 122 | // to leave it alone unless you know what you're doing 123 | success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya); 124 | 125 | if (success) 126 | { 127 | Serial.println("Sector 1 (Blocks 4..7) has been authenticated"); 128 | uint8_t data[16]; 129 | 130 | // If you want to write something to block 4 to test with, uncomment 131 | // the following line and this text should be read back in a minute 132 | //memcpy(data, (const uint8_t[]){ 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0 }, sizeof data); 133 | // success = nfc.mifareclassic_WriteDataBlock (4, data); 134 | 135 | // Try to read the contents of block 4 136 | success = nfc.mifareclassic_ReadDataBlock(4, data); 137 | 138 | if (success) 139 | { 140 | // Data seems to have been read ... spit it out 141 | Serial.println("Reading Block 4:"); 142 | nfc.PrintHexChar(data, 16); 143 | Serial.println(""); 144 | 145 | // Wait a bit before reading the card again 146 | delay(1000); 147 | } 148 | else 149 | { 150 | Serial.println("Ooops ... unable to read the requested block. Try another key?"); 151 | } 152 | } 153 | else 154 | { 155 | Serial.println("Ooops ... authentication failed: Try another key?"); 156 | } 157 | } 158 | 159 | if (uidLength == 7) 160 | { 161 | // We probably have a Mifare Ultralight card ... 162 | Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)"); 163 | 164 | // Try to read the first general-purpose user page (#4) 165 | Serial.println("Reading page 4"); 166 | uint8_t data[32]; 167 | success = nfc.mifareultralight_ReadPage (4, data); 168 | if (success) 169 | { 170 | // Data seems to have been read ... spit it out 171 | nfc.PrintHexChar(data, 4); 172 | Serial.println(""); 173 | 174 | // Wait a bit before reading the card again 175 | delay(1000); 176 | } 177 | else 178 | { 179 | Serial.println("Ooops ... unable to read the requested page!?"); 180 | } 181 | } 182 | } 183 | } 184 | 185 | -------------------------------------------------------------------------------- /examples/readMifareClassic/readMifareClassic.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file readMifareClassic.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | This example will wait for any ISO14443A card or tag, and 8 | depending on the size of the UID will attempt to read from it. 9 | 10 | If the card has a 4-byte UID it is probably a Mifare 11 | Classic card, and the following steps are taken: 12 | 13 | Reads the 4 byte (32 bit) ID of a MiFare Classic card. 14 | Since the classic cards have only 32 bit identifiers you can stick 15 | them in a single variable and use that to compare card ID's as a 16 | number. This doesn't work for ultralight cards that have longer 7 17 | byte IDs! 18 | 19 | Note that you need the baud rate to be 115200 because we need to 20 | print out the data and read from the card at the same time! 21 | 22 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 23 | This library works with the Adafruit NFC breakout 24 | ----> https://www.adafruit.com/products/364 25 | 26 | Check out the links above for our tutorials and wiring diagrams 27 | These chips use SPI to communicate, 4 required to interface 28 | 29 | Adafruit invests time and resources providing this open source code, 30 | please support Adafruit and open-source hardware by purchasing 31 | products from Adafruit! 32 | */ 33 | /**************************************************************************/ 34 | #include 35 | #include 36 | #include 37 | 38 | // If using the breakout with SPI, define the pins for SPI communication. 39 | #define PN532_SCK (2) 40 | #define PN532_MOSI (3) 41 | #define PN532_SS (4) 42 | #define PN532_MISO (5) 43 | 44 | // If using the breakout or shield with I2C, define just the pins connected 45 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 46 | #define PN532_IRQ (2) 47 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 48 | 49 | // Uncomment just _one_ line below depending on how your breakout or shield 50 | // is connected to the Arduino: 51 | 52 | // Use this line for a breakout with a SPI connection: 53 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 54 | 55 | // Use this line for a breakout with a hardware SPI connection. Note that 56 | // the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's 57 | // hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are 58 | // SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin. 59 | //Adafruit_PN532 nfc(PN532_SS); 60 | 61 | // Or use this line for a breakout or shield with an I2C connection: 62 | //Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 63 | 64 | void setup(void) { 65 | Serial.begin(115200); 66 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 67 | 68 | Serial.println("Hello!"); 69 | 70 | nfc.begin(); 71 | 72 | uint32_t versiondata = nfc.getFirmwareVersion(); 73 | if (! versiondata) { 74 | Serial.print("Didn't find PN53x board"); 75 | while (1); // halt 76 | } 77 | // Got ok data, print it out! 78 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 79 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 80 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 81 | 82 | Serial.println("Waiting for an ISO14443A Card ..."); 83 | } 84 | 85 | 86 | void loop(void) { 87 | uint8_t success; 88 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 89 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 90 | 91 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 92 | // 'uid' will be populated with the UID, and uidLength will indicate 93 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 94 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 95 | 96 | if (success) { 97 | // Display some basic information about the card 98 | Serial.println("Found an ISO14443A card"); 99 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 100 | Serial.print(" UID Value: "); 101 | nfc.PrintHex(uid, uidLength); 102 | 103 | if (uidLength == 4) 104 | { 105 | // We probably have a Mifare Classic card ... 106 | uint32_t cardid = uid[0]; 107 | cardid <<= 8; 108 | cardid |= uid[1]; 109 | cardid <<= 8; 110 | cardid |= uid[2]; 111 | cardid <<= 8; 112 | cardid |= uid[3]; 113 | Serial.print("Seems to be a Mifare Classic card #"); 114 | Serial.println(cardid); 115 | } 116 | Serial.println(""); 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /examples/readMifareClassicIrq/readMifareClassicIrq.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file readMifareClassicIrq.pde 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | This example will wait for any ISO14443A card or tag, and 8 | depending on the size of the UID will attempt to read from it. 9 | 10 | If the card has a 4-byte UID it is probably a Mifare 11 | Classic card, and the following steps are taken: 12 | 13 | Reads the 4 byte (32 bit) ID of a MiFare Classic card. 14 | Since the classic cards have only 32 bit identifiers you can stick 15 | them in a single variable and use that to compare card ID's as a 16 | number. This doesn't work for ultralight cards that have longer 7 17 | byte IDs! 18 | 19 | Note that you need the baud rate to be 115200 because we need to 20 | print out the data and read from the card at the same time! 21 | 22 | This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards 23 | This library works with the Adafruit NFC breakout 24 | ----> https://www.adafruit.com/products/364 25 | 26 | Check out the links above for our tutorials and wiring diagrams 27 | 28 | This example is for communicating with the PN532 chip using I2C. Wiring 29 | should be as follows: 30 | PN532 SDA -> SDA pin 31 | PN532 SCL -> SCL pin 32 | PN532 IRQ -> D2 33 | PN532 SDA -> 3.3v (with 2k resistor) 34 | PN532 SCL -> 3.3v (with 2k resistor) 35 | PN532 3.3v -> 3.3v 36 | PN532 GND -> GND 37 | 38 | Adafruit invests time and resources providing this open source code, 39 | please support Adafruit and open-source hardware by purchasing 40 | products from Adafruit! 41 | */ 42 | /**************************************************************************/ 43 | #include 44 | #include 45 | #include 46 | 47 | // If using the breakout with SPI, define the pins for SPI communication. 48 | #define PN532_SCK (2) 49 | #define PN532_MOSI (3) 50 | #define PN532_SS (4) 51 | #define PN532_MISO (5) 52 | 53 | // If using the breakout or shield with I2C, define just the pins connected 54 | // to the IRQ and reset lines. Use the values below (2, 3) for the shield! 55 | #define PN532_IRQ (2) 56 | #define PN532_RESET (3) // Not connected by default on the NFC Shield 57 | 58 | const int DELAY_BETWEEN_CARDS = 500; 59 | long timeLastCardRead = 0; 60 | boolean readerDisabled = false; 61 | int irqCurr; 62 | int irqPrev; 63 | 64 | // This example uses the IRQ line, which is available when in I2C mode. 65 | Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); 66 | 67 | void setup(void) { 68 | Serial.begin(115200); 69 | while (!Serial) delay(10); // for Leonardo/Micro/Zero 70 | 71 | Serial.println("Hello!"); 72 | 73 | nfc.begin(); 74 | 75 | uint32_t versiondata = nfc.getFirmwareVersion(); 76 | if (! versiondata) { 77 | Serial.print("Didn't find PN53x board"); 78 | while (1); // halt 79 | } 80 | // Got ok data, print it out! 81 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 82 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 83 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 84 | 85 | startListeningToNFC(); 86 | } 87 | 88 | void loop(void) { 89 | if (readerDisabled) { 90 | if (millis() - timeLastCardRead > DELAY_BETWEEN_CARDS) { 91 | readerDisabled = false; 92 | startListeningToNFC(); 93 | } 94 | } else { 95 | irqCurr = digitalRead(PN532_IRQ); 96 | 97 | // When the IRQ is pulled low - the reader has got something for us. 98 | if (irqCurr == LOW && irqPrev == HIGH) { 99 | Serial.println("Got NFC IRQ"); 100 | handleCardDetected(); 101 | } 102 | 103 | irqPrev = irqCurr; 104 | } 105 | } 106 | 107 | void startListeningToNFC() { 108 | // Reset our IRQ indicators 109 | irqPrev = irqCurr = HIGH; 110 | 111 | Serial.println("Starting passive read for an ISO14443A Card ..."); 112 | if (!nfc.startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A)) { 113 | Serial.println("No card found. Waiting..."); 114 | } else { 115 | Serial.println("Card already present."); 116 | handleCardDetected(); 117 | } 118 | } 119 | 120 | void handleCardDetected() { 121 | uint8_t success = false; 122 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 123 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 124 | 125 | // read the NFC tag's info 126 | success = nfc.readDetectedPassiveTargetID(uid, &uidLength); 127 | Serial.println(success ? "Read successful" : "Read failed (not a card?)"); 128 | 129 | if (success) { 130 | // Display some basic information about the card 131 | Serial.println("Found an ISO14443A card"); 132 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 133 | Serial.print(" UID Value: "); 134 | nfc.PrintHex(uid, uidLength); 135 | 136 | if (uidLength == 4) 137 | { 138 | // We probably have a Mifare Classic card ... 139 | uint32_t cardid = uid[0]; 140 | cardid <<= 8; 141 | cardid |= uid[1]; 142 | cardid <<= 8; 143 | cardid |= uid[2]; 144 | cardid <<= 8; 145 | cardid |= uid[3]; 146 | Serial.print("Seems to be a Mifare Classic card #"); 147 | Serial.println(cardid); 148 | } 149 | Serial.println(""); 150 | 151 | timeLastCardRead = millis(); 152 | } 153 | 154 | // The reader will be enabled again after DELAY_BETWEEN_CARDS ms will pass. 155 | readerDisabled = true; 156 | } 157 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit PN532 2 | version=1.3.4 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Arduino library for SPI and I2C access to the PN532 RFID/Near Field Communication chip 6 | paragraph=Arduino library for SPI and I2C access to the PN532 RFID/Near Field Communication chip 7 | category=Communication 8 | url=https://github.com/adafruit/Adafruit-PN532 9 | architectures=* 10 | depends=Adafruit BusIO 11 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2012, Adafruit Industries 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of the copyright holders nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | --------------------------------------------------------------------------------