NFC library using PN532 to read/write NDEF Messages to NFC tags
Dependents: Seeed_NFC_Shield_write Nucleo_test_nfc
Fork of PN532 by
PN532.cpp
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
Generated on Tue Jul 12 2022 21:59:39 by 1.7.2