PN532 NFC shield of Adafruit based on PN532 of Seeed.

Fork of PN532 by Seeed

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