to colorize a colorful pixel with a simple touch using nfc technology
Dependencies: Chainable_RGB_LED mbed
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 #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
Generated on Fri Jul 15 2022 06:47:11 by 1.7.2