Milan Jovanovic / Mbed 2 deprecated readMifareORG

Dependencies:   mbed

Fork of readMifare by Interactive Device Design

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_PN532.cpp Source File

Adafruit_PN532.cpp

Go to the documentation of this file.
00001 /**************************************************************************/
00002 /*! 
00003     @file     Adafruit_PN532.cpp
00004     @author   Adafruit Industries
00005     @license  BSD (see license.txt)
00006     
00007     SPI Driver for NXP's PN532 NFC/13.56MHz RFID Transceiver
00008 
00009     This is a library for the Adafruit PN532 NFC/RFID breakout boards
00010     This library works with the Adafruit NFC breakout 
00011     ----> https://www.adafruit.com/products/364
00012     
00013     Check out the links above for our tutorials and wiring diagrams 
00014     These chips use SPI to communicate, 4 required to interface
00015     
00016     Adafruit invests time and resources providing this open source code, 
00017     please support Adafruit and open-source hardware by purchasing 
00018     products from Adafruit!
00019 
00020 
00021     @section  HISTORY
00022 
00023     v1.4 - Added setPassiveActivationRetries()
00024     
00025     v1.2 - Added writeGPIO()
00026          - Added readGPIO()
00027 
00028     v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes
00029          - Added the following helper functions for text display
00030              static void PrintHex(const uint8_t * data, const uint32_t numuint8_ts)
00031              static void PrintHexChar(const uint8_t * pbtData, const uint32_t numuint8_ts)
00032          - Added the following Mifare Classic functions:
00033              bool mifareclassic_IsFirstBlock (uint32_t uiBlock)
00034              bool mifareclassic_IsTrailerBlock (uint32_t uiBlock)
00035              uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData)
00036              uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
00037              uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
00038          - Added the following Mifare Ultalight functions:
00039              uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 
00040 */
00041 /**************************************************************************/
00042 
00043 #include "Adafruit_PN532.h "
00044 
00045 uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
00046 uint8_t pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
00047 
00048 // Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE related code
00049 // #define PN532DEBUG
00050 // #define MIFAREDEBUG
00051 
00052 Serial serial(USBTX, USBRX);
00053 #define SERIAL_PRINT serial.printf
00054 
00055 #define _BV(bit) (1 << (bit))
00056 #define PN532_PACKBUFFSIZ 64
00057 uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ];
00058 
00059 void delay(int delayInMS) {
00060   wait(1.0 * delayInMS / 1000);
00061 }
00062 
00063 /**************************************************************************/
00064 /*! 
00065     @brief  Instantiates a new PN532 class
00066 
00067     @param  clk       SPI clock pin (SCK)
00068     @param  miso      SPI MISO pin 
00069     @param  mosi      SPI MOSI pin
00070     @param  ss        SPI chip select pin (CS/SSEL)
00071 */
00072 /**************************************************************************/
00073 Adafruit_PN532::Adafruit_PN532(DigitalOut clk, DigitalIn miso,
00074                                DigitalOut mosi, DigitalOut ss)
00075     : _clk(clk), _miso(miso), _mosi(mosi), _ss(ss) {}
00076 
00077 Adafruit_PN532::Adafruit_PN532(PinName clk_pin, PinName miso_pin,
00078                                PinName mosi_pin, PinName ss_pin)
00079     : _clk(DigitalOut(clk_pin)), _miso(DigitalIn(miso_pin)),
00080       _mosi(DigitalOut(mosi_pin)), _ss(DigitalOut(ss_pin)) {}
00081 
00082 /**************************************************************************/
00083 /*! 
00084     @brief  Setups the HW
00085 */
00086 /**************************************************************************/
00087 void Adafruit_PN532::begin() {
00088   _ss = 0;  
00089   delay(1000);
00090 
00091   // not exactly sure why but we have to send a dummy command to get synced up
00092   pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
00093   sendCommandCheckAck(pn532_packetbuffer, 1);
00094 
00095   // ignore response!
00096 }
00097  
00098 /**************************************************************************/
00099 /*! 
00100     @brief  Prints a hexadecimal value in plain characters
00101 
00102     @param  data      Pointer to the uint8_t data
00103     @param  numuint8_ts  Data length in uint8_ts
00104 */
00105 /**************************************************************************/
00106 void Adafruit_PN532::PrintHex(const uint8_t * data, const uint32_t numuint8_ts)
00107 {
00108   uint32_t szPos;
00109   for (szPos=0; szPos < numuint8_ts; szPos++) 
00110   {
00111     SERIAL_PRINT("0x");
00112     // Append leading 0 for small values
00113     if (data[szPos] <= 0xF)
00114       SERIAL_PRINT("0");
00115     SERIAL_PRINT("%d", data[szPos]);
00116     if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1))
00117     {
00118       SERIAL_PRINT(" ");
00119     }
00120   }
00121   SERIAL_PRINT("\r\n");
00122 }
00123 
00124 /**************************************************************************/
00125 /*! 
00126     @brief  Prints a hexadecimal value in plain characters, along with
00127             the char equivalents in the following format
00128 
00129             00 00 00 00 00 00  ......
00130 
00131     @param  data      Pointer to the uint8_t data
00132     @param  numuint8_ts  Data length in uint8_ts
00133 */
00134 /**************************************************************************/
00135 void Adafruit_PN532::PrintHexChar(const uint8_t * data, const uint32_t numuint8_ts)
00136 {
00137   uint32_t szPos;
00138   for (szPos=0; szPos < numuint8_ts; szPos++) 
00139   {
00140     // Append leading 0 for small values
00141     if (data[szPos] <= 0xF)
00142       SERIAL_PRINT("0");
00143     SERIAL_PRINT("%x", data[szPos]);
00144     if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1))
00145     {
00146       SERIAL_PRINT(" ");
00147     }
00148   }
00149   SERIAL_PRINT(" ");
00150   for (szPos=0; szPos < numuint8_ts; szPos++) 
00151   {
00152     if (data[szPos] <= 0x1F)
00153       SERIAL_PRINT(".");
00154     else
00155       SERIAL_PRINT("%c", data[szPos]);
00156   }
00157   SERIAL_PRINT("");
00158 }
00159  
00160 /**************************************************************************/
00161 /*! 
00162     @brief  Checks the firmware version of the PN5xx chip
00163 
00164     @returns  The chip's firmware version and ID
00165 */
00166 /**************************************************************************/
00167 uint32_t Adafruit_PN532::getFirmwareVersion(void) {
00168   uint32_t response;
00169 
00170   pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
00171   
00172   if (! sendCommandCheckAck(pn532_packetbuffer, 1))
00173     return 0;
00174   
00175   // read data packet
00176   readspidata(pn532_packetbuffer, 12);
00177   
00178   // check some basic stuff
00179   if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
00180     return 0;
00181   }
00182   
00183   response = pn532_packetbuffer[6];
00184   response <<= 8;
00185   response |= pn532_packetbuffer[7];
00186   response <<= 8;
00187   response |= pn532_packetbuffer[8];
00188   response <<= 8;
00189   response |= pn532_packetbuffer[9];
00190 
00191   return response;
00192 }
00193 
00194 
00195 /**************************************************************************/
00196 /*! 
00197     @brief  Sends a command and waits a specified period for the ACK
00198 
00199     @param  cmd       Pointer to the command buffer
00200     @param  cmdlen    The size of the command in uint8_ts 
00201     @param  timeout   timeout before giving up
00202     
00203     @returns  1 if everything is OK, 0 if timeout occured before an
00204               ACK was recieved
00205 */
00206 /**************************************************************************/
00207 // default timeout of one second
00208 bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) {
00209   uint16_t timer = 0;
00210   
00211   // write the command
00212   spiwritecommand(cmd, cmdlen);
00213   
00214   // Wait for chip to say its ready!
00215   while (readspistatus() != PN532_SPI_READY) {
00216     if (timeout != 0) {
00217       timer+=10;
00218       if (timer > timeout)  
00219         return false;
00220     }
00221     delay(10);
00222   }
00223   
00224   // read acknowledgement
00225   if (!spi_readack()) {
00226     return false;
00227   }
00228   
00229   timer = 0;
00230   // Wait for chip to say its ready!
00231   while (readspistatus() != PN532_SPI_READY) {
00232     if (timeout != 0) {
00233       timer+=10;
00234       if (timer > timeout)  
00235         return false;
00236     }
00237     delay(10);
00238   }
00239   
00240   return true; // ack'd command
00241 }
00242 
00243 /**************************************************************************/
00244 /*! 
00245     Writes an 8-bit value that sets the state of the PN532's GPIO pins
00246     
00247     @warning This function is provided exclusively for board testing and
00248              is dangerous since it will throw an error if any pin other
00249              than the ones marked "Can be used as GPIO" are modified!  All
00250              pins that can not be used as GPIO should ALWAYS be left high
00251              (value = 1) or the system will become unstable and a HW reset
00252              will be required to recover the PN532.
00253     
00254              pinState[0]  = P30     Can be used as GPIO
00255              pinState[1]  = P31     Can be used as GPIO
00256              pinState[2]  = P32     *** RESERVED (Must be 1!) ***
00257              pinState[3]  = P33     Can be used as GPIO
00258              pinState[4]  = P34     *** RESERVED (Must be 1!) ***
00259              pinState[5]  = P35     Can be used as GPIO
00260     
00261     @returns 1 if everything executed properly, 0 for an error
00262 */
00263 /**************************************************************************/
00264 bool Adafruit_PN532::writeGPIO(uint8_t pinstate) {
00265   // Make sure pinstate does not try to toggle P32 or P34
00266   pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
00267   
00268   // Fill command buffer
00269   pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO;
00270   pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate;  // P3 Pins
00271   pn532_packetbuffer[2] = 0x00;    // P7 GPIO Pins (not used ... taken by SPI)
00272 
00273   #ifdef PN532DEBUG
00274     SERIAL_PRINT("Writing P3 GPIO: "); SERIAL_PRINTln(pn532_packetbuffer[1], HEX);
00275   #endif
00276 
00277   // Send the WRITEGPIO command (0x0E)  
00278   if (! sendCommandCheckAck(pn532_packetbuffer, 3))
00279     return 0x0;
00280   
00281   // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 00)
00282   readspidata(pn532_packetbuffer, 8);
00283 
00284   #ifdef PN532DEBUG
00285     SERIAL_PRINT("Received: ");
00286     PrintHex(pn532_packetbuffer, 8);
00287     SERIAL_PRINTln("");
00288   #endif  
00289   
00290   return  (pn532_packetbuffer[5] == 0x0F);
00291 }
00292 
00293 /**************************************************************************/
00294 /*! 
00295     Reads the state of the PN532's GPIO pins
00296     
00297     @returns An 8-bit value containing the pin state where:
00298     
00299              pinState[0]  = P30     
00300              pinState[1]  = P31     
00301              pinState[2]  = P32     
00302              pinState[3]  = P33     
00303              pinState[4]  = P34     
00304              pinState[5]  = P35     
00305 */
00306 /**************************************************************************/
00307 uint8_t Adafruit_PN532::readGPIO(void) {
00308   pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;
00309 
00310   // Send the READGPIO command (0x0C)  
00311   if (! sendCommandCheckAck(pn532_packetbuffer, 1))
00312     return 0x0;
00313   
00314   // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 DATACHECKSUM 00)
00315   readspidata(pn532_packetbuffer, 11);
00316 
00317   /* READGPIO response should be in the following format:
00318   
00319     uint8_t            Description
00320     -------------   ------------------------------------------
00321     b0..5           Frame header and preamble
00322     b6              P3 GPIO Pins
00323     b7              P7 GPIO Pins (not used ... taken by SPI)
00324     b8              Interface Mode Pins (not used ... bus select pins) 
00325     b9..10          checksum */
00326   
00327   #ifdef PN532DEBUG
00328     SERIAL_PRINT("Received: ");
00329     PrintHex(pn532_packetbuffer, 11);
00330     SERIAL_PRINTln("");
00331     SERIAL_PRINT("P3 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[6], HEX);
00332     SERIAL_PRINT("P7 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[7], HEX);
00333     SERIAL_PRINT("IO GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[8], HEX);
00334     // Note: You can use the IO GPIO value to detect the serial bus being used
00335     switch(pn532_packetbuffer[8])
00336     {
00337       case 0x00:    // Using UART
00338         SERIAL_PRINTln("Using UART (IO = 0x00)");
00339         break;
00340       case 0x01:    // Using I2C 
00341         SERIAL_PRINTln("Using I2C (IO = 0x01)");
00342         break;
00343       case 0x02:    // Using SPI
00344         SERIAL_PRINTln("Using SPI (IO = 0x02)");
00345         break;
00346     }
00347   #endif
00348 
00349   return pn532_packetbuffer[6];
00350 }
00351 
00352 /**************************************************************************/
00353 /*! 
00354     @brief  Configures the SAM (Secure Access Module)
00355 */
00356 /**************************************************************************/
00357 bool Adafruit_PN532::SAMConfig(void) {
00358   pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
00359   pn532_packetbuffer[1] = 0x01; // normal mode;
00360   pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
00361   pn532_packetbuffer[3] = 0x01; // use IRQ pin!
00362   
00363   if (! sendCommandCheckAck(pn532_packetbuffer, 4))
00364      return false;
00365 
00366   // read data packet
00367   readspidata(pn532_packetbuffer, 8);
00368   
00369   return  (pn532_packetbuffer[5] == 0x15);
00370 }
00371 
00372 /**************************************************************************/
00373 /*! 
00374     Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
00375     
00376     @param  maxRetries    0xFF to wait forever, 0x00..0xFE to timeout
00377                           after mxRetries
00378     
00379     @returns 1 if everything executed properly, 0 for an error
00380 */
00381 /**************************************************************************/
00382 bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) {
00383   pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
00384   pn532_packetbuffer[1] = 5;    // Config item 5 (MaxRetries)
00385   pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
00386   pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
00387   pn532_packetbuffer[4] = maxRetries;
00388 
00389 #ifdef MIFAREDEBUG
00390   SERIAL_PRINT("Setting MxRtyPassiveActivation to "); SERIAL_PRINT(maxRetries, DEC); SERIAL_PRINTln(" ");
00391 #endif
00392   
00393   if (! sendCommandCheckAck(pn532_packetbuffer, 5))
00394     return 0x0;  // no ACK
00395   
00396   return 1;
00397 }
00398 
00399 /***** ISO14443A Commands ******/
00400 
00401 /**************************************************************************/
00402 /*! 
00403     Waits for an ISO14443A target to enter the field
00404     
00405     @param  cardBaudRate  Baud rate of the card
00406     @param  uid           Pointer to the array that will be populated
00407                           with the card's UID (up to 7 uint8_ts)
00408     @param  uidLength     Pointer to the variable that will hold the
00409                           length of the card's UID.
00410     
00411     @returns 1 if everything executed properly, 0 for an error
00412 */
00413 /**************************************************************************/
00414 bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength) {
00415   pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
00416   pn532_packetbuffer[1] = 1;  // max 1 cards at once (we can set this to 2 later)
00417   pn532_packetbuffer[2] = cardbaudrate;
00418   
00419   if (! sendCommandCheckAck(pn532_packetbuffer, 3))
00420     return 0x0;  // no cards read
00421   
00422   // read data packet
00423   readspidata(pn532_packetbuffer, 20);
00424   // check some basic stuff
00425 
00426   /* ISO14443A card response should be in the following format:
00427   
00428     uint8_t            Description
00429     -------------   ------------------------------------------
00430     b0..6           Frame header and preamble
00431     b7              Tags Found
00432     b8              Tag Number (only one used in this example)
00433     b9..10          SENS_RES
00434     b11             SEL_RES
00435     b12             NFCID Length
00436     b13..NFCIDLen   NFCID                                      */
00437   
00438 #ifdef MIFAREDEBUG
00439     SERIAL_PRINT("Found "); SERIAL_PRINT(pn532_packetbuffer[7], DEC); SERIAL_PRINTln(" tags");
00440 #endif
00441   if (pn532_packetbuffer[7] != 1) 
00442     return 0;
00443     
00444   uint16_t sens_res = pn532_packetbuffer[9];
00445   sens_res <<= 8;
00446   sens_res |= pn532_packetbuffer[10];
00447 #ifdef MIFAREDEBUG
00448     SERIAL_PRINT("ATQA: 0x");  SERIAL_PRINTln(sens_res, HEX); 
00449     SERIAL_PRINT("SAK: 0x");  SERIAL_PRINTln(pn532_packetbuffer[11], HEX); 
00450 #endif
00451   
00452   /* Card appears to be Mifare Classic */
00453   *uidLength = pn532_packetbuffer[12];
00454 #ifdef MIFAREDEBUG
00455     SERIAL_PRINT("UID:"); 
00456 #endif
00457   for (uint8_t i=0; i < pn532_packetbuffer[12]; i++) 
00458   {
00459     uid[i] = pn532_packetbuffer[13+i];
00460 #ifdef MIFAREDEBUG
00461       SERIAL_PRINT(" 0x");SERIAL_PRINT(uid[i], HEX); 
00462 #endif
00463   }
00464 #ifdef MIFAREDEBUG
00465     SERIAL_PRINTln();
00466 #endif
00467 
00468   uint8_t bTestDeselect[2];
00469   bTestDeselect[0] = PN532_COMMAND_INDESELECT;
00470   bTestDeselect[1] = pn532_packetbuffer[8];
00471   sendCommandCheckAck(bTestDeselect,2);
00472 
00473   return 1;
00474 }
00475 
00476 
00477 /***** Mifare Classic Functions ******/
00478 
00479 /**************************************************************************/
00480 /*! 
00481       Indicates whether the specified block number is the first block
00482       in the sector (block 0 relative to the current sector)
00483 */
00484 /**************************************************************************/
00485 bool Adafruit_PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock)
00486 {
00487   // Test if we are in the small or big sectors
00488   if (uiBlock < 128)
00489     return ((uiBlock) % 4 == 0);
00490   else
00491     return ((uiBlock) % 16 == 0);
00492 }
00493 
00494 /**************************************************************************/
00495 /*! 
00496       Indicates whether the specified block number is the sector trailer
00497 */
00498 /**************************************************************************/
00499 bool Adafruit_PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock)
00500 {
00501   // Test if we are in the small or big sectors
00502   if (uiBlock < 128)
00503     return ((uiBlock + 1) % 4 == 0);
00504   else
00505     return ((uiBlock + 1) % 16 == 0);
00506 }
00507 
00508 /**************************************************************************/
00509 /*! 
00510     Tries to authenticate a block of memory on a MIFARE card using the
00511     INDATAEXCHANGE command.  See section 7.3.8 of the PN532 User Manual
00512     for more information on sending MIFARE and other commands.
00513 
00514     @param  uid           Pointer to a uint8_t array containing the card UID
00515     @param  uidLen        The length (in uint8_ts) of the card's UID (Should
00516                           be 4 for MIFARE Classic)
00517     @param  blockNumber   The block number to authenticate.  (0..63 for
00518                           1KB cards, and 0..255 for 4KB cards).
00519     @param  keyNumber     Which key type to use during authentication
00520                           (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
00521     @param  keyData       Pointer to a uint8_t array containing the 6 uint8_t
00522                           key value
00523     
00524     @returns 1 if everything executed properly, 0 for an error
00525 */
00526 /**************************************************************************/
00527 uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData)
00528 {
00529   uint8_t i;
00530   
00531   // Hang on to the key and uid data
00532   memcpy (_key, keyData, 6); 
00533   memcpy (_uid, uid, uidLen); 
00534   _uidLen = uidLen;  
00535 
00536   #ifdef MIFAREDEBUG
00537   SERIAL_PRINT("Trying to authenticate card ");
00538   Adafruit_PN532::PrintHex(_uid, _uidLen);
00539   SERIAL_PRINT("Using authentication KEY ");
00540   SERIAL_PRINT(keyNumber ? "B" : "A");
00541   SERIAL_PRINT(": ");
00542   Adafruit_PN532::PrintHex(_key, 6);
00543   #endif
00544   
00545   // Prepare the authentication command //
00546   pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
00547   pn532_packetbuffer[1] = 1;                              /* Max card numbers */
00548   pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
00549   pn532_packetbuffer[3] = blockNumber;                    /* Block Number (1K = 0..63, 4K = 0..255 */
00550   memcpy (pn532_packetbuffer+4, _key, 6);
00551   for (i = 0; i < _uidLen; i++)
00552   {
00553     pn532_packetbuffer[10+i] = _uid[i];                /* 4 uint8_t card ID */
00554   }
00555   
00556     printf("Auth request:\r\n");
00557     Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 10+_uidLen);
00558     printf("\r\n");
00559 
00560   if (! sendCommandCheckAck(pn532_packetbuffer, 10+_uidLen))
00561     return 0;
00562 
00563   // Read the response packet
00564   readspidata(pn532_packetbuffer, 12);
00565   // check if the response is valid and we are authenticated???
00566   // for an auth success it should be uint8_ts 5-7: 0xD5 0x41 0x00
00567   // Mifare auth error is technically uint8_t 7: 0x14 but anything other and 0x00 is not good
00568   if (pn532_packetbuffer[7] != 0x00)
00569   {
00570     #ifdef PN532DEBUG
00571     SERIAL_PRINT("Authentification failed: ");
00572     #endif
00573     return 0;
00574   }
00575     printf("Auth response:\r\n");
00576     Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 20);
00577     printf("\r\n");
00578   return 1;
00579 }
00580 
00581 /**************************************************************************/
00582 /*! 
00583     Tries to read an entire 16-uint8_t data block at the specified block
00584     address.
00585 
00586     @param  blockNumber   The block number to authenticate.  (0..63 for
00587                           1KB cards, and 0..255 for 4KB cards).
00588     @param  data          Pointer to the uint8_t array that will hold the
00589                           retrieved data (if any)
00590     
00591     @returns 1 if everything executed properly, 0 for an error
00592 */
00593 /**************************************************************************/
00594 uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
00595 {
00596   #ifdef MIFAREDEBUG
00597   SERIAL_PRINT("Trying to read 16 uint8_ts from block ");SERIAL_PRINTln(blockNumber);
00598   #endif
00599   
00600   /* Prepare the command */
00601   
00602   uint8_t pn532_packetbuffer2[PN532_PACKBUFFSIZ];
00603   pn532_packetbuffer2[0] = PN532_COMMAND_INDATAEXCHANGE; /* 0x40 */
00604   pn532_packetbuffer2[1] = 1;                      /* Card number */
00605   pn532_packetbuffer2[2] = MIFARE_CMD_READ;        /* Mifare Read command = 0x30 */
00606   pn532_packetbuffer2[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
00607   
00608     printf("Read request:\r\n");
00609     Adafruit_PN532::PrintHexChar(pn532_packetbuffer2, 4);
00610     printf("\r\n");
00611 
00612   /* Send the command */
00613   if (! sendCommandCheckAck(pn532_packetbuffer2, 4))
00614   {
00615     #ifdef MIFAREDEBUG
00616     SERIAL_PRINTln("Failed to receive ACK for read command");
00617     #endif
00618     return 0;
00619   }
00620 
00621   /* Read the response packet */
00622   readspidata(pn532_packetbuffer2, 26);
00623 
00624   /* If uint8_t 8 isn't 0x00 we probably have an error */
00625   if (pn532_packetbuffer2[7] != 0x00)
00626   {
00627     //#ifdef MIFAREDEBUG
00628     SERIAL_PRINT("Unexpected response");
00629     Adafruit_PN532::PrintHexChar(pn532_packetbuffer2, 26);
00630     //#endif
00631     return 0;
00632   }
00633     
00634   /* Copy the 16 data uint8_ts to the output buffer        */
00635   /* Block content starts at uint8_t 9 of a valid response */
00636   memcpy (data, pn532_packetbuffer2+8, 16);
00637 
00638   
00639     printf("Read response:\r\n");
00640     Adafruit_PN532::PrintHexChar(pn532_packetbuffer2, 26);
00641     printf("\r\n");
00642 
00643   return 1;  
00644 }
00645 
00646 /**************************************************************************/
00647 /*! 
00648     Tries to write an entire 16-uint8_t data block at the specified block
00649     address.
00650 
00651     @param  blockNumber   The block number to authenticate.  (0..63 for
00652                           1KB cards, and 0..255 for 4KB cards).
00653     @param  data          The uint8_t array that contains the data to write.
00654     
00655     @returns 1 if everything executed properly, 0 for an error
00656 */
00657 /**************************************************************************/
00658 uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
00659 {
00660   #ifdef MIFAREDEBUG
00661   SERIAL_PRINT("Trying to write 16 uint8_ts to block ");SERIAL_PRINTln(blockNumber);
00662   #endif
00663   
00664   /* Prepare the first command */
00665   pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00666   pn532_packetbuffer[1] = 1;                      /* Card number */
00667   pn532_packetbuffer[2] = MIFARE_CMD_WRITE;       /* Mifare Write command = 0xA0 */
00668   pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
00669   memcpy (pn532_packetbuffer+4, data, 16);          /* Data Payload */
00670 
00671   /* Send the command */
00672   if (! sendCommandCheckAck(pn532_packetbuffer, 20))
00673   {
00674     #ifdef MIFAREDEBUG
00675     SERIAL_PRINTln("Failed to receive ACK for write command");
00676     #endif
00677     return 0;
00678   }  
00679   delay(10);
00680   
00681   /* Read the response packet */
00682   readspidata(pn532_packetbuffer, 26);
00683 
00684   return 1;  
00685 }
00686 
00687 /**************************************************************************/
00688 /*! 
00689     Formats a Mifare Classic card to store NDEF Records 
00690     
00691     @returns 1 if everything executed properly, 0 for an error
00692 */
00693 /**************************************************************************/
00694 uint8_t Adafruit_PN532::mifareclassic_FormatNDEF (void)
00695 {
00696   uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
00697   uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
00698   uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00699 
00700   // Write block 1 and 2 to the card
00701   if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1)))
00702     return 0;
00703   if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2)))
00704     return 0;
00705   // Write key A and access rights card
00706   if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3)))
00707     return 0;
00708 
00709   // Seems that everything was OK (?!)
00710   return 1;
00711 }
00712 
00713 /**************************************************************************/
00714 /*! 
00715     Writes an NDEF URI Record to the specified sector (1..15)
00716     
00717     Note that this function assumes that the Mifare Classic card is
00718     already formatted to work as an "NFC Forum Tag" and uses a MAD1
00719     file system.  You can use the NXP TagWriter app on Android to
00720     properly format cards for this.
00721 
00722     @param  sectorNumber  The sector that the URI record should be written
00723                           to (can be 1..15 for a 1K card)
00724     @param  uriIdentifier The uri identifier code (0 = none, 0x01 = 
00725                           "http://www.", etc.)
00726     @param  url           The uri text to write (max 38 characters).
00727     
00728     @returns 1 if everything executed properly, 0 for an error
00729 */
00730 /**************************************************************************/
00731 uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url)
00732 {
00733   // Figure out how long the string is
00734   uint8_t len = strlen(url);
00735   
00736   // Make sure we're within a 1K limit for the sector number
00737   if ((sectorNumber < 1) || (sectorNumber > 15))
00738     return 0;
00739   
00740   // Make sure the URI payload is between 1 and 38 chars
00741   if ((len < 1) || (len > 38))
00742     return 0;
00743     
00744   // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
00745   uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len+5, 0xD1, 0x01, len+1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00746   uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00747   uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00748   uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00749   if (len <= 6)
00750   {
00751     // Unlikely we'll get a url this short, but why not ...
00752     memcpy (sectorbuffer1+9, url, len);
00753     sectorbuffer1[len+9] = 0xFE;
00754   }
00755   else if (len == 7)
00756   {
00757     // 0xFE needs to be wrapped around to next block
00758     memcpy (sectorbuffer1+9, url, len);
00759     sectorbuffer2[0] = 0xFE;
00760   }
00761   else if ((len > 7) || (len <= 22))
00762   {
00763     // Url fits in two blocks
00764     memcpy (sectorbuffer1+9, url, 7);
00765     memcpy (sectorbuffer2, url+7, len-7);
00766     sectorbuffer2[len-7] = 0xFE;
00767   }
00768   else if (len == 23)
00769   {
00770     // 0xFE needs to be wrapped around to final block
00771     memcpy (sectorbuffer1+9, url, 7);
00772     memcpy (sectorbuffer2, url+7, len-7);
00773     sectorbuffer3[0] = 0xFE;
00774   }
00775   else
00776   {
00777     // Url fits in three blocks
00778     memcpy (sectorbuffer1+9, url, 7);
00779     memcpy (sectorbuffer2, url+7, 16);
00780     memcpy (sectorbuffer3, url+23, len-24);
00781     sectorbuffer3[len-22] = 0xFE;
00782   }
00783   
00784   // Now write all three blocks back to the card
00785   if (!(mifareclassic_WriteDataBlock (sectorNumber*4, sectorbuffer1)))
00786     return 0;
00787   if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+1, sectorbuffer2)))
00788     return 0;
00789   if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+2, sectorbuffer3)))
00790     return 0;
00791   if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+3, sectorbuffer4)))
00792     return 0;
00793 
00794   // Seems that everything was OK (?!)
00795   return 1;
00796 }
00797 
00798 /***** Mifare Ultralight Functions ******/
00799 
00800 /**************************************************************************/
00801 /*! 
00802     Tries to read an entire 4-uint8_t page at the specified address.
00803 
00804     @param  page        The page number (0..63 in most cases)
00805     @param  buffer      Pointer to the uint8_t array that will hold the
00806                         retrieved data (if any)
00807 */
00808 /**************************************************************************/
00809 uint8_t Adafruit_PN532::mifareultralight_ReadPage (uint8_t page, uint8_t * buffer)
00810 {
00811   if (page >= 64)
00812   {
00813     #ifdef MIFAREDEBUG
00814     SERIAL_PRINTln("Page value out of range");
00815     #endif
00816     return 0;
00817   }
00818 
00819   #ifdef MIFAREDEBUG
00820     SERIAL_PRINT("Reading page ");SERIAL_PRINTln(page);
00821   #endif
00822 
00823   /* Prepare the command */
00824   pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00825   pn532_packetbuffer[1] = 1;                   /* Card number */
00826   pn532_packetbuffer[2] = MIFARE_CMD_READ;     /* Mifare Read command = 0x30 */
00827   pn532_packetbuffer[3] = page;                /* Page Number (0..63 in most cases) */
00828 
00829   /* Send the command */
00830   if (! sendCommandCheckAck(pn532_packetbuffer, 4))
00831   {
00832     #ifdef MIFAREDEBUG
00833     SERIAL_PRINTln("Failed to receive ACK for write command");
00834     #endif
00835     return 0;
00836   }
00837   
00838   /* Read the response packet */
00839   readspidata(pn532_packetbuffer, 26);
00840   #ifdef MIFAREDEBUG
00841     SERIAL_PRINTln("Received: ");
00842     Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
00843   #endif
00844 
00845   /* If uint8_t 8 isn't 0x00 we probably have an error */
00846   if (pn532_packetbuffer[7] == 0x00)
00847   {
00848     /* Copy the 4 data uint8_ts to the output buffer         */
00849     /* Block content starts at uint8_t 9 of a valid response */
00850     /* Note that the command actually reads 16 uint8_t or 4  */
00851     /* pages at a time ... we simply discard the last 12  */
00852     /* uint8_ts                                              */
00853     memcpy (buffer, pn532_packetbuffer+8, 4);
00854   }
00855   else
00856   {
00857     #ifdef MIFAREDEBUG
00858       SERIAL_PRINTln("Unexpected response reading block: ");
00859       Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26);
00860     #endif
00861     return 0;
00862   }
00863 
00864   /* Display data for debug if requested */
00865   #ifdef MIFAREDEBUG
00866     SERIAL_PRINT("Page ");SERIAL_PRINT(page);SERIAL_PRINTln(":");
00867     Adafruit_PN532::PrintHexChar(buffer, 4);
00868   #endif
00869 
00870   // Return OK signal
00871   return 1;
00872 }
00873 
00874 
00875 
00876 /************** high level SPI */
00877 
00878 
00879 /**************************************************************************/
00880 /*! 
00881     @brief  Tries to read the SPI ACK signal
00882 */
00883 /**************************************************************************/
00884 bool Adafruit_PN532::spi_readack() {
00885   uint8_t ackbuff[6];
00886   
00887   readspidata(ackbuff, 6);
00888   
00889   return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
00890 }
00891 
00892 /************** mid level SPI */
00893 
00894 /**************************************************************************/
00895 /*! 
00896     @brief  Reads the SPI status register (to know if the PN532 is ready)
00897 */
00898 /**************************************************************************/
00899 uint8_t Adafruit_PN532::readspistatus(void) {
00900   _ss = 0;
00901   delay(2);
00902   spiwrite(PN532_SPI_STATREAD);
00903   // read uint8_t
00904   uint8_t x = spiread();
00905   
00906   _ss = 1;
00907   return x;
00908 }
00909 
00910 /**************************************************************************/
00911 /*! 
00912     @brief  Reads n uint8_ts of data from the PN532 via SPI
00913 
00914     @param  buff      Pointer to the buffer where data will be written
00915     @param  n         Number of uint8_ts to be read
00916 */
00917 /**************************************************************************/
00918 void Adafruit_PN532::readspidata(uint8_t* buff, uint8_t n) {
00919   _ss = 0;
00920   delay(2); 
00921   spiwrite(PN532_SPI_DATAREAD);
00922 
00923 #ifdef PN532DEBUG
00924   SERIAL_PRINT("Reading: ");
00925 #endif
00926   for (uint8_t i=0; i<n; i++) {
00927     delay(1);
00928     buff[i] = spiread();
00929 #ifdef PN532DEBUG
00930     SERIAL_PRINT(" 0x");
00931     SERIAL_PRINT(buff[i], HEX);
00932 #endif
00933   }
00934 
00935 #ifdef PN532DEBUG
00936   SERIAL_PRINTln();
00937 #endif
00938 
00939   _ss = 1;
00940 }
00941 
00942 /**************************************************************************/
00943 /*! 
00944     @brief  Writes a command to the PN532, automatically inserting the
00945             preamble and required frame details (checksum, len, etc.)
00946 
00947     @param  cmd       Pointer to the command buffer
00948     @param  cmdlen    Command length in uint8_ts 
00949 */
00950 /**************************************************************************/
00951 void Adafruit_PN532::spiwritecommand(uint8_t* cmd, uint8_t cmdlen) {
00952   uint8_t checksum;
00953 
00954   cmdlen++;
00955   
00956 #ifdef PN532DEBUG
00957   SERIAL_PRINT("\r\nSending: ");
00958 #endif
00959 
00960   _ss = 0;
00961   delay(2);     // or whatever the delay is for waking up the board
00962   spiwrite(PN532_SPI_DATAWRITE);
00963 
00964   checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2;
00965   spiwrite(PN532_PREAMBLE);
00966   spiwrite(PN532_PREAMBLE);
00967   spiwrite(PN532_STARTCODE2);
00968 
00969   spiwrite(cmdlen);
00970   spiwrite(~cmdlen + 1);
00971  
00972   spiwrite(PN532_HOSTTOPN532);
00973   checksum += PN532_HOSTTOPN532;
00974 
00975 #ifdef PN532DEBUG
00976   SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX);
00977   SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX);
00978   SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_STARTCODE2, HEX);
00979   SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmdlen, HEX);
00980   SERIAL_PRINT(" 0x"); SERIAL_PRINT(~cmdlen + 1, HEX);
00981   SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_HOSTTOPN532, HEX);
00982 #endif
00983 
00984   for (uint8_t i=0; i<cmdlen-1; i++) {
00985    spiwrite(cmd[i]);
00986    checksum += cmd[i];
00987 #ifdef PN532DEBUG
00988    SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmd[i], HEX);
00989 #endif
00990   }
00991   
00992   spiwrite(~checksum);
00993   spiwrite(PN532_POSTAMBLE);
00994   _ss = 1;
00995 
00996 #ifdef PN532DEBUG
00997   SERIAL_PRINT(" 0x"); SERIAL_PRINT(~checksum, HEX);
00998   SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_POSTAMBLE, HEX);
00999   SERIAL_PRINTln();
01000 #endif
01001 } 
01002 /************** low level SPI */
01003 
01004 /**************************************************************************/
01005 /*! 
01006     @brief  Low-level SPI write wrapper
01007 
01008     @param  c       8-bit command to write to the SPI bus
01009 */
01010 /**************************************************************************/
01011 void Adafruit_PN532::spiwrite(uint8_t c) {
01012   int8_t i;
01013   _clk = 1;
01014   
01015   for (i=0; i<8; i++) {
01016     _clk = 0;
01017     if (c & _BV(i)) {
01018       _mosi = 1;
01019     } else {
01020       _mosi = 0;
01021     }
01022     _clk = 1;
01023   }
01024 }
01025 
01026 /**************************************************************************/
01027 /*! 
01028     @brief  Low-level SPI read wrapper
01029 
01030     @returns The 8-bit value that was read from the SPI bus
01031 */
01032 /**************************************************************************/
01033 uint8_t Adafruit_PN532::spiread(void) {
01034   int8_t i, x;
01035   x = 0;
01036   _clk = 1;
01037 
01038   for (i=0; i<8; i++) {
01039     if (_miso.read()) {
01040       x |= _BV(i);
01041     }
01042     _clk = 0;
01043     _clk = 1;
01044   }
01045   return x;
01046 }