to colorize a colorful pixel with a simple touch using nfc technology

Dependencies:   Chainable_RGB_LED mbed

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