├── examples ├── apduToBlackBerry │ ├── BlackBerry7 │ │ ├── res │ │ │ └── img │ │ │ │ └── icon.png │ │ ├── .classpath │ │ ├── .settings │ │ │ └── org.eclipse.jdt.core.prefs │ │ ├── .project │ │ ├── build.xml │ │ ├── src │ │ │ └── mypackage │ │ │ │ ├── MyApp.java │ │ │ │ ├── ColorMixer.java │ │ │ │ └── MyScreen.java │ │ └── BlackBerry_App_Descriptor.xml │ └── apduToBlackBerry.pde ├── iso14443a_uid │ └── iso14443a_uid.pde ├── readMifareClassic │ └── readMifareClassic.pde ├── ntag2xx_read │ └── ntag2xx_read.pde ├── ntag2xx_erase │ └── ntag2xx_erase.pde ├── readMifare │ └── readMifare.pde ├── mifareclassic_updatendef │ └── mifareclassic_updatendef.pde ├── mifareclassic_formatndef │ └── mifareclassic_formatndef.pde ├── mifareclassic_memdump │ └── mifareclassic_memdump.pde ├── ntag2xx_updatendef │ └── ntag2xx_updatendef.pde ├── mifareclassic_ndeftoclassic │ └── mifareclassic_ndeftoclassic.pde └── ApplePay_Troyka_ACS │ └── ApplePay_Troyka_ACS.ino ├── library.properties ├── README.txt ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── license.txt ├── README.md ├── Adafruit_PN532.h └── Adafruit_PN532.cpp /examples/apduToBlackBerry/BlackBerry7/res/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhovner/Adafruit-PN532/HEAD/examples/apduToBlackBerry/BlackBerry7/res/img/icon.png -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit PN532 2 | version=1.0.2 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 | -------------------------------------------------------------------------------- /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/.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 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This is a library for the Adafruit PN532 NFC/RFID breakout boards 2 | This library works with the Adafruit NFC breakout 3 | ----> https://www.adafruit.com/products/364 4 | 5 | Check out the links above for our tutorials and wiring diagrams 6 | These chips use I2C or SPI to communicate. 7 | 8 | Adafruit invests time and resources providing this open source code, 9 | please support Adafruit and open-source hardware by purchasing 10 | products from Adafruit! 11 | 12 | Written by Limor Fried/Ladyada & Kevin Townsend for Adafruit Industries. 13 | BSD license, check license.txt for more information 14 | All text above must be included in any redistribution 15 | 16 | To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_PN532. Check that the Adafruit_PN532 folder contains Adafruit_PN532.cpp and Adafruit_PN532.h 17 | 18 | Place the Adafruit_PN532 library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE. 19 | -------------------------------------------------------------------------------- /examples/apduToBlackBerry/BlackBerry7/build.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /examples/iso14443a_uid/iso14443a_uid.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 58 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 59 | // also change #define in Adafruit_PN532.cpp library file 60 | #define Serial SerialUSB 61 | #endif 62 | 63 | void setup(void) { 64 | #ifndef ESP8266 65 | while (!Serial); // for Leonardo/Micro/Zero 66 | #endif 67 | Serial.begin(115200); 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 | 78 | // Got ok data, print it out! 79 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 80 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 81 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 82 | 83 | // Set the max number of retry attempts to read from a card 84 | // This prevents us from waiting forever for a card, which is 85 | // the default behaviour of the PN532. 86 | nfc.setPassiveActivationRetries(0xFF); 87 | 88 | // configure board to read RFID tags 89 | nfc.SAMConfig(); 90 | 91 | Serial.println("Waiting for an ISO14443A card"); 92 | } 93 | 94 | void loop(void) { 95 | boolean success; 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 | 99 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 100 | // 'uid' will be populated with the UID, and uidLength will indicate 101 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 102 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); 103 | 104 | if (success) { 105 | Serial.println("Found a card!"); 106 | Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 107 | Serial.print("UID Value: "); 108 | for (uint8_t i=0; i < uidLength; i++) 109 | { 110 | Serial.print(" 0x");Serial.print(uid[i], HEX); 111 | } 112 | Serial.println(""); 113 | // Wait 1 second before continuing 114 | delay(1000); 115 | } 116 | else 117 | { 118 | // PN532 probably timed out waiting for a card 119 | Serial.println("Timed out waiting for a card"); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /examples/readMifareClassic/readMifareClassic.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 65 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 66 | // also change #define in Adafruit_PN532.cpp library file 67 | #define Serial SerialUSB 68 | #endif 69 | 70 | void setup(void) { 71 | #ifndef ESP8266 72 | while (!Serial); // for Leonardo/Micro/Zero 73 | #endif 74 | Serial.begin(115200); 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 | // configure board to read RFID tags 90 | nfc.SAMConfig(); 91 | 92 | Serial.println("Waiting for an ISO14443A Card ..."); 93 | } 94 | 95 | 96 | void loop(void) { 97 | uint8_t success; 98 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 99 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 100 | 101 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 102 | // 'uid' will be populated with the UID, and uidLength will indicate 103 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 104 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 105 | 106 | if (success) { 107 | // Display some basic information about the card 108 | Serial.println("Found an ISO14443A card"); 109 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 110 | Serial.print(" UID Value: "); 111 | nfc.PrintHex(uid, uidLength); 112 | 113 | if (uidLength == 4) 114 | { 115 | // We probably have a Mifare Classic card ... 116 | uint32_t cardid = uid[0]; 117 | cardid <<= 8; 118 | cardid |= uid[1]; 119 | cardid <<= 8; 120 | cardid |= uid[2]; 121 | cardid <<= 8; 122 | cardid |= uid[3]; 123 | Serial.print("Seems to be a Mifare Classic card #"); 124 | Serial.println(cardid); 125 | } 126 | Serial.println(""); 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /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/apduToBlackBerry.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 66 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 67 | // also change #define in Adafruit_PN532.cpp library file 68 | #define Serial SerialUSB 69 | #endif 70 | 71 | void setup() { 72 | #ifndef ESP8266 73 | while (!Serial); // for Leonardo/Micro/Zero 74 | #endif 75 | Serial.begin(115200); 76 | 77 | pinMode(R_PIN,OUTPUT); 78 | pinMode(G_PIN,OUTPUT); 79 | pinMode(B_PIN,OUTPUT); 80 | showColor(); 81 | 82 | nfc.begin(); 83 | 84 | uint32_t versiondata = nfc.getFirmwareVersion(); 85 | if (! versiondata) { 86 | Serial.println("Did not find the shield - locking up"); 87 | while (true) { 88 | } 89 | } 90 | 91 | Serial.print("Found chip PN5"); 92 | Serial.println((versiondata>>24) & 0xFF, HEX); 93 | Serial.print("Firmware ver. "); 94 | Serial.print((versiondata>>16) & 0xFF, DEC); 95 | Serial.print('.'); 96 | Serial.println((versiondata>>8) & 0xFF, DEC); 97 | 98 | // configure board to read RFID tags 99 | nfc.SAMConfig(); 100 | 101 | nfc.begin(); 102 | } 103 | 104 | uint8_t message[4]; 105 | 106 | void loop(void) { 107 | uint8_t i; 108 | 109 | // Serial.println("Listening..."); 110 | if (nfc.inListPassiveTarget()) { 111 | // Serial.println("Something's there..."); 112 | while(true) { 113 | message[0] = 1; 114 | message[1] = r; 115 | message[2] = g; 116 | message[3] = b; 117 | uint8_t responseLength = sizeof(message); 118 | if (nfc.inDataExchange(message,sizeof(message),message,&responseLength)) { 119 | uint8_t command = message[0]; 120 | switch(command) { 121 | case 0: 122 | // NOP 123 | break; 124 | case 1: 125 | if (responseLength==4) { 126 | r = message[1]; 127 | g = message[2]; 128 | b = message[3]; 129 | showColor(); 130 | //Serial.print("Read a color: "); 131 | //for (i=0; i<3; ++i) { 132 | // Serial.print(message[i+1],HEX); 133 | // Serial.print(' '); 134 | //} 135 | //Serial.println(); 136 | } 137 | else { 138 | //Serial.println("Doesn't seem to be a color..."); 139 | } 140 | break; 141 | default: 142 | //Serial.print("Unknown command "); 143 | //Serial.println(message[0]); 144 | ; 145 | } 146 | delay(10); 147 | } 148 | else { 149 | //Serial.println("It's gone..."); 150 | break; 151 | } 152 | } 153 | } 154 | else { 155 | //Serial.print("Trying again..."); 156 | } 157 | } 158 | 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | What changed in genuine Adafrauit PN532 library 3 | 4 | * **_inListedTag** -- tag number for `inDataExchange` method. Defined as `0x1` because `0x0` returns error. 5 | * **PN532_PACKBUFFSIZ** -- increased from 64 to 255 to read long responses from EMV cards. 6 | * **New example** -- Access Control reader based on PayWave/PayPass/ApplePay and Troyka cards (very dumb demo) 7 | 8 | ## Note for 7 byte UID Mifare Classic cards (Mifare Plus in legacy mode) 9 | For 7 byte UID Mifare's only last 4 byte should be used for authenticate sectors. 10 | This library have bug in examples that passes all 7 bytes to authenticate command. 11 | 12 | ### PN532 Command example 13 | 14 | If you have UID `0x04 0x33 0x18 0xEA 0x70 0x32 0x80` 15 | 16 | and want to authenticate block 4 (sector 1), then full PN532 command will be: 17 | 18 | `0xD4 0x40 0x01 0x60 0x04 0xA7 0x3F 0x5D 0xC1 0xD3 0x33 0xEA 0x70 0x32 0x80` 19 | (without PREAMBLE/POSTAMBLE and checksums) 20 | 21 | Command structure: 22 | 23 | * `0xD4` — **TFI** from host controller to PN532 24 | * `0x40` — **InDataExchange** command 25 | * `0x01` — **Tg** byte number of target (card) 26 | * `0x60` — **Mifare command** authenticate with key A 27 | * `0xA7 0x3F 0x5D 0xC1 0xD3 0x33` — **Mifare Key A** for authenticated sector 28 | * `0xEA 0x70 0x32 0x80` — **Last 4 bytes of UID** 29 | 30 | 31 | ### PN532 Response example 32 | Successfully authenticated response: `0x00 0x00 0xFF 0x03 0xFD 0xD5 0x41 0x00` 33 | 34 | If you pass all 7 bytes UID to auth command, you will get `syntax error` response from PN532. 35 | This library is incorrectry handle `syntax error` response from pn532. 36 | 37 | Syntax error respone: `0x00 0x00 0xFF 0x01 0xFF 0x7F 0x81 0x00` 38 | 39 | 40 | 41 | 42 | 43 | 44 | --- 45 | 46 | Source document: https://www.nxp.com/docs/en/user-guide/141520.pdf 47 | 48 | # 6.2 PN532 Host controller communication protocol 49 | 50 | Communication between the host controller and the PN532 is performed through frames, in a half-duplex mode. 51 | Four different types of frames are used in one or both directions (host controller to the PN532 and PN532 to the host controller). 52 | 53 | 54 | ## 6.2.1.1 Normal information frame 55 | 56 | Information frames are used to convey: 57 | * Commands from the host controller to the PN532, 58 | * And responses to these commands from the PN532 to the host controller. 59 | 60 | ### The structure of this frame is the following: 61 | 62 | ![](https://i.imgur.com/P9gbxho.png) 63 | 64 | 65 | * **PREAMBLE** — 1 byte (0x00) 66 | * **START CODE** — 2 bytes (0x00 and 0xFF) 67 | * **LEN** — 1 byte indicating the number of bytes in the data field (TFI and PD0 to PDn) 68 | * **LCS** — 1 Packet Length Checksum LCS byte that satisfies the relation: Lower byte of [LEN + LCS] = 0x00 69 | * **TFI** — 1 byte frame identifier, the value of this byte depends on the way of the message: 70 | - **D4h** in case of a frame from the host controller to the PN532 71 | - **D5h** in case of a frame from the PN532 to the host controller 72 | * **DATA** — LEN-1 bytes of Packet Data Information The first byte PD0 is the Command Code 73 | * **DCS** — 1 Data Checksum DCS byte that satisfies the relation: Lower byte of [TFI + PD0 + PD1 + ... + PDn + DCS] = 0x00 74 | * **POSTAMBLE** — 1 byte (0x00) 75 | 76 | The amount of data that can be exchanged using this frame structure is limited to 255 bytes (including TFI). 77 | 78 | ## 6.2.1.2 Extended information frame 79 | 80 | The information frame has an extended definition allowing exchanging more data between the host controller and the PN532. 81 | In the firmware implementation of the PN532, the maximum length of the packet data is limited to 264 bytes (265 bytes with TFI included). 82 | 83 | ### The structure of this frame is the following: 84 | ![](https://i.imgur.com/5sw4y8Q.png) 85 | 86 | The normal LEN and LCS fields are fixed to the 0xFF value, which is normally considered as erroneous frame, due to the fact that the checksum does not fit. 87 | The real length is then coded in the two following bytes LENM (MSByte) and LENL (LSByte) with: 88 | 89 | **LENGTH** = **LEN**M x 256 + **LENL** coding the number of bytes in the data field (TFI and PD0 to PDn) 90 | * **LCS** — 1 Packet Length Checksum LCS byte that satisfies the relation: Lower byte of [LENM + LENL + LCS] = 0x00 91 | * **DATA** — LENGTH-1 bytes of Packet Data Information The first byte PD0 is the Command Code. 92 | 93 | The host controller, for sending frame whose length is less than 255 bytes, can also use this type of frame. 94 | But, the PN532 always uses the suitable type of frame, depending on the length (Normal Information Frame for frame <= 255 bytes and Extended Information Frame for frame > 255 bytes). 95 | 96 | 97 | ## 6.2.1.3 ACK frame 98 | The specific ACK frame is used for the synchronization of the packets and also for the abort mechanism. 99 | This frame may be used either from the host controller to the PN532 or from the PN532 to the host controller to indicate that the previous frame has been successfully received. 100 | 101 | ### ACK frame: 102 | ![](https://i.imgur.com/WJVgoD2.png) 103 | 104 | ## 6.2.1.4 NACK frame 105 | The specific NACK frame is used for the synchronization of the packets. 106 | This frame is used only from the host controller to the PN532 to indicate that the previous response frame has not been successfully received, then asking for the retransmission of the last response frame from the PN532 to the host controller. 107 | 108 | ### NACK frame: 109 | ![](https://i.imgur.com/PmkO0h2.png) 110 | 111 | ## 6.2.1.5 Error frame 112 | The syntax error frame is used to inform the host controller that the PN532 has detected an error at the application level. 113 | 114 | ### Error frame: 115 | ![](https://i.imgur.com/gT7pCLk.png) 116 | 117 | ## 6.2.1.6 Preamble and Postamble 118 | These two specific fields of the frames are described in the previous paragraphs as single byte, which the value is 0x00. 119 | In fact, these fields can be composed with an undetermined number of bytes. 120 | 121 | 122 | -------------------------------------------------------------------------------- /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/ntag2xx_read/ntag2xx_read.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 53 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 54 | // also change #define in Adafruit_PN532.cpp library file 55 | #define Serial SerialUSB 56 | #endif 57 | 58 | void setup(void) { 59 | #ifndef ESP8266 60 | while (!Serial); // for Leonardo/Micro/Zero 61 | #endif 62 | Serial.begin(115200); 63 | Serial.println("Hello!"); 64 | 65 | nfc.begin(); 66 | 67 | uint32_t versiondata = nfc.getFirmwareVersion(); 68 | if (! versiondata) { 69 | Serial.print("Didn't find PN53x board"); 70 | while (1); // halt 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 | // configure board to read RFID tags 78 | nfc.SAMConfig(); 79 | 80 | Serial.println("Waiting for an ISO14443A Card ..."); 81 | } 82 | 83 | void loop(void) { 84 | uint8_t 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 NTAG203 card. When one is found 'uid' will be populated with 89 | // the UID, and uidLength will indicate the size of the UUID (normally 7) 90 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 91 | 92 | if (success) { 93 | // Display some basic information about the card 94 | Serial.println("Found an ISO14443A card"); 95 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 96 | Serial.print(" UID Value: "); 97 | nfc.PrintHex(uid, uidLength); 98 | Serial.println(""); 99 | 100 | if (uidLength == 7) 101 | { 102 | uint8_t data[32]; 103 | 104 | // We probably have an NTAG2xx card (though it could be Ultralight as well) 105 | Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); 106 | 107 | // NTAG2x3 cards have 39*4 bytes of user pages (156 user bytes), 108 | // starting at page 4 ... larger cards just add pages to the end of 109 | // this range: 110 | 111 | // See: http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf 112 | 113 | // TAG Type PAGES USER START USER STOP 114 | // -------- ----- ---------- --------- 115 | // NTAG 203 42 4 39 116 | // NTAG 213 45 4 39 117 | // NTAG 215 135 4 129 118 | // NTAG 216 231 4 225 119 | 120 | for (uint8_t i = 0; i < 42; i++) 121 | { 122 | success = nfc.ntag2xx_ReadPage(i, data); 123 | 124 | // Display the current page number 125 | Serial.print("PAGE "); 126 | if (i < 10) 127 | { 128 | Serial.print("0"); 129 | Serial.print(i); 130 | } 131 | else 132 | { 133 | Serial.print(i); 134 | } 135 | Serial.print(": "); 136 | 137 | // Display the results, depending on 'success' 138 | if (success) 139 | { 140 | // Dump the page data 141 | nfc.PrintHexChar(data, 4); 142 | } 143 | else 144 | { 145 | Serial.println("Unable to read the requested page!"); 146 | } 147 | } 148 | } 149 | else 150 | { 151 | Serial.println("This doesn't seem to be an NTAG203 tag (UUID length != 7 bytes)!"); 152 | } 153 | 154 | // Wait a bit before trying again 155 | Serial.println("\n\nSend a character to scan another tag!"); 156 | Serial.flush(); 157 | while (!Serial.available()); 158 | while (Serial.available()) { 159 | Serial.read(); 160 | } 161 | Serial.flush(); 162 | } 163 | } 164 | 165 | -------------------------------------------------------------------------------- /examples/ntag2xx_erase/ntag2xx_erase.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 54 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 55 | // also change #define in Adafruit_PN532.cpp library file 56 | #define Serial SerialUSB 57 | #endif 58 | 59 | void setup(void) { 60 | #ifndef ESP8266 61 | while (!Serial); // for Leonardo/Micro/Zero 62 | #endif 63 | Serial.begin(115200); 64 | Serial.println("Hello!"); 65 | 66 | nfc.begin(); 67 | 68 | uint32_t versiondata = nfc.getFirmwareVersion(); 69 | if (! versiondata) { 70 | Serial.print("Didn't find PN53x board"); 71 | while (1); // halt 72 | } 73 | // Got ok data, print it out! 74 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 75 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 76 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 77 | 78 | // configure board to read RFID tags 79 | nfc.SAMConfig(); 80 | 81 | Serial.println("Waiting for an ISO14443A Card ..."); 82 | } 83 | 84 | void loop(void) { 85 | uint8_t success; 86 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 87 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 88 | 89 | // Wait for an NTAG203 card. When one is found 'uid' will be populated with 90 | // the UID, and uidLength will indicate the size of the UUID (normally 7) 91 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 92 | 93 | if (success) { 94 | // Display some basic information about the card 95 | Serial.println("Found an ISO14443A card"); 96 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 97 | Serial.print(" UID Value: "); 98 | nfc.PrintHex(uid, uidLength); 99 | Serial.println(""); 100 | 101 | if (uidLength == 7) 102 | { 103 | uint8_t data[32]; 104 | 105 | // We probably have an NTAG2xx card (though it could be Ultralight as well) 106 | Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); 107 | 108 | // NTAG2x3 cards have 39*4 bytes of user pages (156 user bytes), 109 | // starting at page 4 ... larger cards just add pages to the end of 110 | // this range: 111 | 112 | // See: http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf 113 | 114 | // TAG Type PAGES USER START USER STOP 115 | // -------- ----- ---------- --------- 116 | // NTAG 203 42 4 39 117 | // NTAG 213 45 4 39 118 | // NTAG 215 135 4 129 119 | // NTAG 216 231 4 225 120 | 121 | Serial.println(""); 122 | Serial.println("Writing 0x00 0x00 0x00 0x00 to pages 4..29"); 123 | Serial.println(""); 124 | for (uint8_t i = 4; i < 39; i++) 125 | { 126 | memset(data, 0, 4); 127 | success = nfc.ntag2xx_WritePage(i, data); 128 | 129 | // Display the current page number 130 | Serial.print("Page "); 131 | if (i < 10) 132 | { 133 | Serial.print("0"); 134 | Serial.print(i); 135 | } 136 | else 137 | { 138 | Serial.print(i); 139 | } 140 | Serial.print(": "); 141 | 142 | // Display the results, depending on 'success' 143 | if (success) 144 | { 145 | Serial.println("Erased"); 146 | } 147 | else 148 | { 149 | Serial.println("Unable to write to the requested page!"); 150 | } 151 | } 152 | } 153 | else 154 | { 155 | Serial.println("This doesn't seem to be an NTAG203 tag (UUID length != 7 bytes)!"); 156 | } 157 | 158 | // Wait a bit before trying again 159 | Serial.println("\n\nSend a character to scan another tag!"); 160 | Serial.flush(); 161 | while (!Serial.available()); 162 | while (Serial.available()) { 163 | Serial.read(); 164 | } 165 | Serial.flush(); 166 | } 167 | } 168 | 169 | -------------------------------------------------------------------------------- /examples/readMifare/readMifare.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 68 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 69 | // also change #define in Adafruit_PN532.cpp library file 70 | #define Serial SerialUSB 71 | #endif 72 | 73 | void setup(void) { 74 | #ifndef ESP8266 75 | while (!Serial); // for Leonardo/Micro/Zero 76 | #endif 77 | Serial.begin(115200); 78 | Serial.println("Hello!"); 79 | 80 | nfc.begin(); 81 | 82 | uint32_t versiondata = nfc.getFirmwareVersion(); 83 | if (! versiondata) { 84 | Serial.print("Didn't find PN53x board"); 85 | while (1); // halt 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 | // configure board to read RFID tags 93 | nfc.SAMConfig(); 94 | 95 | Serial.println("Waiting for an ISO14443A Card ..."); 96 | } 97 | 98 | 99 | void loop(void) { 100 | uint8_t success; 101 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 102 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 103 | 104 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 105 | // 'uid' will be populated with the UID, and uidLength will indicate 106 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 107 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 108 | 109 | if (success) { 110 | // Display some basic information about the card 111 | Serial.println("Found an ISO14443A card"); 112 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 113 | Serial.print(" UID Value: "); 114 | nfc.PrintHex(uid, uidLength); 115 | Serial.println(""); 116 | 117 | if (uidLength == 4) 118 | { 119 | // We probably have a Mifare Classic card ... 120 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 121 | 122 | // Now we need to try to authenticate it for read/write access 123 | // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 124 | Serial.println("Trying to authenticate block 4 with default KEYA value"); 125 | uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 126 | 127 | // Start with block 4 (the first block of sector 1) since sector 0 128 | // contains the manufacturer data and it's probably better just 129 | // to leave it alone unless you know what you're doing 130 | success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya); 131 | 132 | if (success) 133 | { 134 | Serial.println("Sector 1 (Blocks 4..7) has been authenticated"); 135 | uint8_t data[16]; 136 | 137 | // If you want to write something to block 4 to test with, uncomment 138 | // the following line and this text should be read back in a minute 139 | //memcpy(data, (const uint8_t[]){ 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0 }, sizeof data); 140 | // success = nfc.mifareclassic_WriteDataBlock (4, data); 141 | 142 | // Try to read the contents of block 4 143 | success = nfc.mifareclassic_ReadDataBlock(4, data); 144 | 145 | if (success) 146 | { 147 | // Data seems to have been read ... spit it out 148 | Serial.println("Reading Block 4:"); 149 | nfc.PrintHexChar(data, 16); 150 | Serial.println(""); 151 | 152 | // Wait a bit before reading the card again 153 | delay(1000); 154 | } 155 | else 156 | { 157 | Serial.println("Ooops ... unable to read the requested block. Try another key?"); 158 | } 159 | } 160 | else 161 | { 162 | Serial.println("Ooops ... authentication failed: Try another key?"); 163 | } 164 | } 165 | 166 | if (uidLength == 7) 167 | { 168 | // We probably have a Mifare Ultralight card ... 169 | Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)"); 170 | 171 | // Try to read the first general-purpose user page (#4) 172 | Serial.println("Reading page 4"); 173 | uint8_t data[32]; 174 | success = nfc.mifareultralight_ReadPage (4, data); 175 | if (success) 176 | { 177 | // Data seems to have been read ... spit it out 178 | nfc.PrintHexChar(data, 4); 179 | Serial.println(""); 180 | 181 | // Wait a bit before reading the card again 182 | delay(1000); 183 | } 184 | else 185 | { 186 | Serial.println("Ooops ... unable to read the requested page!?"); 187 | } 188 | } 189 | } 190 | } 191 | 192 | -------------------------------------------------------------------------------- /examples/mifareclassic_updatendef/mifareclassic_updatendef.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 73 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 74 | // also change #define in Adafruit_PN532.cpp library file 75 | #define Serial SerialUSB 76 | #endif 77 | 78 | void setup(void) { 79 | #ifndef ESP8266 80 | while (!Serial); // for Leonardo/Micro/Zero 81 | #endif 82 | Serial.begin(115200); 83 | Serial.println("Looking for PN532..."); 84 | 85 | nfc.begin(); 86 | 87 | uint32_t versiondata = nfc.getFirmwareVersion(); 88 | if (! versiondata) { 89 | Serial.print("Didn't find PN53x board"); 90 | while (1); // halt 91 | } 92 | 93 | // Got ok data, print it out! 94 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 95 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 96 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 97 | 98 | // configure board to read RFID tags 99 | nfc.SAMConfig(); 100 | } 101 | 102 | void loop(void) { 103 | uint8_t success; // Flag to check if there was an error with the PN532 104 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 105 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 106 | bool authenticated = false; // Flag to indicate if the sector is authenticated 107 | 108 | // Use the default NDEF keys (these would have have set by mifareclassic_formatndef.pde!) 109 | uint8_t keya[6] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }; 110 | uint8_t keyb[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }; 111 | 112 | Serial.println("Place your NDEF formatted Mifare Classic card on the reader to update the"); 113 | Serial.println("NDEF record and press any key to continue ..."); 114 | // Wait for user input before proceeding 115 | while (!Serial.available()); 116 | // a key was pressed1 117 | while (Serial.available()) Serial.read(); 118 | 119 | // Wait for an ISO14443A type card (Mifare, etc.). When one is found 120 | // 'uid' will be populated with the UID, and uidLength will indicate 121 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 122 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 123 | 124 | if (success) 125 | { 126 | // Display some basic information about the card 127 | Serial.println("Found an ISO14443A card"); 128 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 129 | Serial.print(" UID Value: "); 130 | nfc.PrintHex(uid, uidLength); 131 | Serial.println(""); 132 | 133 | // Make sure this is a Mifare Classic card 134 | if (uidLength != 4) 135 | { 136 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 137 | return; 138 | } 139 | 140 | // We probably have a Mifare Classic card ... 141 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 142 | 143 | // Check if this is an NDEF card (using first block of sector 1 from mifareclassic_formatndef.pde) 144 | // Must authenticate on the first key using 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 145 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keyb); 146 | if (!success) 147 | { 148 | Serial.println("Unable to authenticate block 4 ... is this card NDEF formatted?"); 149 | return; 150 | } 151 | 152 | Serial.println("Authentication succeeded (seems to be an NDEF/NFC Forum tag) ..."); 153 | 154 | // Authenticated seems to have worked 155 | // Try to write an NDEF record to sector 1 156 | // Use 0x01 for the URI Identifier Code to prepend "http://www." 157 | // to the url (and save some space). For information on URI ID Codes 158 | // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef 159 | if (strlen(url) > 38) 160 | { 161 | // The length is also checked in the WriteNDEFURI function, but lets 162 | // warn users here just in case they change the value and it's bigger 163 | // than it should be 164 | Serial.println("URI is too long ... must be less than 38 characters!"); 165 | return; 166 | } 167 | 168 | Serial.println("Updating sector 1 with URI as NDEF Message"); 169 | 170 | // URI is within size limits ... write it to the card and report success/failure 171 | success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url); 172 | if (success) 173 | { 174 | Serial.println("NDEF URI Record written to sector 1"); 175 | Serial.println(""); 176 | } 177 | else 178 | { 179 | Serial.println("NDEF Record creation failed! :("); 180 | } 181 | } 182 | 183 | // Wait a bit before trying again 184 | Serial.println("\n\nDone!"); 185 | delay(1000); 186 | Serial.flush(); 187 | while(Serial.available()) Serial.read(); 188 | } 189 | -------------------------------------------------------------------------------- /examples/mifareclassic_formatndef/mifareclassic_formatndef.pde: -------------------------------------------------------------------------------- 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 | #ifndef ESP8266 79 | while (!Serial); // for Leonardo/Micro/Zero 80 | #endif 81 | Serial.begin(115200); 82 | Serial.println("Looking for PN532..."); 83 | 84 | nfc.begin(); 85 | 86 | uint32_t versiondata = nfc.getFirmwareVersion(); 87 | if (! versiondata) { 88 | Serial.print("Didn't find PN53x board"); 89 | while (1); // halt 90 | } 91 | 92 | // Got ok data, print it out! 93 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 94 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 95 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 96 | 97 | // configure board to read RFID tags 98 | nfc.SAMConfig(); 99 | } 100 | 101 | void loop(void) { 102 | uint8_t success; // Flag to check if there was an error with the PN532 103 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 104 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 105 | bool authenticated = false; // Flag to indicate if the sector is authenticated 106 | 107 | // Use the default key 108 | uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 109 | 110 | Serial.println(""); 111 | Serial.println("PLEASE NOTE: Formatting your card for NDEF records will change the"); 112 | Serial.println("authentication keys. To reformat your NDEF tag as a clean Mifare"); 113 | Serial.println("Classic tag, use the mifareclassic_ndeftoclassic example!"); 114 | Serial.println(""); 115 | Serial.println("Place your Mifare Classic card on the reader to format with NDEF"); 116 | Serial.println("and press any key to continue ..."); 117 | // Wait for user input before proceeding 118 | while (!Serial.available()); 119 | // a key was pressed1 120 | while (Serial.available()) Serial.read(); 121 | 122 | // Wait for an ISO14443A type card (Mifare, etc.). When one is found 123 | // 'uid' will be populated with the UID, and uidLength will indicate 124 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 125 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 126 | 127 | if (success) 128 | { 129 | // Display some basic information about the card 130 | Serial.println("Found an ISO14443A card"); 131 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 132 | Serial.print(" UID Value: "); 133 | nfc.PrintHex(uid, uidLength); 134 | Serial.println(""); 135 | 136 | // Make sure this is a Mifare Classic card 137 | if (uidLength != 4) 138 | { 139 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 140 | return; 141 | } 142 | 143 | // We probably have a Mifare Classic card ... 144 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 145 | 146 | // Try to format the card for NDEF data 147 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 0, 0, keya); 148 | if (!success) 149 | { 150 | Serial.println("Unable to authenticate block 0 to enable card formatting!"); 151 | return; 152 | } 153 | success = nfc.mifareclassic_FormatNDEF(); 154 | if (!success) 155 | { 156 | Serial.println("Unable to format the card for NDEF"); 157 | return; 158 | } 159 | 160 | Serial.println("Card has been formatted for NDEF data using MAD1"); 161 | 162 | // Try to authenticate block 4 (first block of sector 1) using our key 163 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keya); 164 | 165 | // Make sure the authentification process didn't fail 166 | if (!success) 167 | { 168 | Serial.println("Authentication failed."); 169 | return; 170 | } 171 | 172 | // Try to write a URL 173 | Serial.println("Writing URI to sector 1 as an NDEF Message"); 174 | 175 | // Authenticated seems to have worked 176 | // Try to write an NDEF record to sector 1 177 | // Use 0x01 for the URI Identifier Code to prepend "http://www." 178 | // to the url (and save some space). For information on URI ID Codes 179 | // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef 180 | if (strlen(url) > 38) 181 | { 182 | // The length is also checked in the WriteNDEFURI function, but lets 183 | // warn users here just in case they change the value and it's bigger 184 | // than it should be 185 | Serial.println("URI is too long ... must be less than 38 characters long"); 186 | return; 187 | } 188 | 189 | // URI is within size limits ... write it to the card and report success/failure 190 | success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url); 191 | if (success) 192 | { 193 | Serial.println("NDEF URI Record written to sector 1"); 194 | } 195 | else 196 | { 197 | Serial.println("NDEF Record creation failed! :("); 198 | } 199 | } 200 | 201 | // Wait a bit before trying again 202 | Serial.println("\n\nDone!"); 203 | delay(1000); 204 | Serial.flush(); 205 | while(Serial.available()) Serial.read(); 206 | } 207 | -------------------------------------------------------------------------------- /examples/mifareclassic_memdump/mifareclassic_memdump.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 57 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 58 | // also change #define in Adafruit_PN532.cpp library file 59 | #define Serial SerialUSB 60 | #endif 61 | 62 | void setup(void) { 63 | #ifndef ESP8266 64 | while (!Serial); // for Leonardo/Micro/Zero 65 | #endif 66 | // has to be fast to dump the entire memory contents! 67 | Serial.begin(115200); 68 | Serial.println("Looking for PN532..."); 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 | // configure board to read RFID tags 83 | nfc.SAMConfig(); 84 | 85 | Serial.println("Waiting for an ISO14443A Card ..."); 86 | } 87 | 88 | 89 | void loop(void) { 90 | uint8_t success; // Flag to check if there was an error with the PN532 91 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 92 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 93 | uint8_t currentblock; // Counter to keep track of which block we're on 94 | bool authenticated = false; // Flag to indicate if the sector is authenticated 95 | uint8_t data[16]; // Array to store block data during reads 96 | 97 | // Keyb on NDEF and Mifare Classic should be the same 98 | uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 99 | 100 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 101 | // 'uid' will be populated with the UID, and uidLength will indicate 102 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 103 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 104 | 105 | if (success) { 106 | // Display some basic information about the card 107 | Serial.println("Found an ISO14443A card"); 108 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 109 | Serial.print(" UID Value: "); 110 | nfc.PrintHex(uid, uidLength); 111 | Serial.println(""); 112 | 113 | if (uidLength == 4) 114 | { 115 | // We probably have a Mifare Classic card ... 116 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 117 | 118 | // Now we try to go through all 16 sectors (each having 4 blocks) 119 | // authenticating each sector, and then dumping the blocks 120 | for (currentblock = 0; currentblock < 64; currentblock++) 121 | { 122 | // Check if this is a new block so that we can reauthenticate 123 | if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false; 124 | 125 | // If the sector hasn't been authenticated, do so first 126 | if (!authenticated) 127 | { 128 | // Starting of a new sector ... try to to authenticate 129 | Serial.print("------------------------Sector ");Serial.print(currentblock/4, DEC);Serial.println("-------------------------"); 130 | if (currentblock == 0) 131 | { 132 | // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!) 133 | // or 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 for NDEF formatted cards using key a, 134 | // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF) 135 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal); 136 | } 137 | else 138 | { 139 | // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!) 140 | // or 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 for NDEF formatted cards using key a, 141 | // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF) 142 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal); 143 | } 144 | if (success) 145 | { 146 | authenticated = true; 147 | } 148 | else 149 | { 150 | Serial.println("Authentication error"); 151 | } 152 | } 153 | // If we're still not authenticated just skip the block 154 | if (!authenticated) 155 | { 156 | Serial.print("Block ");Serial.print(currentblock, DEC);Serial.println(" unable to authenticate"); 157 | } 158 | else 159 | { 160 | // Authenticated ... we should be able to read the block now 161 | // Dump the data into the 'data' array 162 | success = nfc.mifareclassic_ReadDataBlock(currentblock, data); 163 | if (success) 164 | { 165 | // Read successful 166 | Serial.print("Block ");Serial.print(currentblock, DEC); 167 | if (currentblock < 10) 168 | { 169 | Serial.print(" "); 170 | } 171 | else 172 | { 173 | Serial.print(" "); 174 | } 175 | // Dump the raw data 176 | nfc.PrintHexChar(data, 16); 177 | } 178 | else 179 | { 180 | // Oops ... something happened 181 | Serial.print("Block ");Serial.print(currentblock, DEC); 182 | Serial.println(" unable to read this block"); 183 | } 184 | } 185 | } 186 | } 187 | else 188 | { 189 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 190 | } 191 | } 192 | // Wait a bit before trying again 193 | Serial.println("\n\nSend a character to run the mem dumper again!"); 194 | Serial.flush(); 195 | while (!Serial.available()); 196 | while (Serial.available()) { 197 | Serial.read(); 198 | } 199 | Serial.flush(); 200 | } 201 | -------------------------------------------------------------------------------- /examples/ntag2xx_updatendef/ntag2xx_updatendef.pde: -------------------------------------------------------------------------------- 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 | #if defined(ARDUINO_ARCH_SAMD) 72 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 73 | // also change #define in Adafruit_PN532.cpp library file 74 | #define Serial SerialUSB 75 | #endif 76 | 77 | void setup(void) { 78 | #ifndef ESP8266 79 | while (!Serial); // for Leonardo/Micro/Zero 80 | #endif 81 | Serial.begin(115200); 82 | Serial.println("Hello!"); 83 | 84 | nfc.begin(); 85 | 86 | uint32_t versiondata = nfc.getFirmwareVersion(); 87 | if (! versiondata) { 88 | Serial.print("Didn't find PN53x board"); 89 | while (1); // halt 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 | // configure board to read RFID tags 97 | nfc.SAMConfig(); 98 | } 99 | 100 | void loop(void) 101 | { 102 | uint8_t success; 103 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 104 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 105 | uint8_t dataLength; 106 | 107 | // Require some user feedback before running this example! 108 | Serial.println("\r\nPlace your NDEF formatted NTAG2xx tag on the reader to update the"); 109 | Serial.println("NDEF record and press any key to continue ...\r\n"); 110 | // Wait for user input before proceeding 111 | while (!Serial.available()); 112 | // a key was pressed1 113 | while (Serial.available()) Serial.read(); 114 | 115 | // 1.) Wait for an NTAG203 card. When one is found 'uid' will be populated with 116 | // the UID, and uidLength will indicate the size of the UID (normally 7) 117 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 118 | 119 | // It seems we found a valid ISO14443A Tag! 120 | if (success) 121 | { 122 | // 2.) Display some basic information about the card 123 | Serial.println("Found an ISO14443A card"); 124 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 125 | Serial.print(" UID Value: "); 126 | nfc.PrintHex(uid, uidLength); 127 | Serial.println(""); 128 | 129 | if (uidLength != 7) 130 | { 131 | Serial.println("This doesn't seem to be an NTAG203 tag (UUID length != 7 bytes)!"); 132 | } 133 | else 134 | { 135 | uint8_t data[32]; 136 | 137 | // We probably have an NTAG2xx card (though it could be Ultralight as well) 138 | Serial.println("Seems to be an NTAG2xx tag (7 byte UID)"); 139 | 140 | // NTAG2x3 cards have 39*4 bytes of user pages (156 user bytes), 141 | // starting at page 4 ... larger cards just add pages to the end of 142 | // this range: 143 | 144 | // See: http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf 145 | 146 | // TAG Type PAGES USER START USER STOP 147 | // -------- ----- ---------- --------- 148 | // NTAG 203 42 4 39 149 | // NTAG 213 45 4 39 150 | // NTAG 215 135 4 129 151 | // NTAG 216 231 4 225 152 | 153 | 154 | // 3.) Check if the NDEF Capability Container (CC) bits are already set 155 | // in OTP memory (page 3) 156 | memset(data, 0, 4); 157 | success = nfc.ntag2xx_ReadPage(3, data); 158 | if (!success) 159 | { 160 | Serial.println("Unable to read the Capability Container (page 3)"); 161 | return; 162 | } 163 | else 164 | { 165 | // If the tag has already been formatted as NDEF, byte 0 should be: 166 | // Byte 0 = Magic Number (0xE1) 167 | // Byte 1 = NDEF Version (Should be 0x10) 168 | // Byte 2 = Data Area Size (value * 8 bytes) 169 | // Byte 3 = Read/Write Access (0x00 for full read and write) 170 | if (!((data[0] == 0xE1) && (data[1] == 0x10))) 171 | { 172 | Serial.println("This doesn't seem to be an NDEF formatted tag."); 173 | Serial.println("Page 3 should start with 0xE1 0x10."); 174 | } 175 | else 176 | { 177 | // 4.) Determine and display the data area size 178 | dataLength = data[2]*8; 179 | Serial.print("Tag is NDEF formatted. Data area size = "); 180 | Serial.print(dataLength); 181 | Serial.println(" bytes"); 182 | 183 | // 5.) Erase the old data area 184 | Serial.print("Erasing previous data area "); 185 | for (uint8_t i = 4; i < (dataLength/4)+4; i++) 186 | { 187 | memset(data, 0, 4); 188 | success = nfc.ntag2xx_WritePage(i, data); 189 | Serial.print("."); 190 | if (!success) 191 | { 192 | Serial.println(" ERROR!"); 193 | return; 194 | } 195 | } 196 | Serial.println(" DONE!"); 197 | 198 | // 6.) Try to add a new NDEF URI record 199 | Serial.print("Writing URI as NDEF Record ... "); 200 | success = nfc.ntag2xx_WriteNDEFURI(ndefprefix, url, dataLength); 201 | if (success) 202 | { 203 | Serial.println("DONE!"); 204 | } 205 | else 206 | { 207 | Serial.println("ERROR! (URI length?)"); 208 | } 209 | 210 | } // CC contents NDEF record check 211 | } // CC page read check 212 | } // UUID length check 213 | 214 | // Wait a bit before trying again 215 | Serial.flush(); 216 | while (!Serial.available()); 217 | while (Serial.available()) { 218 | Serial.read(); 219 | } 220 | Serial.flush(); 221 | } // Start waiting for a new ISO14443A tag 222 | } -------------------------------------------------------------------------------- /examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.pde: -------------------------------------------------------------------------------- 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); 96 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 97 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 98 | 99 | // configure board to read RFID tags 100 | nfc.SAMConfig(); 101 | } 102 | 103 | void loop(void) { 104 | uint8_t success; // Flag to check if there was an error with the PN532 105 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 106 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 107 | bool authenticated = false; // Flag to indicate if the sector is authenticated 108 | uint8_t blockBuffer[16]; // Buffer to store block contents 109 | uint8_t blankAccessBits[3] = { 0xff, 0x07, 0x80 }; 110 | uint8_t idx = 0; 111 | uint8_t numOfSector = 16; // Assume Mifare Classic 1K for now (16 4-block sectors) 112 | 113 | Serial.println("Place your NDEF formatted Mifare Classic 1K card on the reader"); 114 | Serial.println("and press any key to continue ..."); 115 | 116 | // Wait for user input before proceeding 117 | while (!Serial.available()); 118 | while (Serial.available()) Serial.read(); 119 | 120 | // Wait for an ISO14443A type card (Mifare, etc.). When one is found 121 | // 'uid' will be populated with the UID, and uidLength will indicate 122 | // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) 123 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 124 | 125 | if (success) 126 | { 127 | // We seem to have a tag ... 128 | // Display some basic information about it 129 | Serial.println("Found an ISO14443A card/tag"); 130 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 131 | Serial.print(" UID Value: "); 132 | nfc.PrintHex(uid, uidLength); 133 | Serial.println(""); 134 | 135 | // Make sure this is a Mifare Classic card 136 | if (uidLength != 4) 137 | { 138 | Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!"); 139 | return; 140 | } 141 | 142 | Serial.println("Seems to be a Mifare Classic card (4 byte UID)"); 143 | Serial.println(""); 144 | Serial.println("Reformatting card for Mifare Classic (please don't touch it!) ... "); 145 | 146 | // Now run through the card sector by sector 147 | for (idx = 0; idx < numOfSector; idx++) 148 | { 149 | // Step 1: Authenticate the current sector using key B 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 150 | success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), 1, (uint8_t *)KEY_DEFAULT_KEYAB); 151 | if (!success) 152 | { 153 | Serial.print("Authentication failed for sector "); Serial.println(numOfSector); 154 | return; 155 | } 156 | 157 | // Step 2: Write to the other blocks 158 | if (idx == 16) 159 | { 160 | memset(blockBuffer, 0, sizeof(blockBuffer)); 161 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer))) 162 | { 163 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 164 | return; 165 | } 166 | } 167 | if ((idx == 0) || (idx == 16)) 168 | { 169 | memset(blockBuffer, 0, sizeof(blockBuffer)); 170 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer))) 171 | { 172 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 173 | return; 174 | } 175 | } 176 | else 177 | { 178 | memset(blockBuffer, 0, sizeof(blockBuffer)); 179 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer))) 180 | { 181 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 182 | return; 183 | } 184 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer))) 185 | { 186 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 187 | return; 188 | } 189 | } 190 | memset(blockBuffer, 0, sizeof(blockBuffer)); 191 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, blockBuffer))) 192 | { 193 | Serial.print("Unable to write to sector "); Serial.println(numOfSector); 194 | return; 195 | } 196 | 197 | // Step 3: Reset both keys to 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 198 | memcpy(blockBuffer, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB)); 199 | memcpy(blockBuffer + 6, blankAccessBits, sizeof(blankAccessBits)); 200 | blockBuffer[9] = 0x69; 201 | memcpy(blockBuffer + 10, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB)); 202 | 203 | // Step 4: Write the trailer block 204 | if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), blockBuffer))) 205 | { 206 | Serial.print("Unable to write trailer block of sector "); Serial.println(numOfSector); 207 | return; 208 | } 209 | } 210 | } 211 | 212 | // Wait a bit before trying again 213 | Serial.println("\n\nDone!"); 214 | delay(1000); 215 | Serial.flush(); 216 | while(Serial.available()) Serial.read(); 217 | } -------------------------------------------------------------------------------- /Adafruit_PN532.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Adafruit_PN532.h 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 6 | 7 | 8 | This is a library for the Adafruit PN532 NFC/RFID breakout boards 9 | This library works with the Adafruit NFC breakout 10 | ----> https://www.adafruit.com/products/364 11 | 12 | Check out the links above for our tutorials and wiring diagrams 13 | These chips use SPI or I2C to communicate. 14 | 15 | Adafruit invests time and resources providing this open source code, 16 | please support Adafruit and open-source hardware by purchasing 17 | products from Adafruit! 18 | 19 | @section HISTORY 20 | 21 | v2.0 - Refactored to add I2C support from Adafruit_NFCShield_I2C library. 22 | 23 | v1.1 - Added full command list 24 | - Added 'verbose' mode flag to constructor to toggle debug output 25 | - Changed readPassiveTargetID() to return variable length values 26 | 27 | */ 28 | /**************************************************************************/ 29 | 30 | #ifndef ADAFRUIT_PN532_H 31 | #define ADAFRUIT_PN532_H 32 | 33 | #if ARDUINO >= 100 34 | #include "Arduino.h" 35 | #else 36 | #include "WProgram.h" 37 | #endif 38 | 39 | #define PN532_PREAMBLE (0x00) 40 | #define PN532_STARTCODE1 (0x00) 41 | #define PN532_STARTCODE2 (0xFF) 42 | #define PN532_POSTAMBLE (0x00) 43 | 44 | #define PN532_HOSTTOPN532 (0xD4) 45 | #define PN532_PN532TOHOST (0xD5) 46 | 47 | // PN532 Commands 48 | #define PN532_COMMAND_DIAGNOSE (0x00) 49 | #define PN532_COMMAND_GETFIRMWAREVERSION (0x02) 50 | #define PN532_COMMAND_GETGENERALSTATUS (0x04) 51 | #define PN532_COMMAND_READREGISTER (0x06) 52 | #define PN532_COMMAND_WRITEREGISTER (0x08) 53 | #define PN532_COMMAND_READGPIO (0x0C) 54 | #define PN532_COMMAND_WRITEGPIO (0x0E) 55 | #define PN532_COMMAND_SETSERIALBAUDRATE (0x10) 56 | #define PN532_COMMAND_SETPARAMETERS (0x12) 57 | #define PN532_COMMAND_SAMCONFIGURATION (0x14) 58 | #define PN532_COMMAND_POWERDOWN (0x16) 59 | #define PN532_COMMAND_RFCONFIGURATION (0x32) 60 | #define PN532_COMMAND_RFREGULATIONTEST (0x58) 61 | #define PN532_COMMAND_INJUMPFORDEP (0x56) 62 | #define PN532_COMMAND_INJUMPFORPSL (0x46) 63 | #define PN532_COMMAND_INLISTPASSIVETARGET (0x4A) 64 | #define PN532_COMMAND_INATR (0x50) 65 | #define PN532_COMMAND_INPSL (0x4E) 66 | #define PN532_COMMAND_INDATAEXCHANGE (0x40) 67 | #define PN532_COMMAND_INCOMMUNICATETHRU (0x42) 68 | #define PN532_COMMAND_INDESELECT (0x44) 69 | #define PN532_COMMAND_INRELEASE (0x52) 70 | #define PN532_COMMAND_INSELECT (0x54) 71 | #define PN532_COMMAND_INAUTOPOLL (0x60) 72 | #define PN532_COMMAND_TGINITASTARGET (0x8C) 73 | #define PN532_COMMAND_TGSETGENERALBYTES (0x92) 74 | #define PN532_COMMAND_TGGETDATA (0x86) 75 | #define PN532_COMMAND_TGSETDATA (0x8E) 76 | #define PN532_COMMAND_TGSETMETADATA (0x94) 77 | #define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88) 78 | #define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90) 79 | #define PN532_COMMAND_TGGETTARGETSTATUS (0x8A) 80 | 81 | #define PN532_RESPONSE_INDATAEXCHANGE (0x41) 82 | #define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B) 83 | 84 | #define PN532_WAKEUP (0x55) 85 | 86 | #define PN532_SPI_STATREAD (0x02) 87 | #define PN532_SPI_DATAWRITE (0x01) 88 | #define PN532_SPI_DATAREAD (0x03) 89 | #define PN532_SPI_READY (0x01) 90 | 91 | #define PN532_I2C_ADDRESS (0x48 >> 1) 92 | #define PN532_I2C_READBIT (0x01) 93 | #define PN532_I2C_BUSY (0x00) 94 | #define PN532_I2C_READY (0x01) 95 | #define PN532_I2C_READYTIMEOUT (20) 96 | 97 | #define PN532_MIFARE_ISO14443A (0x00) 98 | 99 | // Mifare Commands 100 | #define MIFARE_CMD_AUTH_A (0x60) 101 | #define MIFARE_CMD_AUTH_B (0x61) 102 | #define MIFARE_CMD_READ (0x30) 103 | #define MIFARE_CMD_WRITE (0xA0) 104 | #define MIFARE_CMD_TRANSFER (0xB0) 105 | #define MIFARE_CMD_DECREMENT (0xC0) 106 | #define MIFARE_CMD_INCREMENT (0xC1) 107 | #define MIFARE_CMD_STORE (0xC2) 108 | #define MIFARE_ULTRALIGHT_CMD_WRITE (0xA2) 109 | 110 | // Prefixes for NDEF Records (to identify record type) 111 | #define NDEF_URIPREFIX_NONE (0x00) 112 | #define NDEF_URIPREFIX_HTTP_WWWDOT (0x01) 113 | #define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02) 114 | #define NDEF_URIPREFIX_HTTP (0x03) 115 | #define NDEF_URIPREFIX_HTTPS (0x04) 116 | #define NDEF_URIPREFIX_TEL (0x05) 117 | #define NDEF_URIPREFIX_MAILTO (0x06) 118 | #define NDEF_URIPREFIX_FTP_ANONAT (0x07) 119 | #define NDEF_URIPREFIX_FTP_FTPDOT (0x08) 120 | #define NDEF_URIPREFIX_FTPS (0x09) 121 | #define NDEF_URIPREFIX_SFTP (0x0A) 122 | #define NDEF_URIPREFIX_SMB (0x0B) 123 | #define NDEF_URIPREFIX_NFS (0x0C) 124 | #define NDEF_URIPREFIX_FTP (0x0D) 125 | #define NDEF_URIPREFIX_DAV (0x0E) 126 | #define NDEF_URIPREFIX_NEWS (0x0F) 127 | #define NDEF_URIPREFIX_TELNET (0x10) 128 | #define NDEF_URIPREFIX_IMAP (0x11) 129 | #define NDEF_URIPREFIX_RTSP (0x12) 130 | #define NDEF_URIPREFIX_URN (0x13) 131 | #define NDEF_URIPREFIX_POP (0x14) 132 | #define NDEF_URIPREFIX_SIP (0x15) 133 | #define NDEF_URIPREFIX_SIPS (0x16) 134 | #define NDEF_URIPREFIX_TFTP (0x17) 135 | #define NDEF_URIPREFIX_BTSPP (0x18) 136 | #define NDEF_URIPREFIX_BTL2CAP (0x19) 137 | #define NDEF_URIPREFIX_BTGOEP (0x1A) 138 | #define NDEF_URIPREFIX_TCPOBEX (0x1B) 139 | #define NDEF_URIPREFIX_IRDAOBEX (0x1C) 140 | #define NDEF_URIPREFIX_FILE (0x1D) 141 | #define NDEF_URIPREFIX_URN_EPC_ID (0x1E) 142 | #define NDEF_URIPREFIX_URN_EPC_TAG (0x1F) 143 | #define NDEF_URIPREFIX_URN_EPC_PAT (0x20) 144 | #define NDEF_URIPREFIX_URN_EPC_RAW (0x21) 145 | #define NDEF_URIPREFIX_URN_EPC (0x22) 146 | #define NDEF_URIPREFIX_URN_NFC (0x23) 147 | 148 | #define PN532_GPIO_VALIDATIONBIT (0x80) 149 | #define PN532_GPIO_P30 (0) 150 | #define PN532_GPIO_P31 (1) 151 | #define PN532_GPIO_P32 (2) 152 | #define PN532_GPIO_P33 (3) 153 | #define PN532_GPIO_P34 (4) 154 | #define PN532_GPIO_P35 (5) 155 | 156 | class Adafruit_PN532{ 157 | public: 158 | Adafruit_PN532(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss); // Software SPI 159 | Adafruit_PN532(uint8_t irq, uint8_t reset); // Hardware I2C 160 | Adafruit_PN532(uint8_t ss); // Hardware SPI 161 | void begin(void); 162 | 163 | // Generic PN532 functions 164 | bool SAMConfig(void); 165 | uint32_t getFirmwareVersion(void); 166 | bool sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout = 1000); 167 | bool writeGPIO(uint8_t pinstate); 168 | uint8_t readGPIO(void); 169 | bool setPassiveActivationRetries(uint8_t maxRetries); 170 | 171 | // ISO14443A functions 172 | bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength, uint16_t timeout = 0); //timeout 0 means no timeout - will block forever. 173 | bool inDataExchange(uint8_t * send, uint8_t sendLength, uint8_t * response, uint8_t * responseLength); 174 | bool inListPassiveTarget(); 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, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData); 180 | uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data); 181 | uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data); 182 | uint8_t mifareclassic_FormatNDEF (void); 183 | uint8_t mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url); 184 | 185 | // Mifare Ultralight functions 186 | uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer); 187 | uint8_t mifareultralight_WritePage (uint8_t page, uint8_t * data); 188 | 189 | // NTAG2xx functions 190 | uint8_t ntag2xx_ReadPage (uint8_t page, uint8_t * buffer); 191 | uint8_t ntag2xx_WritePage (uint8_t page, uint8_t * data); 192 | uint8_t ntag2xx_WriteNDEFURI (uint8_t uriIdentifier, char * url, uint8_t dataLen); 193 | 194 | // Help functions to display formatted text 195 | static void PrintHex(const byte * data, const uint32_t numBytes); 196 | static void PrintHexChar(const byte * pbtData, const uint32_t numBytes); 197 | 198 | private: 199 | uint8_t _ss, _clk, _mosi, _miso; 200 | uint8_t _irq, _reset; 201 | uint8_t _uid[7]; // ISO14443A uid 202 | uint8_t _uidLen; // uid len 203 | uint8_t _key[6]; // Mifare Classic key 204 | uint8_t _inListedTag = 0x1 ; // Tg number of inlisted tag. Undefined tag nubmer (0x00) returns error. 205 | bool _usingSPI; // True if using SPI, false if using I2C. 206 | bool _hardwareSPI; // True is using hardware SPI, false if using software SPI. 207 | 208 | // Low level communication functions that handle both SPI and I2C. 209 | void readdata(uint8_t* buff, uint8_t n); 210 | void writecommand(uint8_t* cmd, uint8_t cmdlen); 211 | bool isready(); 212 | bool waitready(uint16_t timeout); 213 | bool readack(); 214 | 215 | // SPI-specific functions. 216 | void spi_write(uint8_t c); 217 | uint8_t spi_read(void); 218 | 219 | // Note there are i2c_read and i2c_write inline functions defined in the .cpp file. 220 | }; 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /examples/ApplePay_Troyka_ACS/ApplePay_Troyka_ACS.ino: -------------------------------------------------------------------------------- 1 | //Access Control Reader based on ApplePay (EMV) and Troyka cards 2 | 3 | 4 | #include 5 | 6 | // If using the breakout with SPI, define the pins for SPI communication. 7 | #define PN532_SCK (2) 8 | #define PN532_MOSI (3) 9 | #define PN532_SS (4) 10 | #define PN532_MISO (5) 11 | 12 | // Use this line for a breakout with a software SPI connection (recommended): 13 | Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); 14 | 15 | 16 | //EMV card global vars 17 | static const uint8_t aid_marker[] = {0x4F, 0x07}; 18 | static const uint8_t pan_marker[] = {0x5A, 0x08}; 19 | 20 | 21 | 22 | void setup(void) { 23 | Serial.begin(115200); 24 | Serial.println("Hello!"); 25 | 26 | nfc.begin(); 27 | 28 | uint32_t versiondata = nfc.getFirmwareVersion(); 29 | if (! versiondata) { 30 | Serial.print("Didn't find PN53x board"); 31 | while (1); // halt 32 | } 33 | // Got ok data, print it out! 34 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 35 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 36 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 37 | 38 | // configure board to read RFID tags 39 | nfc.SAMConfig(); 40 | 41 | Serial.println("Waiting for an ISO14443A Card ..."); 42 | } 43 | 44 | // dumb_memmem 45 | static char* dumb_memmem(const char* haystack, int hlen, const char* needle, int nlen) { 46 | // naive implementation 47 | if (nlen > hlen) return 0; 48 | int i; 49 | for (i=0; i 20) { 62 | void * searchresult = dumb_memmem(haystack, hlen, pan_marker, 2); 63 | if (searchresult) { 64 | memcpy(outbuff, searchresult + 2, 8); 65 | //Serial.print("Full PAN: "); 66 | //nfc.PrintHex(outbuff, 8); 67 | return 1; 68 | } 69 | return 0; 70 | 71 | } // end of if 72 | return 0; 73 | } //end of pan_search 74 | 75 | 76 | 77 | // Get Troyka serial from data block 78 | char * gettroykaserial(char * blockdata) 79 | { 80 | 81 | uint32_t serial_temp; 82 | char troykaserial[11]; 83 | 84 | 85 | // Parse Troyka 10 digits serial number (not UID) that printed on card 86 | // located from 3 byte up to 4 lower bits of 3 byte 87 | memcpy(&serial_temp, &(blockdata[3]), 4); 88 | 89 | // Covert MSB to LSB byte order 90 | serial_temp = ((serial_temp>>24)&0xf0) | // move half from byte 3 to byte 0 91 | ((serial_temp<<8)&0xff0000) | // move byte 1 to byte 2 92 | ((serial_temp>>8)&0xff00) | // move byte 2 to byte 1 93 | ((serial_temp<<24)&0xff000000); // byte 0 to byte 3 94 | 95 | // Shift to half byte to the right 96 | serial_temp = serial_temp >> 4; 97 | 98 | // Add zero's padding from the left if necessary 99 | sprintf(troykaserial, "%010lu", serial_temp); 100 | 101 | Serial.print("Troyka Serial: "); 102 | Serial.println(troykaserial); 103 | 104 | return troykaserial; 105 | } 106 | 107 | 108 | void loop(void) { 109 | uint8_t success; 110 | uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID 111 | uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) 112 | 113 | 114 | // Troyka 115 | uint8_t TroykaKeyA[6] = { 0xA7, 0x3F, 0x5D, 0xC1, 0xD3, 0x33 }; // Key А from 8 sector Troyka card 116 | uint8_t KeyTypeA = 0; 117 | uint8_t KeyTypeB = 1; 118 | uint8_t TroykaBlockAddr = 32; // Sector 8, block 0 (block number 32) 119 | 120 | // EMV card 121 | bool apdusuccess; 122 | uint8_t apdu[255]; 123 | uint8_t berBuffer[255]; 124 | uint8_t berLength = 255; 125 | uint8_t aid[7]; 126 | void *searchresult; 127 | uint8_t pan[8] = {0x00}; 128 | uint8_t pan_found = 0; 129 | char temp[3]; 130 | char * cardID; 131 | 132 | 133 | // Wait for an ISO14443A type cards (Mifare, etc.). When one is found 134 | // 'uid' will be populated with the UID, and uidLength will indicate length 135 | success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); 136 | 137 | if (success) { 138 | // Display some basic information about the card 139 | Serial.println(""); 140 | Serial.println(""); 141 | Serial.println("Found an ISO14443A card"); 142 | Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); 143 | Serial.print(" UID Value: "); 144 | nfc.PrintHex(uid, uidLength); 145 | Serial.println(""); 146 | 147 | if (uid) 148 | { 149 | 150 | if (uidLength == 7) 151 | { 152 | // If 7 bytes UID, we probably have a Troyka card 153 | // TODO: check ATS for detect mifare plus instead of UID length 154 | Serial.println("Seems to be a Troyka card (7 byte UID). Lets try authenticate it as Mifare Classic"); 155 | 156 | success = nfc.mifareclassic_AuthenticateBlock(uid+3, uidLength - 3, TroykaBlockAddr, KeyTypeA, TroykaKeyA); 157 | 158 | if (success) 159 | { 160 | Serial.println("Sector 8 (Blocks 32..35) has been authenticated"); 161 | uint8_t data[16]; 162 | 163 | // Try to read content of block 32 (sector 8 block 0) 164 | success = nfc.mifareclassic_ReadDataBlock(TroykaBlockAddr, data); 165 | 166 | // Extract Troyka serial from block data 167 | cardID = gettroykaserial(data); 168 | Serial.println("-----------------------"); 169 | Serial.print("Card ID: "); 170 | Serial.println(cardID); 171 | 172 | delay(2000); 173 | } // end of if (success) 174 | 175 | else 176 | { 177 | // If authentication failed, probably it's not mifare card 178 | // tryes to check for EMV card 179 | Serial.println("Failed to authenticate card as Mifare. Try to check for EMV card"); 180 | 181 | delay(2000); 182 | } 183 | } // end of if (uidLength == 7) 184 | 185 | else if (uidLength == 4) 186 | { 187 | // If 4 bytes UID, we probably have a EMV card 188 | Serial.println("Seems to be a EMV card (4 byte UID). Lets try to read PAN nubmer"); 189 | 190 | // Reading PSE file for AID number 191 | uint8_t apdu[] = {0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00}; 192 | apdusuccess = nfc.inDataExchange(apdu, sizeof(apdu), berBuffer, &berLength); 193 | 194 | if (apdusuccess) 195 | { 196 | if (berLength > 10) { 197 | searchresult = dumb_memmem(berBuffer, berLength, aid_marker, 2); 198 | if (searchresult) { 199 | memcpy(&aid, searchresult + 2, 7); 200 | //Serial.print("AID: "); 201 | //nfc.PrintHex(aid, 7); 202 | } 203 | } 204 | 205 | 206 | // Now start application on card (AID) 207 | uint8_t startAID[] = {0x00, 0xa4, 0x04, 0x00, 0x07, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 208 | memcpy(&startAID[5], &aid, 7); 209 | //Serial.print("StartAID is: "); nfc.PrintHex(startAID, sizeof(startAID)); 210 | berLength = 255; 211 | apdusuccess = nfc.inDataExchange(startAID, sizeof(startAID), berBuffer, &berLength); 212 | 213 | 214 | memset(pan, 0x00, 8); 215 | pan_found = 0; 216 | // Looking for PAN 217 | //uint8_t apdu1[] = {0x00, 0xb2, 0x01, 0x0c, 0x00}; 218 | //berLength = 255; 219 | //apdusuccess = nfc.inDataExchange(apdu1, sizeof(apdu1), berBuffer, &berLength); 220 | //Serial.print("berBuffer1 is: "); nfc.PrintHex(berBuffer, berLength); 221 | //pan_found = pan_search(berBuffer, berLength, pan); 222 | //if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found"); 223 | 224 | //uint8_t apdu2[] = {0x00, 0xb2, 0x02, 0x0c, 0x00}; 225 | //berLength = 255; 226 | //apdusuccess = nfc.inDataExchange(apdu2, sizeof(apdu2), berBuffer, &berLength); 227 | //Serial.print("berBuffer3 is: "); nfc.PrintHex(berBuffer, berLength); 228 | //if (!pan_found) 229 | //pan_found = pan_search(berBuffer, berLength, pan); 230 | //if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found"); 231 | 232 | uint8_t apdu3[] = {0x00, 0xb2, 0x01, 0x14, 0x00}; 233 | berLength = 255; 234 | apdusuccess = nfc.inDataExchange(apdu3, sizeof(apdu3), berBuffer, &berLength); 235 | //Serial.print("berBuffer4 is: "); nfc.PrintHex(berBuffer, berLength); 236 | if (!pan_found) 237 | pan_found = pan_search(berBuffer, berLength, pan); 238 | //if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found"); 239 | 240 | uint8_t apdu4[] = {0x00, 0xb2, 0x02, 0x14, 0x00}; 241 | uint8_t berLength = 255; 242 | apdusuccess = nfc.inDataExchange(apdu4, sizeof(apdu4), berBuffer, &berLength); 243 | //Serial.print("berBuffer5 is: "); nfc.PrintHex(berBuffer, berLength); 244 | if (!pan_found) 245 | pan_found = pan_search(berBuffer, berLength, pan); 246 | //if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found"); 247 | 248 | if (pan_found) { 249 | Serial.println("-----------------------"); 250 | Serial.print("Сard ID: "); 251 | for (int i = 3; i < 8; i++) { 252 | sprintf(temp, "%02x", pan[i]); 253 | Serial.print(temp); 254 | } 255 | } 256 | } 257 | 258 | 259 | } 260 | 261 | else 262 | { 263 | Serial.print("Abnormal UID Length: "); 264 | nfc.PrintHex(uid, uidLength); 265 | } 266 | 267 | } // end of if (uid) 268 | 269 | else 270 | { 271 | // Failed to read card 272 | Serial.println("Failed to read card. Retry after 2 seconds."); 273 | delay(2000); 274 | } 275 | } 276 | } 277 | 278 | -------------------------------------------------------------------------------- /Adafruit_PN532.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Adafruit_PN532.cpp 4 | @author Adafruit Industries 5 | @license BSD (see license.txt) 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 HISTORY 21 | 22 | v2.1 - Added NTAG2xx helper functions 23 | 24 | v2.0 - Refactored to add I2C support from Adafruit_NFCShield_I2C library. 25 | 26 | v1.4 - Added setPassiveActivationRetries() 27 | 28 | v1.2 - Added writeGPIO() 29 | - Added readGPIO() 30 | 31 | v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes 32 | - Added the following helper functions for text display 33 | static void PrintHex(const byte * data, const uint32_t numBytes) 34 | static void PrintHexChar(const byte * pbtData, const uint32_t numBytes) 35 | - Added the following Mifare Classic functions: 36 | bool mifareclassic_IsFirstBlock (uint32_t uiBlock) 37 | bool mifareclassic_IsTrailerBlock (uint32_t uiBlock) 38 | uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) 39 | uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) 40 | uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) 41 | - Added the following Mifare Ultalight functions: 42 | uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 43 | */ 44 | /**************************************************************************/ 45 | #if ARDUINO >= 100 46 | #include "Arduino.h" 47 | #else 48 | #include "WProgram.h" 49 | #endif 50 | 51 | #include 52 | #if defined(__AVR__) || defined(__i386__) || defined(ARDUINO_ARCH_SAMD) || defined(ESP8266) || defined(ARDUINO_ARCH_STM32) 53 | #define WIRE Wire 54 | #else // Arduino Due 55 | #define WIRE Wire1 56 | #endif 57 | 58 | #include 59 | 60 | #include "Adafruit_PN532.h" 61 | 62 | byte pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00}; 63 | byte pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03}; 64 | 65 | // Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE related code 66 | // #define PN532DEBUG 67 | // #define MIFAREDEBUG 68 | 69 | // If using Native Port on Arduino Zero or Due define as SerialUSB 70 | #define PN532DEBUGPRINT Serial 71 | //#define PN532DEBUGPRINT SerialUSB 72 | 73 | // Hardware SPI-specific configuration: 74 | #ifdef SPI_HAS_TRANSACTION 75 | #define PN532_SPI_SETTING SPISettings(1000000, LSBFIRST, SPI_MODE0) 76 | #else 77 | #define PN532_SPI_CLOCKDIV SPI_CLOCK_DIV16 78 | #endif 79 | 80 | #define PN532_PACKBUFFSIZ 255 81 | byte pn532_packetbuffer[PN532_PACKBUFFSIZ]; 82 | 83 | #ifndef _BV 84 | #define _BV(bit) (1<<(bit)) 85 | #endif 86 | 87 | /**************************************************************************/ 88 | /*! 89 | @brief Sends a single byte via I2C 90 | 91 | @param x The byte to send 92 | */ 93 | /**************************************************************************/ 94 | static inline void i2c_send(uint8_t x) 95 | { 96 | #if ARDUINO >= 100 97 | WIRE.write((uint8_t)x); 98 | #else 99 | WIRE.send(x); 100 | #endif 101 | } 102 | 103 | /**************************************************************************/ 104 | /*! 105 | @brief Reads a single byte via I2C 106 | */ 107 | /**************************************************************************/ 108 | static inline uint8_t i2c_recv(void) 109 | { 110 | #if ARDUINO >= 100 111 | return WIRE.read(); 112 | #else 113 | return WIRE.receive(); 114 | #endif 115 | } 116 | 117 | /**************************************************************************/ 118 | /*! 119 | @brief Instantiates a new PN532 class using software SPI. 120 | 121 | @param clk SPI clock pin (SCK) 122 | @param miso SPI MISO pin 123 | @param mosi SPI MOSI pin 124 | @param ss SPI chip select pin (CS/SSEL) 125 | */ 126 | /**************************************************************************/ 127 | Adafruit_PN532::Adafruit_PN532(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss): 128 | _clk(clk), 129 | _miso(miso), 130 | _mosi(mosi), 131 | _ss(ss), 132 | _irq(0), 133 | _reset(0), 134 | _usingSPI(true), 135 | _hardwareSPI(false) 136 | { 137 | pinMode(_ss, OUTPUT); 138 | pinMode(_clk, OUTPUT); 139 | pinMode(_mosi, OUTPUT); 140 | pinMode(_miso, INPUT); 141 | } 142 | 143 | /**************************************************************************/ 144 | /*! 145 | @brief Instantiates a new PN532 class using I2C. 146 | 147 | @param irq Location of the IRQ pin 148 | @param reset Location of the RSTPD_N pin 149 | */ 150 | /**************************************************************************/ 151 | Adafruit_PN532::Adafruit_PN532(uint8_t irq, uint8_t reset): 152 | _clk(0), 153 | _miso(0), 154 | _mosi(0), 155 | _ss(0), 156 | _irq(irq), 157 | _reset(reset), 158 | _usingSPI(false), 159 | _hardwareSPI(false) 160 | { 161 | pinMode(_irq, INPUT); 162 | pinMode(_reset, OUTPUT); 163 | } 164 | 165 | /**************************************************************************/ 166 | /*! 167 | @brief Instantiates a new PN532 class using hardware SPI. 168 | 169 | @param ss SPI chip select pin (CS/SSEL) 170 | */ 171 | /**************************************************************************/ 172 | Adafruit_PN532::Adafruit_PN532(uint8_t ss): 173 | _clk(0), 174 | _miso(0), 175 | _mosi(0), 176 | _ss(ss), 177 | _irq(0), 178 | _reset(0), 179 | _usingSPI(true), 180 | _hardwareSPI(true) 181 | { 182 | pinMode(_ss, OUTPUT); 183 | } 184 | 185 | /**************************************************************************/ 186 | /*! 187 | @brief Setups the HW 188 | */ 189 | /**************************************************************************/ 190 | void Adafruit_PN532::begin() { 191 | if (_usingSPI) { 192 | // SPI initialization 193 | if (_hardwareSPI) { 194 | SPI.begin(); 195 | 196 | #ifdef SPI_HAS_TRANSACTION 197 | SPI.beginTransaction(PN532_SPI_SETTING); 198 | #else 199 | SPI.setDataMode(SPI_MODE0); 200 | SPI.setBitOrder(LSBFIRST); 201 | SPI.setClockDivider(PN532_SPI_CLOCKDIV); 202 | #endif 203 | } 204 | digitalWrite(_ss, LOW); 205 | 206 | delay(1000); 207 | 208 | // not exactly sure why but we have to send a dummy command to get synced up 209 | pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; 210 | sendCommandCheckAck(pn532_packetbuffer, 1); 211 | 212 | // ignore response! 213 | 214 | digitalWrite(_ss, HIGH); 215 | #ifdef SPI_HAS_TRANSACTION 216 | if (_hardwareSPI) SPI.endTransaction(); 217 | #endif 218 | } 219 | else { 220 | // I2C initialization. 221 | WIRE.begin(); 222 | 223 | // Reset the PN532 224 | digitalWrite(_reset, HIGH); 225 | digitalWrite(_reset, LOW); 226 | delay(400); 227 | digitalWrite(_reset, HIGH); 228 | delay(10); // Small delay required before taking other actions after reset. 229 | // See timing diagram on page 209 of the datasheet, section 12.23. 230 | } 231 | } 232 | 233 | /**************************************************************************/ 234 | /*! 235 | @brief Prints a hexadecimal value in plain characters 236 | 237 | @param data Pointer to the byte data 238 | @param numBytes Data length in bytes 239 | */ 240 | /**************************************************************************/ 241 | void Adafruit_PN532::PrintHex(const byte * data, const uint32_t numBytes) 242 | { 243 | uint32_t szPos; 244 | for (szPos=0; szPos < numBytes; szPos++) 245 | { 246 | PN532DEBUGPRINT.print(F("0x")); 247 | // Append leading 0 for small values 248 | if (data[szPos] <= 0xF) 249 | PN532DEBUGPRINT.print(F("0")); 250 | PN532DEBUGPRINT.print(data[szPos]&0xff, HEX); 251 | if ((numBytes > 1) && (szPos != numBytes - 1)) 252 | { 253 | PN532DEBUGPRINT.print(F(" ")); 254 | } 255 | } 256 | PN532DEBUGPRINT.println(); 257 | } 258 | 259 | /**************************************************************************/ 260 | /*! 261 | @brief Prints a hexadecimal value in plain characters, along with 262 | the char equivalents in the following format 263 | 264 | 00 00 00 00 00 00 ...... 265 | 266 | @param data Pointer to the byte data 267 | @param numBytes Data length in bytes 268 | */ 269 | /**************************************************************************/ 270 | void Adafruit_PN532::PrintHexChar(const byte * data, const uint32_t numBytes) 271 | { 272 | uint32_t szPos; 273 | for (szPos=0; szPos < numBytes; szPos++) 274 | { 275 | // Append leading 0 for small values 276 | if (data[szPos] <= 0xF) 277 | PN532DEBUGPRINT.print(F("0")); 278 | PN532DEBUGPRINT.print(data[szPos], HEX); 279 | if ((numBytes > 1) && (szPos != numBytes - 1)) 280 | { 281 | PN532DEBUGPRINT.print(F(" ")); 282 | } 283 | } 284 | PN532DEBUGPRINT.print(F(" ")); 285 | for (szPos=0; szPos < numBytes; szPos++) 286 | { 287 | if (data[szPos] <= 0x1F) 288 | PN532DEBUGPRINT.print(F(".")); 289 | else 290 | PN532DEBUGPRINT.print((char)data[szPos]); 291 | } 292 | PN532DEBUGPRINT.println(); 293 | } 294 | 295 | /**************************************************************************/ 296 | /*! 297 | @brief Checks the firmware version of the PN5xx chip 298 | 299 | @returns The chip's firmware version and ID 300 | */ 301 | /**************************************************************************/ 302 | uint32_t Adafruit_PN532::getFirmwareVersion(void) { 303 | uint32_t response; 304 | 305 | pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; 306 | 307 | if (! sendCommandCheckAck(pn532_packetbuffer, 1)) { 308 | return 0; 309 | } 310 | 311 | // read data packet 312 | readdata(pn532_packetbuffer, 12); 313 | 314 | // check some basic stuff 315 | if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) { 316 | #ifdef PN532DEBUG 317 | PN532DEBUGPRINT.println(F("Firmware doesn't match!")); 318 | #endif 319 | return 0; 320 | } 321 | 322 | int offset = _usingSPI ? 6 : 7; // Skip a response byte when using I2C to ignore extra data. 323 | response = pn532_packetbuffer[offset++]; 324 | response <<= 8; 325 | response |= pn532_packetbuffer[offset++]; 326 | response <<= 8; 327 | response |= pn532_packetbuffer[offset++]; 328 | response <<= 8; 329 | response |= pn532_packetbuffer[offset++]; 330 | 331 | return response; 332 | } 333 | 334 | 335 | /**************************************************************************/ 336 | /*! 337 | @brief Sends a command and waits a specified period for the ACK 338 | 339 | @param cmd Pointer to the command buffer 340 | @param cmdlen The size of the command in bytes 341 | @param timeout timeout before giving up 342 | 343 | @returns 1 if everything is OK, 0 if timeout occured before an 344 | ACK was recieved 345 | */ 346 | /**************************************************************************/ 347 | // default timeout of one second 348 | bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) { 349 | uint16_t timer = 0; 350 | 351 | // write the command 352 | writecommand(cmd, cmdlen); 353 | 354 | // Wait for chip to say its ready! 355 | if (!waitready(timeout)) { 356 | return false; 357 | } 358 | 359 | #ifdef PN532DEBUG 360 | if (!_usingSPI) { 361 | PN532DEBUGPRINT.println(F("IRQ received")); 362 | } 363 | #endif 364 | 365 | // read acknowledgement 366 | if (!readack()) { 367 | #ifdef PN532DEBUG 368 | PN532DEBUGPRINT.println(F("No ACK frame received!")); 369 | #endif 370 | return false; 371 | } 372 | 373 | // For SPI only wait for the chip to be ready again. 374 | // This is unnecessary with I2C. 375 | if (_usingSPI) { 376 | if (!waitready(timeout)) { 377 | return false; 378 | } 379 | } 380 | 381 | return true; // ack'd command 382 | } 383 | 384 | /**************************************************************************/ 385 | /*! 386 | Writes an 8-bit value that sets the state of the PN532's GPIO pins 387 | 388 | @warning This function is provided exclusively for board testing and 389 | is dangerous since it will throw an error if any pin other 390 | than the ones marked "Can be used as GPIO" are modified! All 391 | pins that can not be used as GPIO should ALWAYS be left high 392 | (value = 1) or the system will become unstable and a HW reset 393 | will be required to recover the PN532. 394 | 395 | pinState[0] = P30 Can be used as GPIO 396 | pinState[1] = P31 Can be used as GPIO 397 | pinState[2] = P32 *** RESERVED (Must be 1!) *** 398 | pinState[3] = P33 Can be used as GPIO 399 | pinState[4] = P34 *** RESERVED (Must be 1!) *** 400 | pinState[5] = P35 Can be used as GPIO 401 | 402 | @returns 1 if everything executed properly, 0 for an error 403 | */ 404 | /**************************************************************************/ 405 | bool Adafruit_PN532::writeGPIO(uint8_t pinstate) { 406 | uint8_t errorbit; 407 | 408 | // Make sure pinstate does not try to toggle P32 or P34 409 | pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); 410 | 411 | // Fill command buffer 412 | pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; 413 | pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins 414 | pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by SPI) 415 | 416 | #ifdef PN532DEBUG 417 | PN532DEBUGPRINT.print(F("Writing P3 GPIO: ")); PN532DEBUGPRINT.println(pn532_packetbuffer[1], HEX); 418 | #endif 419 | 420 | // Send the WRITEGPIO command (0x0E) 421 | if (! sendCommandCheckAck(pn532_packetbuffer, 3)) 422 | return 0x0; 423 | 424 | // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 00) 425 | readdata(pn532_packetbuffer, 8); 426 | 427 | #ifdef PN532DEBUG 428 | PN532DEBUGPRINT.print(F("Received: ")); 429 | PrintHex(pn532_packetbuffer, 8); 430 | PN532DEBUGPRINT.println(); 431 | #endif 432 | 433 | int offset = _usingSPI ? 5 : 6; 434 | return (pn532_packetbuffer[offset] == 0x0F); 435 | } 436 | 437 | /**************************************************************************/ 438 | /*! 439 | Reads the state of the PN532's GPIO pins 440 | 441 | @returns An 8-bit value containing the pin state where: 442 | 443 | pinState[0] = P30 444 | pinState[1] = P31 445 | pinState[2] = P32 446 | pinState[3] = P33 447 | pinState[4] = P34 448 | pinState[5] = P35 449 | */ 450 | /**************************************************************************/ 451 | uint8_t Adafruit_PN532::readGPIO(void) { 452 | pn532_packetbuffer[0] = PN532_COMMAND_READGPIO; 453 | 454 | // Send the READGPIO command (0x0C) 455 | if (! sendCommandCheckAck(pn532_packetbuffer, 1)) 456 | return 0x0; 457 | 458 | // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 DATACHECKSUM 00) 459 | readdata(pn532_packetbuffer, 11); 460 | 461 | /* READGPIO response should be in the following format: 462 | 463 | byte Description 464 | ------------- ------------------------------------------ 465 | b0..5 Frame header and preamble (with I2C there is an extra 0x00) 466 | b6 P3 GPIO Pins 467 | b7 P7 GPIO Pins (not used ... taken by SPI) 468 | b8 Interface Mode Pins (not used ... bus select pins) 469 | b9..10 checksum */ 470 | 471 | int p3offset = _usingSPI ? 6 : 7; 472 | 473 | #ifdef PN532DEBUG 474 | PN532DEBUGPRINT.print(F("Received: ")); 475 | PrintHex(pn532_packetbuffer, 11); 476 | PN532DEBUGPRINT.println(); 477 | PN532DEBUGPRINT.print(F("P3 GPIO: 0x")); PN532DEBUGPRINT.println(pn532_packetbuffer[p3offset], HEX); 478 | PN532DEBUGPRINT.print(F("P7 GPIO: 0x")); PN532DEBUGPRINT.println(pn532_packetbuffer[p3offset+1], HEX); 479 | PN532DEBUGPRINT.print(F("IO GPIO: 0x")); PN532DEBUGPRINT.println(pn532_packetbuffer[p3offset+2], HEX); 480 | // Note: You can use the IO GPIO value to detect the serial bus being used 481 | switch(pn532_packetbuffer[p3offset+2]) 482 | { 483 | case 0x00: // Using UART 484 | PN532DEBUGPRINT.println(F("Using UART (IO = 0x00)")); 485 | break; 486 | case 0x01: // Using I2C 487 | PN532DEBUGPRINT.println(F("Using I2C (IO = 0x01)")); 488 | break; 489 | case 0x02: // Using SPI 490 | PN532DEBUGPRINT.println(F("Using SPI (IO = 0x02)")); 491 | break; 492 | } 493 | #endif 494 | 495 | return pn532_packetbuffer[p3offset]; 496 | } 497 | 498 | /**************************************************************************/ 499 | /*! 500 | @brief Configures the SAM (Secure Access Module) 501 | */ 502 | /**************************************************************************/ 503 | bool Adafruit_PN532::SAMConfig(void) { 504 | pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; 505 | pn532_packetbuffer[1] = 0x01; // normal mode; 506 | pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second 507 | pn532_packetbuffer[3] = 0x01; // use IRQ pin! 508 | 509 | if (! sendCommandCheckAck(pn532_packetbuffer, 4)) 510 | return false; 511 | 512 | // read data packet 513 | readdata(pn532_packetbuffer, 8); 514 | 515 | int offset = _usingSPI ? 5 : 6; 516 | return (pn532_packetbuffer[offset] == 0x15); 517 | } 518 | 519 | /**************************************************************************/ 520 | /*! 521 | Sets the MxRtyPassiveActivation byte of the RFConfiguration register 522 | 523 | @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout 524 | after mxRetries 525 | 526 | @returns 1 if everything executed properly, 0 for an error 527 | */ 528 | /**************************************************************************/ 529 | bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) { 530 | pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; 531 | pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) 532 | pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) 533 | pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) 534 | pn532_packetbuffer[4] = maxRetries; 535 | 536 | #ifdef MIFAREDEBUG 537 | PN532DEBUGPRINT.print(F("Setting MxRtyPassiveActivation to ")); PN532DEBUGPRINT.print(maxRetries, DEC); PN532DEBUGPRINT.println(F(" ")); 538 | #endif 539 | 540 | if (! sendCommandCheckAck(pn532_packetbuffer, 5)) 541 | return 0x0; // no ACK 542 | 543 | return 1; 544 | } 545 | 546 | /***** ISO14443A Commands ******/ 547 | 548 | /**************************************************************************/ 549 | /*! 550 | Waits for an ISO14443A target to enter the field 551 | 552 | @param cardBaudRate Baud rate of the card 553 | @param uid Pointer to the array that will be populated 554 | with the card's UID (up to 7 bytes) 555 | @param uidLength Pointer to the variable that will hold the 556 | length of the card's UID. 557 | 558 | @returns 1 if everything executed properly, 0 for an error 559 | */ 560 | /**************************************************************************/ 561 | bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength, uint16_t timeout) { 562 | pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; 563 | pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) 564 | pn532_packetbuffer[2] = cardbaudrate; 565 | 566 | if (!sendCommandCheckAck(pn532_packetbuffer, 3, timeout)) 567 | { 568 | #ifdef PN532DEBUG 569 | PN532DEBUGPRINT.println(F("No card(s) read")); 570 | #endif 571 | return 0x0; // no cards read 572 | } 573 | 574 | // wait for a card to enter the field (only possible with I2C) 575 | if (!_usingSPI) { 576 | #ifdef PN532DEBUG 577 | PN532DEBUGPRINT.println(F("Waiting for IRQ (indicates card presence)")); 578 | #endif 579 | if (!waitready(timeout)) { 580 | #ifdef PN532DEBUG 581 | PN532DEBUGPRINT.println(F("IRQ Timeout")); 582 | #endif 583 | return 0x0; 584 | } 585 | } 586 | 587 | // read data packet 588 | readdata(pn532_packetbuffer, 20); 589 | // check some basic stuff 590 | 591 | /* ISO14443A card response should be in the following format: 592 | 593 | byte Description 594 | ------------- ------------------------------------------ 595 | b0..6 Frame header and preamble 596 | b7 Tags Found 597 | b8 Tag Number (only one used in this example) 598 | b9..10 SENS_RES 599 | b11 SEL_RES 600 | b12 NFCID Length 601 | b13..NFCIDLen NFCID */ 602 | 603 | #ifdef MIFAREDEBUG 604 | PN532DEBUGPRINT.print(F("Found ")); PN532DEBUGPRINT.print(pn532_packetbuffer[7], DEC); PN532DEBUGPRINT.println(F(" tags")); 605 | #endif 606 | if (pn532_packetbuffer[7] != 1) 607 | return 0; 608 | 609 | uint16_t sens_res = pn532_packetbuffer[9]; 610 | sens_res <<= 8; 611 | sens_res |= pn532_packetbuffer[10]; 612 | #ifdef MIFAREDEBUG 613 | PN532DEBUGPRINT.print(F("ATQA: 0x")); PN532DEBUGPRINT.println(sens_res, HEX); 614 | PN532DEBUGPRINT.print(F("SAK: 0x")); PN532DEBUGPRINT.println(pn532_packetbuffer[11], HEX); 615 | #endif 616 | 617 | /* Card appears to be Mifare Classic */ 618 | *uidLength = pn532_packetbuffer[12]; 619 | #ifdef MIFAREDEBUG 620 | PN532DEBUGPRINT.print(F("UID:")); 621 | #endif 622 | for (uint8_t i=0; i < pn532_packetbuffer[12]; i++) 623 | { 624 | uid[i] = pn532_packetbuffer[13+i]; 625 | #ifdef MIFAREDEBUG 626 | PN532DEBUGPRINT.print(F(" 0x"));PN532DEBUGPRINT.print(uid[i], HEX); 627 | #endif 628 | } 629 | #ifdef MIFAREDEBUG 630 | PN532DEBUGPRINT.println(); 631 | #endif 632 | 633 | return 1; 634 | } 635 | 636 | /**************************************************************************/ 637 | /*! 638 | @brief Exchanges an APDU with the currently inlisted peer 639 | 640 | @param send Pointer to data to send 641 | @param sendLength Length of the data to send 642 | @param response Pointer to response data 643 | @param responseLength Pointer to the response data length 644 | */ 645 | /**************************************************************************/ 646 | bool Adafruit_PN532::inDataExchange(uint8_t * send, uint8_t sendLength, uint8_t * response, uint8_t * responseLength) { 647 | if (sendLength > PN532_PACKBUFFSIZ-2) { 648 | #ifdef PN532DEBUG 649 | PN532DEBUGPRINT.println(F("APDU length too long for packet buffer")); 650 | #endif 651 | return false; 652 | } 653 | uint8_t i; 654 | 655 | pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE; 656 | pn532_packetbuffer[1] = _inListedTag; 657 | for (i=0; i *responseLength) { 698 | length = *responseLength; // silent truncation... 699 | } 700 | 701 | for (i=0; i 15)) 1046 | return 0; 1047 | 1048 | // Make sure the URI payload is between 1 and 38 chars 1049 | if ((len < 1) || (len > 38)) 1050 | return 0; 1051 | 1052 | // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A 1053 | // in NDEF records 1054 | 1055 | // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) 1056 | uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len+5, 0xD1, 0x01, len+1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 1057 | uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 1058 | uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 1059 | uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 1060 | if (len <= 6) 1061 | { 1062 | // Unlikely we'll get a url this short, but why not ... 1063 | memcpy (sectorbuffer1+9, url, len); 1064 | sectorbuffer1[len+9] = 0xFE; 1065 | } 1066 | else if (len == 7) 1067 | { 1068 | // 0xFE needs to be wrapped around to next block 1069 | memcpy (sectorbuffer1+9, url, len); 1070 | sectorbuffer2[0] = 0xFE; 1071 | } 1072 | else if ((len > 7) && (len <= 22)) 1073 | { 1074 | // Url fits in two blocks 1075 | memcpy (sectorbuffer1+9, url, 7); 1076 | memcpy (sectorbuffer2, url+7, len-7); 1077 | sectorbuffer2[len-7] = 0xFE; 1078 | } 1079 | else if (len == 23) 1080 | { 1081 | // 0xFE needs to be wrapped around to final block 1082 | memcpy (sectorbuffer1+9, url, 7); 1083 | memcpy (sectorbuffer2, url+7, len-7); 1084 | sectorbuffer3[0] = 0xFE; 1085 | } 1086 | else 1087 | { 1088 | // Url fits in three blocks 1089 | memcpy (sectorbuffer1+9, url, 7); 1090 | memcpy (sectorbuffer2, url+7, 16); 1091 | memcpy (sectorbuffer3, url+23, len-24); 1092 | sectorbuffer3[len-22] = 0xFE; 1093 | } 1094 | 1095 | // Now write all three blocks back to the card 1096 | if (!(mifareclassic_WriteDataBlock (sectorNumber*4, sectorbuffer1))) 1097 | return 0; 1098 | if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+1, sectorbuffer2))) 1099 | return 0; 1100 | if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+2, sectorbuffer3))) 1101 | return 0; 1102 | if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+3, sectorbuffer4))) 1103 | return 0; 1104 | 1105 | // Seems that everything was OK (?!) 1106 | return 1; 1107 | } 1108 | 1109 | /***** Mifare Ultralight Functions ******/ 1110 | 1111 | /**************************************************************************/ 1112 | /*! 1113 | Tries to read an entire 4-byte page at the specified address. 1114 | 1115 | @param page The page number (0..63 in most cases) 1116 | @param buffer Pointer to the byte array that will hold the 1117 | retrieved data (if any) 1118 | */ 1119 | /**************************************************************************/ 1120 | uint8_t Adafruit_PN532::mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 1121 | { 1122 | if (page >= 64) 1123 | { 1124 | #ifdef MIFAREDEBUG 1125 | PN532DEBUGPRINT.println(F("Page value out of range")); 1126 | #endif 1127 | return 0; 1128 | } 1129 | 1130 | #ifdef MIFAREDEBUG 1131 | PN532DEBUGPRINT.print(F("Reading page "));PN532DEBUGPRINT.println(page); 1132 | #endif 1133 | 1134 | /* Prepare the command */ 1135 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1136 | pn532_packetbuffer[1] = 1; /* Card number */ 1137 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 1138 | pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ 1139 | 1140 | /* Send the command */ 1141 | if (! sendCommandCheckAck(pn532_packetbuffer, 4)) 1142 | { 1143 | #ifdef MIFAREDEBUG 1144 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1145 | #endif 1146 | return 0; 1147 | } 1148 | 1149 | /* Read the response packet */ 1150 | readdata(pn532_packetbuffer, 26); 1151 | #ifdef MIFAREDEBUG 1152 | PN532DEBUGPRINT.println(F("Received: ")); 1153 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1154 | #endif 1155 | 1156 | /* If byte 8 isn't 0x00 we probably have an error */ 1157 | if (pn532_packetbuffer[7] == 0x00) 1158 | { 1159 | /* Copy the 4 data bytes to the output buffer */ 1160 | /* Block content starts at byte 9 of a valid response */ 1161 | /* Note that the command actually reads 16 byte or 4 */ 1162 | /* pages at a time ... we simply discard the last 12 */ 1163 | /* bytes */ 1164 | memcpy (buffer, pn532_packetbuffer+8, 4); 1165 | } 1166 | else 1167 | { 1168 | #ifdef MIFAREDEBUG 1169 | PN532DEBUGPRINT.println(F("Unexpected response reading block: ")); 1170 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1171 | #endif 1172 | return 0; 1173 | } 1174 | 1175 | /* Display data for debug if requested */ 1176 | #ifdef MIFAREDEBUG 1177 | PN532DEBUGPRINT.print(F("Page "));PN532DEBUGPRINT.print(page);PN532DEBUGPRINT.println(F(":")); 1178 | Adafruit_PN532::PrintHexChar(buffer, 4); 1179 | #endif 1180 | 1181 | // Return OK signal 1182 | return 1; 1183 | } 1184 | 1185 | /**************************************************************************/ 1186 | /*! 1187 | Tries to write an entire 4-byte page at the specified block 1188 | address. 1189 | 1190 | @param page The page number to write. (0..63 for most cases) 1191 | @param data The byte array that contains the data to write. 1192 | Should be exactly 4 bytes long. 1193 | 1194 | @returns 1 if everything executed properly, 0 for an error 1195 | */ 1196 | /**************************************************************************/ 1197 | uint8_t Adafruit_PN532::mifareultralight_WritePage (uint8_t page, uint8_t * data) 1198 | { 1199 | 1200 | if (page >= 64) 1201 | { 1202 | #ifdef MIFAREDEBUG 1203 | PN532DEBUGPRINT.println(F("Page value out of range")); 1204 | #endif 1205 | // Return Failed Signal 1206 | return 0; 1207 | } 1208 | 1209 | #ifdef MIFAREDEBUG 1210 | PN532DEBUGPRINT.print(F("Trying to write 4 byte page"));PN532DEBUGPRINT.println(page); 1211 | #endif 1212 | 1213 | /* Prepare the first command */ 1214 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1215 | pn532_packetbuffer[1] = 1; /* Card number */ 1216 | pn532_packetbuffer[2] = MIFARE_ULTRALIGHT_CMD_WRITE; /* Mifare Ultralight Write command = 0xA2 */ 1217 | pn532_packetbuffer[3] = page; /* Page Number (0..63 for most cases) */ 1218 | memcpy (pn532_packetbuffer+4, data, 4); /* Data Payload */ 1219 | 1220 | /* Send the command */ 1221 | if (! sendCommandCheckAck(pn532_packetbuffer, 8)) 1222 | { 1223 | #ifdef MIFAREDEBUG 1224 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1225 | #endif 1226 | 1227 | // Return Failed Signal 1228 | return 0; 1229 | } 1230 | delay(10); 1231 | 1232 | /* Read the response packet */ 1233 | readdata(pn532_packetbuffer, 26); 1234 | 1235 | // Return OK Signal 1236 | return 1; 1237 | } 1238 | 1239 | 1240 | /***** NTAG2xx Functions ******/ 1241 | 1242 | /**************************************************************************/ 1243 | /*! 1244 | Tries to read an entire 4-byte page at the specified address. 1245 | 1246 | @param page The page number (0..63 in most cases) 1247 | @param buffer Pointer to the byte array that will hold the 1248 | retrieved data (if any) 1249 | */ 1250 | /**************************************************************************/ 1251 | uint8_t Adafruit_PN532::ntag2xx_ReadPage (uint8_t page, uint8_t * buffer) 1252 | { 1253 | // TAG Type PAGES USER START USER STOP 1254 | // -------- ----- ---------- --------- 1255 | // NTAG 203 42 4 39 1256 | // NTAG 213 45 4 39 1257 | // NTAG 215 135 4 129 1258 | // NTAG 216 231 4 225 1259 | 1260 | if (page >= 231) 1261 | { 1262 | #ifdef MIFAREDEBUG 1263 | PN532DEBUGPRINT.println(F("Page value out of range")); 1264 | #endif 1265 | return 0; 1266 | } 1267 | 1268 | #ifdef MIFAREDEBUG 1269 | PN532DEBUGPRINT.print(F("Reading page "));PN532DEBUGPRINT.println(page); 1270 | #endif 1271 | 1272 | /* Prepare the command */ 1273 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1274 | pn532_packetbuffer[1] = 1; /* Card number */ 1275 | pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 1276 | pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ 1277 | 1278 | /* Send the command */ 1279 | if (! sendCommandCheckAck(pn532_packetbuffer, 4)) 1280 | { 1281 | #ifdef MIFAREDEBUG 1282 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1283 | #endif 1284 | return 0; 1285 | } 1286 | 1287 | /* Read the response packet */ 1288 | readdata(pn532_packetbuffer, 26); 1289 | #ifdef MIFAREDEBUG 1290 | PN532DEBUGPRINT.println(F("Received: ")); 1291 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1292 | #endif 1293 | 1294 | /* If byte 8 isn't 0x00 we probably have an error */ 1295 | if (pn532_packetbuffer[7] == 0x00) 1296 | { 1297 | /* Copy the 4 data bytes to the output buffer */ 1298 | /* Block content starts at byte 9 of a valid response */ 1299 | /* Note that the command actually reads 16 byte or 4 */ 1300 | /* pages at a time ... we simply discard the last 12 */ 1301 | /* bytes */ 1302 | memcpy (buffer, pn532_packetbuffer+8, 4); 1303 | } 1304 | else 1305 | { 1306 | #ifdef MIFAREDEBUG 1307 | PN532DEBUGPRINT.println(F("Unexpected response reading block: ")); 1308 | Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 1309 | #endif 1310 | return 0; 1311 | } 1312 | 1313 | /* Display data for debug if requested */ 1314 | #ifdef MIFAREDEBUG 1315 | PN532DEBUGPRINT.print(F("Page "));PN532DEBUGPRINT.print(page);PN532DEBUGPRINT.println(F(":")); 1316 | Adafruit_PN532::PrintHexChar(buffer, 4); 1317 | #endif 1318 | 1319 | // Return OK signal 1320 | return 1; 1321 | } 1322 | 1323 | /**************************************************************************/ 1324 | /*! 1325 | Tries to write an entire 4-byte page at the specified block 1326 | address. 1327 | 1328 | @param page The page number to write. (0..63 for most cases) 1329 | @param data The byte array that contains the data to write. 1330 | Should be exactly 4 bytes long. 1331 | 1332 | @returns 1 if everything executed properly, 0 for an error 1333 | */ 1334 | /**************************************************************************/ 1335 | uint8_t Adafruit_PN532::ntag2xx_WritePage (uint8_t page, uint8_t * data) 1336 | { 1337 | // TAG Type PAGES USER START USER STOP 1338 | // -------- ----- ---------- --------- 1339 | // NTAG 203 42 4 39 1340 | // NTAG 213 45 4 39 1341 | // NTAG 215 135 4 129 1342 | // NTAG 216 231 4 225 1343 | 1344 | if ((page < 4) || (page > 225)) 1345 | { 1346 | #ifdef MIFAREDEBUG 1347 | PN532DEBUGPRINT.println(F("Page value out of range")); 1348 | #endif 1349 | // Return Failed Signal 1350 | return 0; 1351 | } 1352 | 1353 | #ifdef MIFAREDEBUG 1354 | PN532DEBUGPRINT.print(F("Trying to write 4 byte page"));PN532DEBUGPRINT.println(page); 1355 | #endif 1356 | 1357 | /* Prepare the first command */ 1358 | pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 1359 | pn532_packetbuffer[1] = 1; /* Card number */ 1360 | pn532_packetbuffer[2] = MIFARE_ULTRALIGHT_CMD_WRITE; /* Mifare Ultralight Write command = 0xA2 */ 1361 | pn532_packetbuffer[3] = page; /* Page Number (0..63 for most cases) */ 1362 | memcpy (pn532_packetbuffer+4, data, 4); /* Data Payload */ 1363 | 1364 | /* Send the command */ 1365 | if (! sendCommandCheckAck(pn532_packetbuffer, 8)) 1366 | { 1367 | #ifdef MIFAREDEBUG 1368 | PN532DEBUGPRINT.println(F("Failed to receive ACK for write command")); 1369 | #endif 1370 | 1371 | // Return Failed Signal 1372 | return 0; 1373 | } 1374 | delay(10); 1375 | 1376 | /* Read the response packet */ 1377 | readdata(pn532_packetbuffer, 26); 1378 | 1379 | // Return OK Signal 1380 | return 1; 1381 | } 1382 | 1383 | /**************************************************************************/ 1384 | /*! 1385 | Writes an NDEF URI Record starting at the specified page (4..nn) 1386 | 1387 | Note that this function assumes that the NTAG2xx card is 1388 | already formatted to work as an "NFC Forum Tag". 1389 | 1390 | @param uriIdentifier The uri identifier code (0 = none, 0x01 = 1391 | "http://www.", etc.) 1392 | @param url The uri text to write (null-terminated string). 1393 | @param dataLen The size of the data area for overflow checks. 1394 | 1395 | @returns 1 if everything executed properly, 0 for an error 1396 | */ 1397 | /**************************************************************************/ 1398 | uint8_t Adafruit_PN532::ntag2xx_WriteNDEFURI (uint8_t uriIdentifier, char * url, uint8_t dataLen) 1399 | { 1400 | uint8_t pageBuffer[4] = { 0, 0, 0, 0 }; 1401 | 1402 | // Remove NDEF record overhead from the URI data (pageHeader below) 1403 | uint8_t wrapperSize = 12; 1404 | 1405 | // Figure out how long the string is 1406 | uint8_t len = strlen(url); 1407 | 1408 | // Make sure the URI payload will fit in dataLen (include 0xFE trailer) 1409 | if ((len < 1) || (len+1 > (dataLen-wrapperSize))) 1410 | return 0; 1411 | 1412 | // Setup the record header 1413 | // See NFCForum-TS-Type-2-Tag_1.1.pdf for details 1414 | uint8_t pageHeader[12] = 1415 | { 1416 | /* NDEF Lock Control TLV (must be first and always present) */ 1417 | 0x01, /* Tag Field (0x01 = Lock Control TLV) */ 1418 | 0x03, /* Payload Length (always 3) */ 1419 | 0xA0, /* The position inside the tag of the lock bytes (upper 4 = page address, lower 4 = byte offset) */ 1420 | 0x10, /* Size in bits of the lock area */ 1421 | 0x44, /* Size in bytes of a page and the number of bytes each lock bit can lock (4 bit + 4 bits) */ 1422 | /* NDEF Message TLV - URI Record */ 1423 | 0x03, /* Tag Field (0x03 = NDEF Message) */ 1424 | len+5, /* Payload Length (not including 0xFE trailer) */ 1425 | 0xD1, /* NDEF Record Header (TNF=0x1:Well known record + SR + ME + MB) */ 1426 | 0x01, /* Type Length for the record type indicator */ 1427 | len+1, /* Payload len */ 1428 | 0x55, /* Record Type Indicator (0x55 or 'U' = URI Record) */ 1429 | uriIdentifier /* URI Prefix (ex. 0x01 = "http://www.") */ 1430 | }; 1431 | 1432 | // Write 12 byte header (three pages of data starting at page 4) 1433 | memcpy (pageBuffer, pageHeader, 4); 1434 | if (!(ntag2xx_WritePage (4, pageBuffer))) 1435 | return 0; 1436 | memcpy (pageBuffer, pageHeader+4, 4); 1437 | if (!(ntag2xx_WritePage (5, pageBuffer))) 1438 | return 0; 1439 | memcpy (pageBuffer, pageHeader+8, 4); 1440 | if (!(ntag2xx_WritePage (6, pageBuffer))) 1441 | return 0; 1442 | 1443 | // Write URI (starting at page 7) 1444 | uint8_t currentPage = 7; 1445 | char * urlcopy = url; 1446 | while(len) 1447 | { 1448 | if (len < 4) 1449 | { 1450 | memset(pageBuffer, 0, 4); 1451 | memcpy(pageBuffer, urlcopy, len); 1452 | pageBuffer[len] = 0xFE; // NDEF record footer 1453 | if (!(ntag2xx_WritePage (currentPage, pageBuffer))) 1454 | return 0; 1455 | // DONE! 1456 | return 1; 1457 | } 1458 | else if (len == 4) 1459 | { 1460 | memcpy(pageBuffer, urlcopy, len); 1461 | if (!(ntag2xx_WritePage (currentPage, pageBuffer))) 1462 | return 0; 1463 | memset(pageBuffer, 0, 4); 1464 | pageBuffer[0] = 0xFE; // NDEF record footer 1465 | currentPage++; 1466 | if (!(ntag2xx_WritePage (currentPage, pageBuffer))) 1467 | return 0; 1468 | // DONE! 1469 | return 1; 1470 | } 1471 | else 1472 | { 1473 | // More than one page of data left 1474 | memcpy(pageBuffer, urlcopy, 4); 1475 | if (!(ntag2xx_WritePage (currentPage, pageBuffer))) 1476 | return 0; 1477 | currentPage++; 1478 | urlcopy+=4; 1479 | len-=4; 1480 | } 1481 | } 1482 | 1483 | // Seems that everything was OK (?!) 1484 | return 1; 1485 | } 1486 | 1487 | 1488 | /************** high level communication functions (handles both I2C and SPI) */ 1489 | 1490 | 1491 | /**************************************************************************/ 1492 | /*! 1493 | @brief Tries to read the SPI or I2C ACK signal 1494 | */ 1495 | /**************************************************************************/ 1496 | bool Adafruit_PN532::readack() { 1497 | uint8_t ackbuff[6]; 1498 | 1499 | readdata(ackbuff, 6); 1500 | 1501 | return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6)); 1502 | } 1503 | 1504 | 1505 | /**************************************************************************/ 1506 | /*! 1507 | @brief Return true if the PN532 is ready with a response. 1508 | */ 1509 | /**************************************************************************/ 1510 | bool Adafruit_PN532::isready() { 1511 | if (_usingSPI) { 1512 | // SPI read status and check if ready. 1513 | #ifdef SPI_HAS_TRANSACTION 1514 | if (_hardwareSPI) SPI.beginTransaction(PN532_SPI_SETTING); 1515 | #endif 1516 | digitalWrite(_ss, LOW); 1517 | delay(2); 1518 | spi_write(PN532_SPI_STATREAD); 1519 | // read byte 1520 | uint8_t x = spi_read(); 1521 | 1522 | digitalWrite(_ss, HIGH); 1523 | #ifdef SPI_HAS_TRANSACTION 1524 | if (_hardwareSPI) SPI.endTransaction(); 1525 | #endif 1526 | 1527 | // Check if status is ready. 1528 | return x == PN532_SPI_READY; 1529 | } 1530 | else { 1531 | // I2C check if status is ready by IRQ line being pulled low. 1532 | uint8_t x = digitalRead(_irq); 1533 | return x == 0; 1534 | } 1535 | } 1536 | 1537 | /**************************************************************************/ 1538 | /*! 1539 | @brief Waits until the PN532 is ready. 1540 | 1541 | @param timeout Timeout before giving up 1542 | */ 1543 | /**************************************************************************/ 1544 | bool Adafruit_PN532::waitready(uint16_t timeout) { 1545 | uint16_t timer = 0; 1546 | while(!isready()) { 1547 | if (timeout != 0) { 1548 | timer += 10; 1549 | if (timer > timeout) { 1550 | PN532DEBUGPRINT.println("TIMEOUT!"); 1551 | return false; 1552 | } 1553 | } 1554 | delay(10); 1555 | } 1556 | return true; 1557 | } 1558 | 1559 | /**************************************************************************/ 1560 | /*! 1561 | @brief Reads n bytes of data from the PN532 via SPI or I2C. 1562 | 1563 | @param buff Pointer to the buffer where data will be written 1564 | @param n Number of bytes to be read 1565 | */ 1566 | /**************************************************************************/ 1567 | void Adafruit_PN532::readdata(uint8_t* buff, uint8_t n) { 1568 | if (_usingSPI) { 1569 | // SPI write. 1570 | #ifdef SPI_HAS_TRANSACTION 1571 | if (_hardwareSPI) SPI.beginTransaction(PN532_SPI_SETTING); 1572 | #endif 1573 | digitalWrite(_ss, LOW); 1574 | delay(2); 1575 | spi_write(PN532_SPI_DATAREAD); 1576 | 1577 | #ifdef PN532DEBUG 1578 | PN532DEBUGPRINT.print(F("Reading: ")); 1579 | #endif 1580 | for (uint8_t i=0; i