PN532 Driver library This library provides an abstract API to drive the pn532 nfc chip, with I2C/HSU/SPI interface. Its based on the Seeed Studio's Arduino version.

Dependents:   PN532_ReadUid Nfctest2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PN532.cpp Source File

PN532.cpp

Go to the documentation of this file.
00001 /**************************************************************************/
00002 /*!
00003     @file     PN532.cpp
00004     @author   Adafruit Industries & Seeed Studio
00005     @license  BSD
00006 */
00007 /**************************************************************************/
00008 
00009 #include "Arduino.h"
00010 #include "PN532.h "
00011 #include "PN532_debug.h"
00012 #include <string.h>
00013 
00014 #define HAL(func)   (_interface->func)
00015 
00016 PN532::PN532(PN532Interface &interface)
00017 {
00018     _interface = &interface;
00019 }
00020 
00021 /**************************************************************************/
00022 /*!
00023     @brief  Setups the HW
00024 */
00025 /**************************************************************************/
00026 void PN532::begin()
00027 {
00028     HAL(begin)();
00029     HAL(wakeup)();
00030 }
00031 
00032 /**************************************************************************/
00033 /*!
00034     @brief  Prints a hexadecimal value in plain characters
00035 
00036     @param  data      Pointer to the uint8_t data
00037     @param  numBytes  Data length in bytes
00038 */
00039 /**************************************************************************/
00040 void PN532::PrintHex(const uint8_t *data, const uint32_t numBytes)
00041 {
00042 #ifdef ARDUINO
00043     for (uint8_t i = 0; i < numBytes; i++) {
00044         if (data[i] < 0x10) {
00045             Serial.print(" 0");
00046         } else {
00047             Serial.print(' ');
00048         }
00049         Serial.print(data[i], HEX);
00050     }
00051     Serial.println("");
00052 #else
00053     for (uint8_t i = 0; i < numBytes; i++) {
00054         printf(" %2X", data[i]);
00055     }
00056     printf("\n");
00057 #endif
00058 }
00059 
00060 /**************************************************************************/
00061 /*!
00062     @brief  Prints a hexadecimal value in plain characters, along with
00063             the char equivalents in the following format
00064 
00065             00 00 00 00 00 00  ......
00066 
00067     @param  data      Pointer to the data
00068     @param  numBytes  Data length in bytes
00069 */
00070 /**************************************************************************/
00071 void PN532::PrintHexChar(const uint8_t *data, const uint32_t numBytes)
00072 {
00073 #ifdef ARDUINO
00074     for (uint8_t i = 0; i < numBytes; i++) {
00075         if (data[i] < 0x10) {
00076             Serial.print(" 0");
00077         } else {
00078             Serial.print(' ');
00079         }
00080         Serial.print(data[i], HEX);
00081     }
00082     Serial.print("    ");
00083     for (uint8_t i = 0; i < numBytes; i++) {
00084         char c = data[i];
00085         if (c <= 0x1f || c > 0x7f) {
00086             Serial.print('.');
00087         } else {
00088             Serial.print(c);
00089         }
00090     }
00091     Serial.println("");
00092 #else
00093     for (uint8_t i = 0; i < numBytes; i++) {
00094         printf(" %2X", data[i]);
00095     }
00096     printf("    ");
00097     for (uint8_t i = 0; i < numBytes; i++) {
00098         char c = data[i];
00099         if (c <= 0x1f || c > 0x7f) {
00100             printf(".");
00101         } else {
00102             printf("%c", c);
00103         }
00104         printf("\n");
00105     }
00106 #endif
00107 }
00108 
00109 /**************************************************************************/
00110 /*!
00111     @brief  Checks the firmware version of the PN5xx chip
00112 
00113     @returns  The chip's firmware version and ID
00114 */
00115 /**************************************************************************/
00116 uint32_t PN532::getFirmwareVersion(void)
00117 {
00118     uint32_t response;
00119 
00120     pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
00121 
00122     if (HAL(writeCommand)(pn532_packetbuffer, 1)) {
00123         return 0;
00124     }
00125 
00126     // read data packet
00127     int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00128     if (0 > status) {
00129         return 0;
00130     }
00131 
00132     response = pn532_packetbuffer[0];
00133     response <<= 8;
00134     response |= pn532_packetbuffer[1];
00135     response <<= 8;
00136     response |= pn532_packetbuffer[2];
00137     response <<= 8;
00138     response |= pn532_packetbuffer[3];
00139 
00140     return response;
00141 }
00142 
00143 
00144 /**************************************************************************/
00145 /*!
00146     Writes an 8-bit value that sets the state of the PN532's GPIO pins
00147 
00148     @warning This function is provided exclusively for board testing and
00149              is dangerous since it will throw an error if any pin other
00150              than the ones marked "Can be used as GPIO" are modified!  All
00151              pins that can not be used as GPIO should ALWAYS be left high
00152              (value = 1) or the system will become unstable and a HW reset
00153              will be required to recover the PN532.
00154 
00155              pinState[0]  = P30     Can be used as GPIO
00156              pinState[1]  = P31     Can be used as GPIO
00157              pinState[2]  = P32     *** RESERVED (Must be 1!) ***
00158              pinState[3]  = P33     Can be used as GPIO
00159              pinState[4]  = P34     *** RESERVED (Must be 1!) ***
00160              pinState[5]  = P35     Can be used as GPIO
00161 
00162     @returns 1 if everything executed properly, 0 for an error
00163 */
00164 /**************************************************************************/
00165 bool PN532::writeGPIO(uint8_t pinstate)
00166 {
00167     // Make sure pinstate does not try to toggle P32 or P34
00168     pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
00169 
00170     // Fill command buffer
00171     pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO;
00172     pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate;  // P3 Pins
00173     pn532_packetbuffer[2] = 0x00;    // P7 GPIO Pins (not used ... taken by I2C)
00174 
00175     DMSG("Writing P3 GPIO: ");
00176     DMSG_HEX(pn532_packetbuffer[1]);
00177     DMSG("\n");
00178 
00179     // Send the WRITEGPIO command (0x0E)
00180     if (HAL(writeCommand)(pn532_packetbuffer, 3))
00181         return 0;
00182 
00183     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
00184 }
00185 
00186 /**************************************************************************/
00187 /*!
00188     Reads the state of the PN532's GPIO pins
00189 
00190     @returns An 8-bit value containing the pin state where:
00191 
00192              pinState[0]  = P30
00193              pinState[1]  = P31
00194              pinState[2]  = P32
00195              pinState[3]  = P33
00196              pinState[4]  = P34
00197              pinState[5]  = P35
00198 */
00199 /**************************************************************************/
00200 uint8_t PN532::readGPIO(void)
00201 {
00202     pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;
00203 
00204     // Send the READGPIO command (0x0C)
00205     if (HAL(writeCommand)(pn532_packetbuffer, 1))
00206         return 0x0;
00207 
00208     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00209 
00210     /* READGPIO response without prefix and suffix should be in the following format:
00211 
00212       byte            Description
00213       -------------   ------------------------------------------
00214       b0              P3 GPIO Pins
00215       b1              P7 GPIO Pins (not used ... taken by I2C)
00216       b2              Interface Mode Pins (not used ... bus select pins)
00217     */
00218 
00219 
00220     DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]);
00221     DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]);
00222     DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]);
00223     DMSG("\n");
00224 
00225     return pn532_packetbuffer[0];
00226 }
00227 
00228 /**************************************************************************/
00229 /*!
00230     @brief  Configures the SAM (Secure Access Module)
00231 */
00232 /**************************************************************************/
00233 bool PN532::SAMConfig(void)
00234 {
00235     pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
00236     pn532_packetbuffer[1] = 0x01; // normal mode;
00237     pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
00238     pn532_packetbuffer[3] = 0x01; // use IRQ pin!
00239 
00240     DMSG("SAMConfig\n");
00241 
00242     if (HAL(writeCommand)(pn532_packetbuffer, 4))
00243         return false;
00244 
00245     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
00246 }
00247 
00248 /**************************************************************************/
00249 /*!
00250     Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
00251 
00252     @param  maxRetries    0xFF to wait forever, 0x00..0xFE to timeout
00253                           after mxRetries
00254 
00255     @returns 1 if everything executed properly, 0 for an error
00256 */
00257 /**************************************************************************/
00258 bool PN532::setPassiveActivationRetries(uint8_t maxRetries)
00259 {
00260     pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
00261     pn532_packetbuffer[1] = 5;    // Config item 5 (MaxRetries)
00262     pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
00263     pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
00264     pn532_packetbuffer[4] = maxRetries;
00265 
00266     if (HAL(writeCommand)(pn532_packetbuffer, 5))
00267         return 0x0;  // no ACK
00268 
00269     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
00270 }
00271 
00272 /***** ISO14443A Commands ******/
00273 
00274 /**************************************************************************/
00275 /*!
00276     Waits for an ISO14443A target to enter the field
00277 
00278     @param  cardBaudRate  Baud rate of the card
00279     @param  uid           Pointer to the array that will be populated
00280                           with the card's UID (up to 7 bytes)
00281     @param  uidLength     Pointer to the variable that will hold the
00282                           length of the card's UID.
00283     @param  timeout       The number of tries before timing out
00284     @param  inlist        If set to true, the card will be inlisted
00285 
00286     @returns 1 if everything executed properly, 0 for an error
00287 */
00288 /**************************************************************************/
00289 bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout, bool inlist)
00290 {
00291     pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
00292     pn532_packetbuffer[1] = 1;  // max 1 cards at once (we can set this to 2 later)
00293     pn532_packetbuffer[2] = cardbaudrate;
00294 
00295     if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
00296         return 0x0;  // command failed
00297     }
00298 
00299     // read data packet
00300     if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) {
00301         return 0x0;
00302     }
00303 
00304     // check some basic stuff
00305     /* ISO14443A card response should be in the following format:
00306 
00307       byte            Description
00308       -------------   ------------------------------------------
00309       b0              Tags Found
00310       b1              Tag Number (only one used in this example)
00311       b2..3           SENS_RES
00312       b4              SEL_RES
00313       b5              NFCID Length
00314       b6..NFCIDLen    NFCID
00315     */
00316 
00317     if (pn532_packetbuffer[0] != 1)
00318         return 0;
00319 
00320     uint16_t sens_res = pn532_packetbuffer[2];
00321     sens_res <<= 8;
00322     sens_res |= pn532_packetbuffer[3];
00323 
00324     DMSG("ATQA: 0x");  DMSG_HEX(sens_res);
00325     DMSG("\n");
00326     DMSG("SAK: 0x");  DMSG_HEX(pn532_packetbuffer[4]);
00327     DMSG("\n");
00328 
00329     /* Card appears to be Mifare Classic */
00330     *uidLength = pn532_packetbuffer[5];
00331 
00332     for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) {
00333         uid[i] = pn532_packetbuffer[6 + i];
00334     }
00335 
00336     if (inlist) {
00337         inListedTag = pn532_packetbuffer[1];
00338     }
00339 
00340     return 1;
00341 }
00342 
00343 
00344 /***** Mifare Classic Functions ******/
00345 
00346 /**************************************************************************/
00347 /*!
00348       Indicates whether the specified block number is the first block
00349       in the sector (block 0 relative to the current sector)
00350 */
00351 /**************************************************************************/
00352 bool PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock)
00353 {
00354     // Test if we are in the small or big sectors
00355     if (uiBlock < 128)
00356         return ((uiBlock) % 4 == 0);
00357     else
00358         return ((uiBlock) % 16 == 0);
00359 }
00360 
00361 /**************************************************************************/
00362 /*!
00363       Indicates whether the specified block number is the sector trailer
00364 */
00365 /**************************************************************************/
00366 bool PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock)
00367 {
00368     // Test if we are in the small or big sectors
00369     if (uiBlock < 128)
00370         return ((uiBlock + 1) % 4 == 0);
00371     else
00372         return ((uiBlock + 1) % 16 == 0);
00373 }
00374 
00375 /**************************************************************************/
00376 /*!
00377     Tries to authenticate a block of memory on a MIFARE card using the
00378     INDATAEXCHANGE command.  See section 7.3.8 of the PN532 User Manual
00379     for more information on sending MIFARE and other commands.
00380 
00381     @param  uid           Pointer to a byte array containing the card UID
00382     @param  uidLen        The length (in bytes) of the card's UID (Should
00383                           be 4 for MIFARE Classic)
00384     @param  blockNumber   The block number to authenticate.  (0..63 for
00385                           1KB cards, and 0..255 for 4KB cards).
00386     @param  keyNumber     Which key type to use during authentication
00387                           (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
00388     @param  keyData       Pointer to a byte array containing the 6 bytes
00389                           key value
00390 
00391     @returns 1 if everything executed properly, 0 for an error
00392 */
00393 /**************************************************************************/
00394 uint8_t PN532::mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
00395 {
00396     uint8_t i;
00397 
00398     // Hang on to the key and uid data
00399     memcpy (_key, keyData, 6);
00400     memcpy (_uid, uid, uidLen);
00401     _uidLen = uidLen;
00402 
00403     // Prepare the authentication command //
00404     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
00405     pn532_packetbuffer[1] = 1;                              /* Max card numbers */
00406     pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
00407     pn532_packetbuffer[3] = blockNumber;                    /* Block Number (1K = 0..63, 4K = 0..255 */
00408     memcpy (pn532_packetbuffer + 4, _key, 6);
00409     for (i = 0; i < _uidLen; i++) {
00410         pn532_packetbuffer[10 + i] = _uid[i];              /* 4 bytes card ID */
00411     }
00412 
00413     if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen))
00414         return 0;
00415 
00416     // Read the response packet
00417     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00418 
00419     // Check if the response is valid and we are authenticated???
00420     // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
00421     // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
00422     if (pn532_packetbuffer[0] != 0x00) {
00423         DMSG("Authentification failed\n");
00424         return 0;
00425     }
00426 
00427     return 1;
00428 }
00429 
00430 /**************************************************************************/
00431 /*!
00432     Tries to read an entire 16-bytes data block at the specified block
00433     address.
00434 
00435     @param  blockNumber   The block number to authenticate.  (0..63 for
00436                           1KB cards, and 0..255 for 4KB cards).
00437     @param  data          Pointer to the byte array that will hold the
00438                           retrieved data (if any)
00439 
00440     @returns 1 if everything executed properly, 0 for an error
00441 */
00442 /**************************************************************************/
00443 uint8_t PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
00444 {
00445     DMSG("Trying to read 16 bytes from block ");
00446     DMSG_INT(blockNumber);
00447 
00448     /* Prepare the command */
00449     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00450     pn532_packetbuffer[1] = 1;                      /* Card number */
00451     pn532_packetbuffer[2] = MIFARE_CMD_READ;        /* Mifare Read command = 0x30 */
00452     pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
00453 
00454     /* Send the command */
00455     if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
00456         return 0;
00457     }
00458 
00459     /* Read the response packet */
00460     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00461 
00462     /* If byte 8 isn't 0x00 we probably have an error */
00463     if (pn532_packetbuffer[0] != 0x00) {
00464         return 0;
00465     }
00466 
00467     /* Copy the 16 data bytes to the output buffer        */
00468     /* Block content starts at byte 9 of a valid response */
00469     memcpy (data, pn532_packetbuffer + 1, 16);
00470 
00471     return 1;
00472 }
00473 
00474 /**************************************************************************/
00475 /*!
00476     Tries to write an entire 16-bytes data block at the specified block
00477     address.
00478 
00479     @param  blockNumber   The block number to authenticate.  (0..63 for
00480                           1KB cards, and 0..255 for 4KB cards).
00481     @param  data          The byte array that contains the data to write.
00482 
00483     @returns 1 if everything executed properly, 0 for an error
00484 */
00485 /**************************************************************************/
00486 uint8_t PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
00487 {
00488     /* Prepare the first command */
00489     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00490     pn532_packetbuffer[1] = 1;                      /* Card number */
00491     pn532_packetbuffer[2] = MIFARE_CMD_WRITE;       /* Mifare Write command = 0xA0 */
00492     pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
00493     memcpy (pn532_packetbuffer + 4, data, 16);        /* Data Payload */
00494 
00495     /* Send the command */
00496     if (HAL(writeCommand)(pn532_packetbuffer, 20)) {
00497         return 0;
00498     }
00499 
00500     /* Read the response packet */
00501     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
00502 }
00503 
00504 /**************************************************************************/
00505 /*!
00506     Formats a Mifare Classic card to store NDEF Records
00507 
00508     @returns 1 if everything executed properly, 0 for an error
00509 */
00510 /**************************************************************************/
00511 uint8_t PN532::mifareclassic_FormatNDEF (void)
00512 {
00513     uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
00514     uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
00515     uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00516 
00517     // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A
00518     // for the MAD sector in NDEF records (sector 0)
00519 
00520     // Write block 1 and 2 to the card
00521     if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1)))
00522         return 0;
00523     if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2)))
00524         return 0;
00525     // Write key A and access rights card
00526     if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3)))
00527         return 0;
00528 
00529     // Seems that everything was OK (?!)
00530     return 1;
00531 }
00532 
00533 /**************************************************************************/
00534 /*!
00535     Writes an NDEF URI Record to the specified sector (1..15)
00536 
00537     Note that this function assumes that the Mifare Classic card is
00538     already formatted to work as an "NFC Forum Tag" and uses a MAD1
00539     file system.  You can use the NXP TagWriter app on Android to
00540     properly format cards for this.
00541 
00542     @param  sectorNumber  The sector that the URI record should be written
00543                           to (can be 1..15 for a 1K card)
00544     @param  uriIdentifier The uri identifier code (0 = none, 0x01 =
00545                           "http://www.", etc.)
00546     @param  url           The uri text to write (max 38 characters).
00547 
00548     @returns 1 if everything executed properly, 0 for an error
00549 */
00550 /**************************************************************************/
00551 uint8_t PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url)
00552 {
00553     // Figure out how long the string is
00554     uint8_t len = strlen(url);
00555 
00556     // Make sure we're within a 1K limit for the sector number
00557     if ((sectorNumber < 1) || (sectorNumber > 15))
00558         return 0;
00559 
00560     // Make sure the URI payload is between 1 and 38 chars
00561     if ((len < 1) || (len > 38))
00562         return 0;
00563 
00564     // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A
00565     // in NDEF records
00566 
00567     // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
00568     uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00569     uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00570     uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00571     uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00572     if (len <= 6) {
00573         // Unlikely we'll get a url this short, but why not ...
00574         memcpy (sectorbuffer1 + 9, url, len);
00575         sectorbuffer1[len + 9] = 0xFE;
00576     } else if (len == 7) {
00577         // 0xFE needs to be wrapped around to next block
00578         memcpy (sectorbuffer1 + 9, url, len);
00579         sectorbuffer2[0] = 0xFE;
00580     } else if ((len > 7) || (len <= 22)) {
00581         // Url fits in two blocks
00582         memcpy (sectorbuffer1 + 9, url, 7);
00583         memcpy (sectorbuffer2, url + 7, len - 7);
00584         sectorbuffer2[len - 7] = 0xFE;
00585     } else if (len == 23) {
00586         // 0xFE needs to be wrapped around to final block
00587         memcpy (sectorbuffer1 + 9, url, 7);
00588         memcpy (sectorbuffer2, url + 7, len - 7);
00589         sectorbuffer3[0] = 0xFE;
00590     } else {
00591         // Url fits in three blocks
00592         memcpy (sectorbuffer1 + 9, url, 7);
00593         memcpy (sectorbuffer2, url + 7, 16);
00594         memcpy (sectorbuffer3, url + 23, len - 24);
00595         sectorbuffer3[len - 22] = 0xFE;
00596     }
00597 
00598     // Now write all three blocks back to the card
00599     if (!(mifareclassic_WriteDataBlock (sectorNumber * 4, sectorbuffer1)))
00600         return 0;
00601     if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 1, sectorbuffer2)))
00602         return 0;
00603     if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 2, sectorbuffer3)))
00604         return 0;
00605     if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 3, sectorbuffer4)))
00606         return 0;
00607 
00608     // Seems that everything was OK (?!)
00609     return 1;
00610 }
00611 
00612 /***** Mifare Ultralight Functions ******/
00613 
00614 /**************************************************************************/
00615 /*!
00616     Tries to read an entire 4-bytes page at the specified address.
00617 
00618     @param  page        The page number (0..63 in most cases)
00619     @param  buffer      Pointer to the byte array that will hold the
00620                         retrieved data (if any)
00621 */
00622 /**************************************************************************/
00623 uint8_t PN532::mifareultralight_ReadPage (uint8_t page, uint8_t *buffer)
00624 {
00625     if (page >= 64) {
00626         DMSG("Page value out of range\n");
00627         return 0;
00628     }
00629 
00630     /* Prepare the command */
00631     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00632     pn532_packetbuffer[1] = 1;                   /* Card number */
00633     pn532_packetbuffer[2] = MIFARE_CMD_READ;     /* Mifare Read command = 0x30 */
00634     pn532_packetbuffer[3] = page;                /* Page Number (0..63 in most cases) */
00635 
00636     /* Send the command */
00637     if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
00638         return 0;
00639     }
00640 
00641     /* Read the response packet */
00642     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00643 
00644     /* If byte 8 isn't 0x00 we probably have an error */
00645     if (pn532_packetbuffer[0] == 0x00) {
00646         /* Copy the 4 data bytes to the output buffer         */
00647         /* Block content starts at byte 9 of a valid response */
00648         /* Note that the command actually reads 16 bytes or 4  */
00649         /* pages at a time ... we simply discard the last 12  */
00650         /* bytes                                              */
00651         memcpy (buffer, pn532_packetbuffer + 1, 4);
00652     } else {
00653         return 0;
00654     }
00655 
00656     // Return OK signal
00657     return 1;
00658 }
00659 
00660 /**************************************************************************/
00661 /*!
00662     Tries to write an entire 4-bytes data buffer at the specified page
00663     address.
00664 
00665     @param  page     The page number to write into.  (0..63).
00666     @param  buffer   The byte array that contains the data to write.
00667 
00668     @returns 1 if everything executed properly, 0 for an error
00669 */
00670 /**************************************************************************/
00671 uint8_t PN532::mifareultralight_WritePage (uint8_t page, uint8_t *buffer)
00672 {
00673     /* Prepare the first command */
00674     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00675     pn532_packetbuffer[1] = 1;                           /* Card number */
00676     pn532_packetbuffer[2] = MIFARE_CMD_WRITE_ULTRALIGHT; /* Mifare UL Write cmd = 0xA2 */
00677     pn532_packetbuffer[3] = page;                        /* page Number (0..63) */
00678     memcpy (pn532_packetbuffer + 4, buffer, 4);          /* Data Payload */
00679 
00680     /* Send the command */
00681     if (HAL(writeCommand)(pn532_packetbuffer, 8)) {
00682         return 0;
00683     }
00684 
00685     /* Read the response packet */
00686     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
00687 }
00688 
00689 /**************************************************************************/
00690 /*!
00691     @brief  Exchanges an APDU with the currently inlisted peer
00692 
00693     @param  send            Pointer to data to send
00694     @param  sendLength      Length of the data to send
00695     @param  response        Pointer to response data
00696     @param  responseLength  Pointer to the response data length
00697 */
00698 /**************************************************************************/
00699 bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength)
00700 {
00701     uint8_t i;
00702 
00703     pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
00704     pn532_packetbuffer[1] = inListedTag;
00705 
00706     if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) {
00707         return false;
00708     }
00709 
00710     int16_t status = HAL(readResponse)(response, *responseLength, 1000);
00711     if (status < 0) {
00712         return false;
00713     }
00714 
00715     if ((response[0] & 0x3f) != 0) {
00716         DMSG("Status code indicates an error\n");
00717         return false;
00718     }
00719 
00720     uint8_t length = status;
00721     length -= 1;
00722 
00723     if (length > *responseLength) {
00724         length = *responseLength; // silent truncation...
00725     }
00726 
00727     for (uint8_t i = 0; i < length; i++) {
00728         response[i] = response[i + 1];
00729     }
00730     *responseLength = length;
00731 
00732     return true;
00733 }
00734 
00735 /**************************************************************************/
00736 /*!
00737     @brief  'InLists' a passive target. PN532 acting as reader/initiator,
00738             peer acting as card/responder.
00739 */
00740 /**************************************************************************/
00741 bool PN532::inListPassiveTarget()
00742 {
00743     pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
00744     pn532_packetbuffer[1] = 1;
00745     pn532_packetbuffer[2] = 0;
00746 
00747     DMSG("inList passive target\n");
00748 
00749     if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
00750         return false;
00751     }
00752 
00753     int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 30000);
00754     if (status < 0) {
00755         return false;
00756     }
00757 
00758     if (pn532_packetbuffer[0] != 1) {
00759         return false;
00760     }
00761 
00762     inListedTag = pn532_packetbuffer[1];
00763 
00764     return true;
00765 }
00766 
00767 int8_t PN532::tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout){
00768   
00769   int8_t status = HAL(writeCommand)(command, len);
00770     if (status < 0) {
00771         return -1;
00772     }
00773 
00774     status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout);
00775     if (status > 0) {
00776         return 1;
00777     } else if (PN532_TIMEOUT == status) {
00778         return 0;
00779     } else {
00780         return -2;
00781     }
00782 }
00783 
00784 /**
00785  * Peer to Peer
00786  */
00787 int8_t PN532::tgInitAsTarget(uint16_t timeout)
00788 {
00789     const uint8_t command[] = {
00790         PN532_COMMAND_TGINITASTARGET,
00791         0,
00792         0x00, 0x00,         //SENS_RES
00793         0x00, 0x00, 0x00,   //NFCID1
00794         0x40,               //SEL_RES
00795 
00796         0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES
00797         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00798         0xFF, 0xFF,
00799 
00800         0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value
00801 
00802         0x0a, 0x46,  0x66, 0x6D, 0x01, 0x01, 0x10, 0x02, 0x02, 0x00, 0x80, // LLCP magic number, version parameter and MIUX
00803         0x00
00804     };
00805     return tgInitAsTarget(command, sizeof(command), timeout);
00806 }
00807 
00808 int16_t PN532::tgGetData(uint8_t *buf, uint8_t len)
00809 {
00810     buf[0] = PN532_COMMAND_TGGETDATA;
00811 
00812     if (HAL(writeCommand)(buf, 1)) {
00813         return -1;
00814     }
00815 
00816     int16_t status = HAL(readResponse)(buf, len, 3000);
00817     if (0 >= status) {
00818         return status;
00819     }
00820 
00821     uint16_t length = status - 1;
00822 
00823 
00824     if (buf[0] != 0) {
00825         DMSG("status is not ok\n");
00826         return -5;
00827     }
00828 
00829     for (uint8_t i = 0; i < length; i++) {
00830         buf[i] = buf[i + 1];
00831     }
00832 
00833     return length;
00834 }
00835 
00836 bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
00837 {
00838     if (hlen > (sizeof(pn532_packetbuffer) - 1)) {
00839         if ((body != 0) || (header == pn532_packetbuffer)) {
00840             DMSG("tgSetData:buffer too small\n");
00841             return false;
00842         }
00843 
00844         pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
00845         if (HAL(writeCommand)(pn532_packetbuffer, 1, header, hlen)) {
00846             return false;
00847         }
00848     } else {
00849         for (int8_t i = hlen - 1; i >= 0; i--){
00850             pn532_packetbuffer[i + 1] = header[i];
00851         }
00852         pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
00853 
00854         if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) {
00855             return false;
00856         }
00857     }
00858 
00859     if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) {
00860         return false;
00861     }
00862 
00863     if (0 != pn532_packetbuffer[0]) {
00864         return false;
00865     }
00866 
00867     return true;
00868 }
00869 
00870 int16_t PN532::inRelease(const uint8_t relevantTarget){
00871 
00872     pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
00873     pn532_packetbuffer[1] = relevantTarget;
00874 
00875     if (HAL(writeCommand)(pn532_packetbuffer, 2)) {
00876         return 0;
00877     }
00878 
00879     // read data packet
00880     return HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00881 }
00882 
00883