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