NFC library using PN532 to read/write NDEF Messages to NFC tags

Dependents:   Seeed_NFC_Shield_write Nucleo_test_nfc

Fork of PN532 by Yihui Xiong

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 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 
00325     DMSG("ATQA: 0x");  DMSG_HEX(sens_res);
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     return 1;
00337 }
00338 
00339 
00340 /***** Mifare Classic Functions ******/
00341 
00342 /**************************************************************************/
00343 /*!
00344       Indicates whether the specified block number is the first block
00345       in the sector (block 0 relative to the current sector)
00346 */
00347 /**************************************************************************/
00348 bool PN532::mifareclassic_IsFirstBlock  (uint32_t uiBlock)
00349 {
00350     // Test if we are in the small or big sectors
00351     if (uiBlock < 128)
00352         return ((uiBlock) % 4 == 0);
00353     else
00354         return ((uiBlock) % 16 == 0);
00355 }
00356 
00357 /**************************************************************************/
00358 /*!
00359       Indicates whether the specified block number is the sector trailer
00360 */
00361 /**************************************************************************/
00362 bool PN532::mifareclassic_IsTrailerBlock  (uint32_t uiBlock)
00363 {
00364     // Test if we are in the small or big sectors
00365     if (uiBlock < 128)
00366         return ((uiBlock + 1) % 4 == 0);
00367     else
00368         return ((uiBlock + 1) % 16 == 0);
00369 }
00370 
00371 /**************************************************************************/
00372 /*!
00373     Tries to authenticate a block of memory on a MIFARE card using the
00374     INDATAEXCHANGE command.  See section 7.3.8 of the PN532 User Manual
00375     for more information on sending MIFARE and other commands.
00376 
00377     @param  uid           Pointer to a byte array containing the card UID
00378     @param  uidLen        The length (in bytes) of the card's UID (Should
00379                           be 4 for MIFARE Classic)
00380     @param  blockNumber   The block number to authenticate.  (0..63 for
00381                           1KB cards, and 0..255 for 4KB cards).
00382     @param  keyNumber     Which key type to use during authentication
00383                           (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
00384     @param  keyData       Pointer to a byte array containing the 6 bytes
00385                           key value
00386 
00387     @returns 1 if everything executed properly, 0 for an error
00388 */
00389 /**************************************************************************/
00390 uint8_t PN532::mifareclassic_AuthenticateBlock  (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
00391 {
00392     uint8_t i;
00393 
00394     // Hang on to the key and uid data
00395     memcpy (_key, keyData, 6);
00396     memcpy (_uid, uid, uidLen);
00397     _uidLen = uidLen;
00398 
00399     // Prepare the authentication command //
00400     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
00401     pn532_packetbuffer[1] = 1;                              /* Max card numbers */
00402     pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
00403     pn532_packetbuffer[3] = blockNumber;                    /* Block Number (1K = 0..63, 4K = 0..255 */
00404     memcpy (pn532_packetbuffer + 4, _key, 6);
00405     for (i = 0; i < _uidLen; i++) {
00406         pn532_packetbuffer[10 + i] = _uid[i];              /* 4 bytes card ID */
00407     }
00408 
00409     if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen))
00410         return 0;
00411 
00412     // Read the response packet
00413     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00414 
00415     // Check if the response is valid and we are authenticated???
00416     // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
00417     // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
00418     if (pn532_packetbuffer[0] != 0x00) {
00419         DMSG("Authentification failed\n");
00420         return 0;
00421     }
00422 
00423     return 1;
00424 }
00425 
00426 /**************************************************************************/
00427 /*!
00428     Tries to read an entire 16-bytes data block at the specified block
00429     address.
00430 
00431     @param  blockNumber   The block number to authenticate.  (0..63 for
00432                           1KB cards, and 0..255 for 4KB cards).
00433     @param  data          Pointer to the byte array that will hold the
00434                           retrieved data (if any)
00435 
00436     @returns 1 if everything executed properly, 0 for an error
00437 */
00438 /**************************************************************************/
00439 uint8_t PN532::mifareclassic_ReadDataBlock  (uint8_t blockNumber, uint8_t *data)
00440 {
00441     DMSG("Trying to read 16 bytes from block ");
00442     DMSG_INT(blockNumber);
00443 
00444     /* Prepare the command */
00445     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00446     pn532_packetbuffer[1] = 1;                      /* Card number */
00447     pn532_packetbuffer[2] = MIFARE_CMD_READ;        /* Mifare Read command = 0x30 */
00448     pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
00449 
00450     /* Send the command */
00451     if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
00452         return 0;
00453     }
00454 
00455     /* Read the response packet */
00456     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00457 
00458     /* If byte 8 isn't 0x00 we probably have an error */
00459     if (pn532_packetbuffer[0] != 0x00) {
00460         return 0;
00461     }
00462 
00463     /* Copy the 16 data bytes to the output buffer        */
00464     /* Block content starts at byte 9 of a valid response */
00465     memcpy (data, pn532_packetbuffer + 1, 16);
00466 
00467     return 1;
00468 }
00469 
00470 /**************************************************************************/
00471 /*!
00472     Tries to write an entire 16-bytes data block at the specified block
00473     address.
00474 
00475     @param  blockNumber   The block number to authenticate.  (0..63 for
00476                           1KB cards, and 0..255 for 4KB cards).
00477     @param  data          The byte array that contains the data to write.
00478 
00479     @returns 1 if everything executed properly, 0 for an error
00480 */
00481 /**************************************************************************/
00482 uint8_t PN532::mifareclassic_WriteDataBlock  (uint8_t blockNumber, uint8_t *data)
00483 {
00484     /* Prepare the first command */
00485     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00486     pn532_packetbuffer[1] = 1;                      /* Card number */
00487     pn532_packetbuffer[2] = MIFARE_CMD_WRITE;       /* Mifare Write command = 0xA0 */
00488     pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
00489     memcpy (pn532_packetbuffer + 4, data, 16);        /* Data Payload */
00490 
00491     /* Send the command */
00492     if (HAL(writeCommand)(pn532_packetbuffer, 20)) {
00493         return 0;
00494     }
00495 
00496     /* Read the response packet */
00497     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
00498 }
00499 
00500 /**************************************************************************/
00501 /*!
00502     Formats a Mifare Classic card to store NDEF Records
00503 
00504     @returns 1 if everything executed properly, 0 for an error
00505 */
00506 /**************************************************************************/
00507 uint8_t PN532::mifareclassic_FormatNDEF  (void)
00508 {
00509     uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
00510     uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
00511     uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00512 
00513     // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A
00514     // for the MAD sector in NDEF records (sector 0)
00515 
00516     // Write block 1 and 2 to the card
00517     if (!(mifareclassic_WriteDataBlock  (1, sectorbuffer1)))
00518         return 0;
00519     if (!(mifareclassic_WriteDataBlock  (2, sectorbuffer2)))
00520         return 0;
00521     // Write key A and access rights card
00522     if (!(mifareclassic_WriteDataBlock  (3, sectorbuffer3)))
00523         return 0;
00524 
00525     // Seems that everything was OK (?!)
00526     return 1;
00527 }
00528 
00529 /**************************************************************************/
00530 /*!
00531     Writes an NDEF URI Record to the specified sector (1..15)
00532 
00533     Note that this function assumes that the Mifare Classic card is
00534     already formatted to work as an "NFC Forum Tag" and uses a MAD1
00535     file system.  You can use the NXP TagWriter app on Android to
00536     properly format cards for this.
00537 
00538     @param  sectorNumber  The sector that the URI record should be written
00539                           to (can be 1..15 for a 1K card)
00540     @param  uriIdentifier The uri identifier code (0 = none, 0x01 =
00541                           "http://www.", etc.)
00542     @param  url           The uri text to write (max 38 characters).
00543 
00544     @returns 1 if everything executed properly, 0 for an error
00545 */
00546 /**************************************************************************/
00547 uint8_t PN532::mifareclassic_WriteNDEFURI  (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url)
00548 {
00549     // Figure out how long the string is
00550     uint8_t len = strlen(url);
00551 
00552     // Make sure we're within a 1K limit for the sector number
00553     if ((sectorNumber < 1) || (sectorNumber > 15))
00554         return 0;
00555 
00556     // Make sure the URI payload is between 1 and 38 chars
00557     if ((len < 1) || (len > 38))
00558         return 0;
00559 
00560     // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A
00561     // in NDEF records
00562 
00563     // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
00564     uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00565     uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00566     uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00567     uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00568     if (len <= 6) {
00569         // Unlikely we'll get a url this short, but why not ...
00570         memcpy (sectorbuffer1 + 9, url, len);
00571         sectorbuffer1[len + 9] = 0xFE;
00572     } else if (len == 7) {
00573         // 0xFE needs to be wrapped around to next block
00574         memcpy (sectorbuffer1 + 9, url, len);
00575         sectorbuffer2[0] = 0xFE;
00576     } else if ((len > 7) || (len <= 22)) {
00577         // Url fits in two blocks
00578         memcpy (sectorbuffer1 + 9, url, 7);
00579         memcpy (sectorbuffer2, url + 7, len - 7);
00580         sectorbuffer2[len - 7] = 0xFE;
00581     } else if (len == 23) {
00582         // 0xFE needs to be wrapped around to final block
00583         memcpy (sectorbuffer1 + 9, url, 7);
00584         memcpy (sectorbuffer2, url + 7, len - 7);
00585         sectorbuffer3[0] = 0xFE;
00586     } else {
00587         // Url fits in three blocks
00588         memcpy (sectorbuffer1 + 9, url, 7);
00589         memcpy (sectorbuffer2, url + 7, 16);
00590         memcpy (sectorbuffer3, url + 23, len - 24);
00591         sectorbuffer3[len - 22] = 0xFE;
00592     }
00593 
00594     // Now write all three blocks back to the card
00595     if (!(mifareclassic_WriteDataBlock  (sectorNumber * 4, sectorbuffer1)))
00596         return 0;
00597     if (!(mifareclassic_WriteDataBlock  ((sectorNumber * 4) + 1, sectorbuffer2)))
00598         return 0;
00599     if (!(mifareclassic_WriteDataBlock  ((sectorNumber * 4) + 2, sectorbuffer3)))
00600         return 0;
00601     if (!(mifareclassic_WriteDataBlock  ((sectorNumber * 4) + 3, sectorbuffer4)))
00602         return 0;
00603 
00604     // Seems that everything was OK (?!)
00605     return 1;
00606 }
00607 
00608 /***** Mifare Ultralight Functions ******/
00609 
00610 /**************************************************************************/
00611 /*!
00612     Tries to read an entire 4-bytes page at the specified address.
00613 
00614     @param  page        The page number (0..63 in most cases)
00615     @param  buffer      Pointer to the byte array that will hold the
00616                         retrieved data (if any)
00617 */
00618 /**************************************************************************/
00619 uint8_t PN532::mifareultralight_ReadPage  (uint8_t page, uint8_t *buffer)
00620 {
00621     if (page >= 64) {
00622         DMSG("Page value out of range\n");
00623         return 0;
00624     }
00625 
00626     /* Prepare the command */
00627     pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
00628     pn532_packetbuffer[1] = 1;                   /* Card number */
00629     pn532_packetbuffer[2] = MIFARE_CMD_READ;     /* Mifare Read command = 0x30 */
00630     pn532_packetbuffer[3] = page;                /* Page Number (0..63 in most cases) */
00631 
00632     /* Send the command */
00633     if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
00634         return 0;
00635     }
00636 
00637     /* Read the response packet */
00638     HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00639 
00640     /* If byte 8 isn't 0x00 we probably have an error */
00641     if (pn532_packetbuffer[0] == 0x00) {
00642         /* Copy the 4 data bytes to the output buffer         */
00643         /* Block content starts at byte 9 of a valid response */
00644         /* Note that the command actually reads 16 bytes or 4  */
00645         /* pages at a time ... we simply discard the last 12  */
00646         /* bytes                                              */
00647         memcpy (buffer, pn532_packetbuffer + 1, 4);
00648     } else {
00649         return 0;
00650     }
00651 
00652     // Return OK signal
00653     return 1;
00654 }
00655 
00656 /**************************************************************************/
00657 /*!
00658     @brief  Exchanges an APDU with the currently inlisted peer
00659 
00660     @param  send            Pointer to data to send
00661     @param  sendLength      Length of the data to send
00662     @param  response        Pointer to response data
00663     @param  responseLength  Pointer to the response data length
00664 */
00665 /**************************************************************************/
00666 bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength)
00667 {
00668     //uint8_t i;
00669 
00670     pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
00671     pn532_packetbuffer[1] = inListedTag;
00672 
00673     if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) {
00674         return false;
00675     }
00676 
00677     int16_t status = HAL(readResponse)(response, *responseLength, 1000);
00678     if (status < 0) {
00679         return false;
00680     }
00681 
00682     if ((response[0] & 0x3f) != 0) {
00683         DMSG("Status code indicates an error\n");
00684         return false;
00685     }
00686 
00687     uint8_t length = status;
00688     length -= 1;
00689 
00690     if (length > *responseLength) {
00691         length = *responseLength; // silent truncation...
00692     }
00693 
00694     for (uint8_t i = 0; i < length; i++) {
00695         response[i] = response[i + 1];
00696     }
00697     *responseLength = length;
00698 
00699     return true;
00700 }
00701 
00702 /**************************************************************************/
00703 /*!
00704     @brief  'InLists' a passive target. PN532 acting as reader/initiator,
00705             peer acting as card/responder.
00706 */
00707 /**************************************************************************/
00708 bool PN532::inListPassiveTarget()
00709 {
00710     pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
00711     pn532_packetbuffer[1] = 1;
00712     pn532_packetbuffer[2] = 0;
00713 
00714     DMSG("inList passive target\n");
00715 
00716     if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
00717         return false;
00718     }
00719 
00720     int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 30000);
00721     if (status < 0) {
00722         return false;
00723     }
00724 
00725     if (pn532_packetbuffer[0] != 1) {
00726         return false;
00727     }
00728 
00729     inListedTag = pn532_packetbuffer[1];
00730 
00731     return true;
00732 }
00733 
00734 int8_t PN532::tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout){
00735   
00736   int8_t status = HAL(writeCommand)(command, len);
00737     if (status < 0) {
00738         return -1;
00739     }
00740 
00741     status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout);
00742     if (status > 0) {
00743         return 1;
00744     } else if (PN532_TIMEOUT == status) {
00745         return 0;
00746     } else {
00747         return -2;
00748     }
00749 }
00750 
00751 /**
00752  * Peer to Peer
00753  */
00754 int8_t PN532::tgInitAsTarget(uint16_t timeout)
00755 {
00756     const uint8_t command[] = {
00757         PN532_COMMAND_TGINITASTARGET,
00758         0,
00759         0x00, 0x00,         //SENS_RES
00760         0x00, 0x00, 0x00,   //NFCID1
00761         0x40,               //SEL_RES
00762 
00763         0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES
00764         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00765         0xFF, 0xFF,
00766 
00767         0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value
00768 
00769         0x06, 0x46,  0x66, 0x6D, 0x01, 0x01, 0x10, 0x00// LLCP magic number and version parameter
00770     };
00771     return tgInitAsTarget(command, sizeof(command), timeout);
00772 }
00773 
00774 int16_t PN532::tgGetData(uint8_t *buf, uint8_t len)
00775 {
00776     buf[0] = PN532_COMMAND_TGGETDATA;
00777 
00778     if (HAL(writeCommand)(buf, 1)) {
00779         return -1;
00780     }
00781 
00782     int16_t status = HAL(readResponse)(buf, len, 3000);
00783     if (0 >= status) {
00784         return status;
00785     }
00786 
00787     uint16_t length = status - 1;
00788 
00789 
00790     if (buf[0] != 0) {
00791         DMSG("status is not ok\n");
00792         return -5;
00793     }
00794 
00795     for (uint8_t i = 0; i < length; i++) {
00796         buf[i] = buf[i + 1];
00797     }
00798 
00799     return length;
00800 }
00801 
00802 bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
00803 {
00804     if (hlen > (sizeof(pn532_packetbuffer) - 1)) {
00805         return false;
00806     }
00807 
00808     for (int8_t i = hlen - 1; i >= 0; i--){
00809         pn532_packetbuffer[i + 1] = header[i];
00810     }
00811     pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
00812 
00813     if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) {
00814         return false;
00815     }
00816 
00817     if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) {
00818         return false;
00819     }
00820 
00821     if (0 != pn532_packetbuffer[0]) {
00822         return false;
00823     }
00824 
00825     return true;
00826 }
00827 
00828 int16_t PN532::inRelease(const uint8_t relevantTarget){
00829 
00830     pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
00831     pn532_packetbuffer[1] = relevantTarget;
00832 
00833     if (HAL(writeCommand)(pn532_packetbuffer, 2)) {
00834         return 0;
00835     }
00836 
00837     // read data packet
00838     return HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
00839 }
00840 
00841