mbed code for the Kinoma team's wireless assignment
Dependencies: mbed
Fork of idd_hw5_kinoma_rememberkeys by
Adafruit_PN532.cpp
00001 /**************************************************************************/ 00002 /*! 00003 @file Adafruit_PN532.cpp 00004 @author Adafruit Industries 00005 @license BSD (see license.txt) 00006 00007 SPI Driver for NXP's PN532 NFC/13.56MHz RFID Transceiver 00008 00009 This is a library for the Adafruit PN532 NFC/RFID breakout boards 00010 This library works with the Adafruit NFC breakout 00011 ----> https://www.adafruit.com/products/364 00012 00013 Check out the links above for our tutorials and wiring diagrams 00014 These chips use SPI to communicate, 4 required to interface 00015 00016 Adafruit invests time and resources providing this open source code, 00017 please support Adafruit and open-source hardware by purchasing 00018 products from Adafruit! 00019 00020 00021 @section HISTORY 00022 00023 v1.4 - Added setPassiveActivationRetries() 00024 00025 v1.2 - Added writeGPIO() 00026 - Added readGPIO() 00027 00028 v1.1 - Changed readPassiveTargetID() to handle multiple UID sizes 00029 - Added the following helper functions for text display 00030 static void PrintHex(const uint8_t * data, const uint32_t numuint8_ts) 00031 static void PrintHexChar(const uint8_t * pbtData, const uint32_t numuint8_ts) 00032 - Added the following Mifare Classic functions: 00033 bool mifareclassic_IsFirstBlock (uint32_t uiBlock) 00034 bool mifareclassic_IsTrailerBlock (uint32_t uiBlock) 00035 uint8_t mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) 00036 uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) 00037 uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) 00038 - Added the following Mifare Ultalight functions: 00039 uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 00040 */ 00041 /**************************************************************************/ 00042 00043 #include "Adafruit_PN532.h " 00044 00045 uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00}; 00046 uint8_t pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03}; 00047 00048 // Uncomment these lines to enable debug output for PN532(SPI) and/or MIFARE related code 00049 // #define PN532DEBUG 00050 // #define MIFAREDEBUG 00051 00052 Serial serial(USBTX, USBRX); 00053 #define SERIAL_PRINT serial.printf 00054 00055 #define _BV(bit) (1 << (bit)) 00056 #define PN532_PACKBUFFSIZ 64 00057 uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ]; 00058 00059 void delay(int delayInMS) { 00060 wait(1.0 * delayInMS / 1000); 00061 } 00062 00063 /**************************************************************************/ 00064 /*! 00065 @brief Instantiates a new PN532 class 00066 00067 @param clk SPI clock pin (SCK) 00068 @param miso SPI MISO pin 00069 @param mosi SPI MOSI pin 00070 @param ss SPI chip select pin (CS/SSEL) 00071 */ 00072 /**************************************************************************/ 00073 Adafruit_PN532::Adafruit_PN532(DigitalOut clk, DigitalIn miso, 00074 DigitalOut mosi, DigitalOut ss) 00075 : _clk(clk), _miso(miso), _mosi(mosi), _ss(ss) {} 00076 00077 Adafruit_PN532::Adafruit_PN532(PinName clk_pin, PinName miso_pin, 00078 PinName mosi_pin, PinName ss_pin) 00079 : _clk(DigitalOut(clk_pin)), _miso(DigitalIn(miso_pin)), 00080 _mosi(DigitalOut(mosi_pin)), _ss(DigitalOut(ss_pin)) {} 00081 00082 /**************************************************************************/ 00083 /*! 00084 @brief Setups the HW 00085 */ 00086 /**************************************************************************/ 00087 void Adafruit_PN532::begin() { 00088 _ss = 0; 00089 delay(1000); 00090 00091 // not exactly sure why but we have to send a dummy command to get synced up 00092 pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; 00093 sendCommandCheckAck(pn532_packetbuffer, 1); 00094 00095 // ignore response! 00096 } 00097 00098 /**************************************************************************/ 00099 /*! 00100 @brief Prints a hexadecimal value in plain characters 00101 00102 @param data Pointer to the uint8_t data 00103 @param numuint8_ts Data length in uint8_ts 00104 */ 00105 /**************************************************************************/ 00106 void Adafruit_PN532::PrintHex(const uint8_t * data, const uint32_t numuint8_ts) 00107 { 00108 uint32_t szPos; 00109 for (szPos=0; szPos < numuint8_ts; szPos++) 00110 { 00111 SERIAL_PRINT("0x"); 00112 // Append leading 0 for small values 00113 if (data[szPos] <= 0xF) 00114 SERIAL_PRINT("0"); 00115 SERIAL_PRINT("%d", data[szPos]); 00116 if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1)) 00117 { 00118 SERIAL_PRINT(" "); 00119 } 00120 } 00121 SERIAL_PRINT("\n"); 00122 } 00123 00124 /**************************************************************************/ 00125 /*! 00126 @brief Prints a hexadecimal value in plain characters, along with 00127 the char equivalents in the following format 00128 00129 00 00 00 00 00 00 ...... 00130 00131 @param data Pointer to the uint8_t data 00132 @param numuint8_ts Data length in uint8_ts 00133 */ 00134 /**************************************************************************/ 00135 void Adafruit_PN532::PrintHexChar(const uint8_t * data, const uint32_t numuint8_ts) 00136 { 00137 uint32_t szPos; 00138 for (szPos=0; szPos < numuint8_ts; szPos++) 00139 { 00140 // Append leading 0 for small values 00141 if (data[szPos] <= 0xF) 00142 SERIAL_PRINT("0"); 00143 SERIAL_PRINT("%x", data[szPos]); 00144 if ((numuint8_ts > 1) && (szPos != numuint8_ts - 1)) 00145 { 00146 SERIAL_PRINT(" "); 00147 } 00148 } 00149 SERIAL_PRINT(" "); 00150 for (szPos=0; szPos < numuint8_ts; szPos++) 00151 { 00152 if (data[szPos] <= 0x1F) 00153 SERIAL_PRINT("."); 00154 else 00155 SERIAL_PRINT("%c", data[szPos]); 00156 } 00157 SERIAL_PRINT(""); 00158 } 00159 00160 /**************************************************************************/ 00161 /*! 00162 @brief Checks the firmware version of the PN5xx chip 00163 00164 @returns The chip's firmware version and ID 00165 */ 00166 /**************************************************************************/ 00167 uint32_t Adafruit_PN532::getFirmwareVersion(void) { 00168 uint32_t response; 00169 00170 pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; 00171 00172 if (! sendCommandCheckAck(pn532_packetbuffer, 1)) 00173 return 0; 00174 00175 // read data packet 00176 readspidata(pn532_packetbuffer, 12); 00177 00178 // check some basic stuff 00179 if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) { 00180 return 0; 00181 } 00182 00183 response = pn532_packetbuffer[6]; 00184 response <<= 8; 00185 response |= pn532_packetbuffer[7]; 00186 response <<= 8; 00187 response |= pn532_packetbuffer[8]; 00188 response <<= 8; 00189 response |= pn532_packetbuffer[9]; 00190 00191 return response; 00192 } 00193 00194 00195 /**************************************************************************/ 00196 /*! 00197 @brief Sends a command and waits a specified period for the ACK 00198 00199 @param cmd Pointer to the command buffer 00200 @param cmdlen The size of the command in uint8_ts 00201 @param timeout timeout before giving up 00202 00203 @returns 1 if everything is OK, 0 if timeout occured before an 00204 ACK was recieved 00205 */ 00206 /**************************************************************************/ 00207 // default timeout of one second 00208 bool Adafruit_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) { 00209 uint16_t timer = 0; 00210 00211 // write the command 00212 spiwritecommand(cmd, cmdlen); 00213 00214 // Wait for chip to say its ready! 00215 while (readspistatus() != PN532_SPI_READY) { 00216 if (timeout != 0) { 00217 timer+=10; 00218 if (timer > timeout) 00219 return false; 00220 } 00221 delay(10); 00222 } 00223 00224 // read acknowledgement 00225 if (!spi_readack()) { 00226 return false; 00227 } 00228 00229 timer = 0; 00230 // Wait for chip to say its ready! 00231 while (readspistatus() != PN532_SPI_READY) { 00232 if (timeout != 0) { 00233 timer+=10; 00234 if (timer > timeout) 00235 return false; 00236 } 00237 delay(10); 00238 } 00239 00240 return true; // ack'd command 00241 } 00242 00243 /**************************************************************************/ 00244 /*! 00245 Writes an 8-bit value that sets the state of the PN532's GPIO pins 00246 00247 @warning This function is provided exclusively for board testing and 00248 is dangerous since it will throw an error if any pin other 00249 than the ones marked "Can be used as GPIO" are modified! All 00250 pins that can not be used as GPIO should ALWAYS be left high 00251 (value = 1) or the system will become unstable and a HW reset 00252 will be required to recover the PN532. 00253 00254 pinState[0] = P30 Can be used as GPIO 00255 pinState[1] = P31 Can be used as GPIO 00256 pinState[2] = P32 *** RESERVED (Must be 1!) *** 00257 pinState[3] = P33 Can be used as GPIO 00258 pinState[4] = P34 *** RESERVED (Must be 1!) *** 00259 pinState[5] = P35 Can be used as GPIO 00260 00261 @returns 1 if everything executed properly, 0 for an error 00262 */ 00263 /**************************************************************************/ 00264 bool Adafruit_PN532::writeGPIO(uint8_t pinstate) { 00265 // Make sure pinstate does not try to toggle P32 or P34 00266 pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); 00267 00268 // Fill command buffer 00269 pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO; 00270 pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins 00271 pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by SPI) 00272 00273 #ifdef PN532DEBUG 00274 SERIAL_PRINT("Writing P3 GPIO: "); SERIAL_PRINTln(pn532_packetbuffer[1], HEX); 00275 #endif 00276 00277 // Send the WRITEGPIO command (0x0E) 00278 if (! sendCommandCheckAck(pn532_packetbuffer, 3)) 00279 return 0x0; 00280 00281 // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0F) DATACHECKSUM 00) 00282 readspidata(pn532_packetbuffer, 8); 00283 00284 #ifdef PN532DEBUG 00285 SERIAL_PRINT("Received: "); 00286 PrintHex(pn532_packetbuffer, 8); 00287 SERIAL_PRINTln(""); 00288 #endif 00289 00290 return (pn532_packetbuffer[5] == 0x0F); 00291 } 00292 00293 /**************************************************************************/ 00294 /*! 00295 Reads the state of the PN532's GPIO pins 00296 00297 @returns An 8-bit value containing the pin state where: 00298 00299 pinState[0] = P30 00300 pinState[1] = P31 00301 pinState[2] = P32 00302 pinState[3] = P33 00303 pinState[4] = P34 00304 pinState[5] = P35 00305 */ 00306 /**************************************************************************/ 00307 uint8_t Adafruit_PN532::readGPIO(void) { 00308 pn532_packetbuffer[0] = PN532_COMMAND_READGPIO; 00309 00310 // Send the READGPIO command (0x0C) 00311 if (! sendCommandCheckAck(pn532_packetbuffer, 1)) 00312 return 0x0; 00313 00314 // Read response packet (00 FF PLEN PLENCHECKSUM D5 CMD+1(0x0D) P3 P7 IO1 DATACHECKSUM 00) 00315 readspidata(pn532_packetbuffer, 11); 00316 00317 /* READGPIO response should be in the following format: 00318 00319 uint8_t Description 00320 ------------- ------------------------------------------ 00321 b0..5 Frame header and preamble 00322 b6 P3 GPIO Pins 00323 b7 P7 GPIO Pins (not used ... taken by SPI) 00324 b8 Interface Mode Pins (not used ... bus select pins) 00325 b9..10 checksum */ 00326 00327 #ifdef PN532DEBUG 00328 SERIAL_PRINT("Received: "); 00329 PrintHex(pn532_packetbuffer, 11); 00330 SERIAL_PRINTln(""); 00331 SERIAL_PRINT("P3 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[6], HEX); 00332 SERIAL_PRINT("P7 GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[7], HEX); 00333 SERIAL_PRINT("IO GPIO: 0x"); SERIAL_PRINTln(pn532_packetbuffer[8], HEX); 00334 // Note: You can use the IO GPIO value to detect the serial bus being used 00335 switch(pn532_packetbuffer[8]) 00336 { 00337 case 0x00: // Using UART 00338 SERIAL_PRINTln("Using UART (IO = 0x00)"); 00339 break; 00340 case 0x01: // Using I2C 00341 SERIAL_PRINTln("Using I2C (IO = 0x01)"); 00342 break; 00343 case 0x02: // Using SPI 00344 SERIAL_PRINTln("Using SPI (IO = 0x02)"); 00345 break; 00346 } 00347 #endif 00348 00349 return pn532_packetbuffer[6]; 00350 } 00351 00352 /**************************************************************************/ 00353 /*! 00354 @brief Configures the SAM (Secure Access Module) 00355 */ 00356 /**************************************************************************/ 00357 bool Adafruit_PN532::SAMConfig(void) { 00358 pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; 00359 pn532_packetbuffer[1] = 0x01; // normal mode; 00360 pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second 00361 pn532_packetbuffer[3] = 0x01; // use IRQ pin! 00362 00363 if (! sendCommandCheckAck(pn532_packetbuffer, 4)) 00364 return false; 00365 00366 // read data packet 00367 readspidata(pn532_packetbuffer, 8); 00368 00369 return (pn532_packetbuffer[5] == 0x15); 00370 } 00371 00372 /**************************************************************************/ 00373 /*! 00374 Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register 00375 00376 @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout 00377 after mxRetries 00378 00379 @returns 1 if everything executed properly, 0 for an error 00380 */ 00381 /**************************************************************************/ 00382 bool Adafruit_PN532::setPassiveActivationRetries(uint8_t maxRetries) { 00383 pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; 00384 pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) 00385 pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) 00386 pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) 00387 pn532_packetbuffer[4] = maxRetries; 00388 00389 #ifdef MIFAREDEBUG 00390 SERIAL_PRINT("Setting MxRtyPassiveActivation to "); SERIAL_PRINT(maxRetries, DEC); SERIAL_PRINTln(" "); 00391 #endif 00392 00393 if (! sendCommandCheckAck(pn532_packetbuffer, 5)) 00394 return 0x0; // no ACK 00395 00396 return 1; 00397 } 00398 00399 /***** ISO14443A Commands ******/ 00400 00401 /**************************************************************************/ 00402 /*! 00403 Waits for an ISO14443A target to enter the field 00404 00405 @param cardBaudRate Baud rate of the card 00406 @param uid Pointer to the array that will be populated 00407 with the card's UID (up to 7 uint8_ts) 00408 @param uidLength Pointer to the variable that will hold the 00409 length of the card's UID. 00410 00411 @returns 1 if everything executed properly, 0 for an error 00412 */ 00413 /**************************************************************************/ 00414 bool Adafruit_PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength) { 00415 pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; 00416 pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) 00417 pn532_packetbuffer[2] = cardbaudrate; 00418 00419 if (! sendCommandCheckAck(pn532_packetbuffer, 3)) 00420 return 0x0; // no cards read 00421 00422 // read data packet 00423 readspidata(pn532_packetbuffer, 20); 00424 // check some basic stuff 00425 00426 /* ISO14443A card response should be in the following format: 00427 00428 uint8_t Description 00429 ------------- ------------------------------------------ 00430 b0..6 Frame header and preamble 00431 b7 Tags Found 00432 b8 Tag Number (only one used in this example) 00433 b9..10 SENS_RES 00434 b11 SEL_RES 00435 b12 NFCID Length 00436 b13..NFCIDLen NFCID */ 00437 00438 #ifdef MIFAREDEBUG 00439 SERIAL_PRINT("Found "); SERIAL_PRINT(pn532_packetbuffer[7], DEC); SERIAL_PRINTln(" tags"); 00440 #endif 00441 if (pn532_packetbuffer[7] != 1) 00442 return 0; 00443 00444 uint16_t sens_res = pn532_packetbuffer[9]; 00445 sens_res <<= 8; 00446 sens_res |= pn532_packetbuffer[10]; 00447 #ifdef MIFAREDEBUG 00448 SERIAL_PRINT("ATQA: 0x"); SERIAL_PRINTln(sens_res, HEX); 00449 SERIAL_PRINT("SAK: 0x"); SERIAL_PRINTln(pn532_packetbuffer[11], HEX); 00450 #endif 00451 00452 /* Card appears to be Mifare Classic */ 00453 *uidLength = pn532_packetbuffer[12]; 00454 #ifdef MIFAREDEBUG 00455 SERIAL_PRINT("UID:"); 00456 #endif 00457 for (uint8_t i=0; i < pn532_packetbuffer[12]; i++) 00458 { 00459 uid[i] = pn532_packetbuffer[13+i]; 00460 #ifdef MIFAREDEBUG 00461 SERIAL_PRINT(" 0x");SERIAL_PRINT(uid[i], HEX); 00462 #endif 00463 } 00464 #ifdef MIFAREDEBUG 00465 SERIAL_PRINTln(); 00466 #endif 00467 00468 uint8_t bTestDeselect[2]; 00469 bTestDeselect[0] = PN532_COMMAND_INDESELECT; 00470 bTestDeselect[1] = pn532_packetbuffer[8]; 00471 sendCommandCheckAck(bTestDeselect,2); 00472 00473 return 1; 00474 } 00475 00476 00477 /***** Mifare Classic Functions ******/ 00478 00479 /**************************************************************************/ 00480 /*! 00481 Indicates whether the specified block number is the first block 00482 in the sector (block 0 relative to the current sector) 00483 */ 00484 /**************************************************************************/ 00485 bool Adafruit_PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock) 00486 { 00487 // Test if we are in the small or big sectors 00488 if (uiBlock < 128) 00489 return ((uiBlock) % 4 == 0); 00490 else 00491 return ((uiBlock) % 16 == 0); 00492 } 00493 00494 /**************************************************************************/ 00495 /*! 00496 Indicates whether the specified block number is the sector trailer 00497 */ 00498 /**************************************************************************/ 00499 bool Adafruit_PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock) 00500 { 00501 // Test if we are in the small or big sectors 00502 if (uiBlock < 128) 00503 return ((uiBlock + 1) % 4 == 0); 00504 else 00505 return ((uiBlock + 1) % 16 == 0); 00506 } 00507 00508 /**************************************************************************/ 00509 /*! 00510 Tries to authenticate a block of memory on a MIFARE card using the 00511 INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual 00512 for more information on sending MIFARE and other commands. 00513 00514 @param uid Pointer to a uint8_t array containing the card UID 00515 @param uidLen The length (in uint8_ts) of the card's UID (Should 00516 be 4 for MIFARE Classic) 00517 @param blockNumber The block number to authenticate. (0..63 for 00518 1KB cards, and 0..255 for 4KB cards). 00519 @param keyNumber Which key type to use during authentication 00520 (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B) 00521 @param keyData Pointer to a uint8_t array containing the 6 uint8_t 00522 key value 00523 00524 @returns 1 if everything executed properly, 0 for an error 00525 */ 00526 /**************************************************************************/ 00527 uint8_t Adafruit_PN532::mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t * keyData) 00528 { 00529 uint8_t i; 00530 00531 // Hang on to the key and uid data 00532 memcpy (_key, keyData, 6); 00533 memcpy (_uid, uid, uidLen); 00534 _uidLen = uidLen; 00535 00536 #ifdef MIFAREDEBUG 00537 SERIAL_PRINT("Trying to authenticate card "); 00538 Adafruit_PN532::PrintHex(_uid, _uidLen); 00539 SERIAL_PRINT("Using authentication KEY ");SERIAL_PRINT(keyNumber ? 'B' : 'A');SERIAL_PRINT(": "); 00540 Adafruit_PN532::PrintHex(_key, 6); 00541 #endif 00542 00543 // Prepare the authentication command // 00544 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ 00545 pn532_packetbuffer[1] = 1; /* Max card numbers */ 00546 pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; 00547 pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ 00548 memcpy (pn532_packetbuffer+4, _key, 6); 00549 for (i = 0; i < _uidLen; i++) 00550 { 00551 pn532_packetbuffer[10+i] = _uid[i]; /* 4 uint8_t card ID */ 00552 } 00553 00554 if (! sendCommandCheckAck(pn532_packetbuffer, 10+_uidLen)) 00555 return 0; 00556 00557 // Read the response packet 00558 readspidata(pn532_packetbuffer, 12); 00559 // check if the response is valid and we are authenticated??? 00560 // for an auth success it should be uint8_ts 5-7: 0xD5 0x41 0x00 00561 // Mifare auth error is technically uint8_t 7: 0x14 but anything other and 0x00 is not good 00562 if (pn532_packetbuffer[7] != 0x00) 00563 { 00564 #ifdef PN532DEBUG 00565 SERIAL_PRINT("Authentification failed: "); 00566 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 12); 00567 #endif 00568 return 0; 00569 } 00570 00571 return 1; 00572 } 00573 00574 /**************************************************************************/ 00575 /*! 00576 Tries to read an entire 16-uint8_t data block at the specified block 00577 address. 00578 00579 @param blockNumber The block number to authenticate. (0..63 for 00580 1KB cards, and 0..255 for 4KB cards). 00581 @param data Pointer to the uint8_t array that will hold the 00582 retrieved data (if any) 00583 00584 @returns 1 if everything executed properly, 0 for an error 00585 */ 00586 /**************************************************************************/ 00587 uint8_t Adafruit_PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data) 00588 { 00589 #ifdef MIFAREDEBUG 00590 SERIAL_PRINT("Trying to read 16 uint8_ts from block ");SERIAL_PRINTln(blockNumber); 00591 #endif 00592 00593 /* Prepare the command */ 00594 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 00595 pn532_packetbuffer[1] = 1; /* Card number */ 00596 pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 00597 pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ 00598 00599 /* Send the command */ 00600 if (! sendCommandCheckAck(pn532_packetbuffer, 4)) 00601 { 00602 #ifdef MIFAREDEBUG 00603 SERIAL_PRINTln("Failed to receive ACK for read command"); 00604 #endif 00605 return 0; 00606 } 00607 00608 /* Read the response packet */ 00609 readspidata(pn532_packetbuffer, 26); 00610 00611 /* If uint8_t 8 isn't 0x00 we probably have an error */ 00612 if (pn532_packetbuffer[7] != 0x00) 00613 { 00614 //#ifdef MIFAREDEBUG 00615 SERIAL_PRINT("Unexpected response"); 00616 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 00617 //#endif 00618 return 0; 00619 } 00620 00621 /* Copy the 16 data uint8_ts to the output buffer */ 00622 /* Block content starts at uint8_t 9 of a valid response */ 00623 memcpy (data, pn532_packetbuffer+8, 16); 00624 00625 /* Display data for debug if requested */ 00626 #ifdef MIFAREDEBUG 00627 SERIAL_PRINT("Block "); 00628 SERIAL_PRINTln(blockNumber); 00629 Adafruit_PN532::PrintHexChar(data, 16); 00630 #endif 00631 00632 return 1; 00633 } 00634 00635 /**************************************************************************/ 00636 /*! 00637 Tries to write an entire 16-uint8_t data block at the specified block 00638 address. 00639 00640 @param blockNumber The block number to authenticate. (0..63 for 00641 1KB cards, and 0..255 for 4KB cards). 00642 @param data The uint8_t array that contains the data to write. 00643 00644 @returns 1 if everything executed properly, 0 for an error 00645 */ 00646 /**************************************************************************/ 00647 uint8_t Adafruit_PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data) 00648 { 00649 #ifdef MIFAREDEBUG 00650 SERIAL_PRINT("Trying to write 16 uint8_ts to block ");SERIAL_PRINTln(blockNumber); 00651 #endif 00652 00653 /* Prepare the first command */ 00654 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 00655 pn532_packetbuffer[1] = 1; /* Card number */ 00656 pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ 00657 pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ 00658 memcpy (pn532_packetbuffer+4, data, 16); /* Data Payload */ 00659 00660 /* Send the command */ 00661 if (! sendCommandCheckAck(pn532_packetbuffer, 20)) 00662 { 00663 #ifdef MIFAREDEBUG 00664 SERIAL_PRINTln("Failed to receive ACK for write command"); 00665 #endif 00666 return 0; 00667 } 00668 delay(10); 00669 00670 /* Read the response packet */ 00671 readspidata(pn532_packetbuffer, 26); 00672 00673 return 1; 00674 } 00675 00676 /**************************************************************************/ 00677 /*! 00678 Formats a Mifare Classic card to store NDEF Records 00679 00680 @returns 1 if everything executed properly, 0 for an error 00681 */ 00682 /**************************************************************************/ 00683 uint8_t Adafruit_PN532::mifareclassic_FormatNDEF (void) 00684 { 00685 uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; 00686 uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; 00687 uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 00688 00689 // Write block 1 and 2 to the card 00690 if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1))) 00691 return 0; 00692 if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2))) 00693 return 0; 00694 // Write key A and access rights card 00695 if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3))) 00696 return 0; 00697 00698 // Seems that everything was OK (?!) 00699 return 1; 00700 } 00701 00702 /**************************************************************************/ 00703 /*! 00704 Writes an NDEF URI Record to the specified sector (1..15) 00705 00706 Note that this function assumes that the Mifare Classic card is 00707 already formatted to work as an "NFC Forum Tag" and uses a MAD1 00708 file system. You can use the NXP TagWriter app on Android to 00709 properly format cards for this. 00710 00711 @param sectorNumber The sector that the URI record should be written 00712 to (can be 1..15 for a 1K card) 00713 @param uriIdentifier The uri identifier code (0 = none, 0x01 = 00714 "http://www.", etc.) 00715 @param url The uri text to write (max 38 characters). 00716 00717 @returns 1 if everything executed properly, 0 for an error 00718 */ 00719 /**************************************************************************/ 00720 uint8_t Adafruit_PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url) 00721 { 00722 // Figure out how long the string is 00723 uint8_t len = strlen(url); 00724 00725 // Make sure we're within a 1K limit for the sector number 00726 if ((sectorNumber < 1) || (sectorNumber > 15)) 00727 return 0; 00728 00729 // Make sure the URI payload is between 1 and 38 chars 00730 if ((len < 1) || (len > 38)) 00731 return 0; 00732 00733 // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message) 00734 uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len+5, 0xD1, 0x01, len+1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00735 uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00736 uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00737 uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 00738 if (len <= 6) 00739 { 00740 // Unlikely we'll get a url this short, but why not ... 00741 memcpy (sectorbuffer1+9, url, len); 00742 sectorbuffer1[len+9] = 0xFE; 00743 } 00744 else if (len == 7) 00745 { 00746 // 0xFE needs to be wrapped around to next block 00747 memcpy (sectorbuffer1+9, url, len); 00748 sectorbuffer2[0] = 0xFE; 00749 } 00750 else if ((len > 7) || (len <= 22)) 00751 { 00752 // Url fits in two blocks 00753 memcpy (sectorbuffer1+9, url, 7); 00754 memcpy (sectorbuffer2, url+7, len-7); 00755 sectorbuffer2[len-7] = 0xFE; 00756 } 00757 else if (len == 23) 00758 { 00759 // 0xFE needs to be wrapped around to final block 00760 memcpy (sectorbuffer1+9, url, 7); 00761 memcpy (sectorbuffer2, url+7, len-7); 00762 sectorbuffer3[0] = 0xFE; 00763 } 00764 else 00765 { 00766 // Url fits in three blocks 00767 memcpy (sectorbuffer1+9, url, 7); 00768 memcpy (sectorbuffer2, url+7, 16); 00769 memcpy (sectorbuffer3, url+23, len-24); 00770 sectorbuffer3[len-22] = 0xFE; 00771 } 00772 00773 // Now write all three blocks back to the card 00774 if (!(mifareclassic_WriteDataBlock (sectorNumber*4, sectorbuffer1))) 00775 return 0; 00776 if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+1, sectorbuffer2))) 00777 return 0; 00778 if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+2, sectorbuffer3))) 00779 return 0; 00780 if (!(mifareclassic_WriteDataBlock ((sectorNumber*4)+3, sectorbuffer4))) 00781 return 0; 00782 00783 // Seems that everything was OK (?!) 00784 return 1; 00785 } 00786 00787 /***** Mifare Ultralight Functions ******/ 00788 00789 /**************************************************************************/ 00790 /*! 00791 Tries to read an entire 4-uint8_t page at the specified address. 00792 00793 @param page The page number (0..63 in most cases) 00794 @param buffer Pointer to the uint8_t array that will hold the 00795 retrieved data (if any) 00796 */ 00797 /**************************************************************************/ 00798 uint8_t Adafruit_PN532::mifareultralight_ReadPage (uint8_t page, uint8_t * buffer) 00799 { 00800 if (page >= 64) 00801 { 00802 #ifdef MIFAREDEBUG 00803 SERIAL_PRINTln("Page value out of range"); 00804 #endif 00805 return 0; 00806 } 00807 00808 #ifdef MIFAREDEBUG 00809 SERIAL_PRINT("Reading page ");SERIAL_PRINTln(page); 00810 #endif 00811 00812 /* Prepare the command */ 00813 pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; 00814 pn532_packetbuffer[1] = 1; /* Card number */ 00815 pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ 00816 pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */ 00817 00818 /* Send the command */ 00819 if (! sendCommandCheckAck(pn532_packetbuffer, 4)) 00820 { 00821 #ifdef MIFAREDEBUG 00822 SERIAL_PRINTln("Failed to receive ACK for write command"); 00823 #endif 00824 return 0; 00825 } 00826 00827 /* Read the response packet */ 00828 readspidata(pn532_packetbuffer, 26); 00829 #ifdef MIFAREDEBUG 00830 SERIAL_PRINTln("Received: "); 00831 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 00832 #endif 00833 00834 /* If uint8_t 8 isn't 0x00 we probably have an error */ 00835 if (pn532_packetbuffer[7] == 0x00) 00836 { 00837 /* Copy the 4 data uint8_ts to the output buffer */ 00838 /* Block content starts at uint8_t 9 of a valid response */ 00839 /* Note that the command actually reads 16 uint8_t or 4 */ 00840 /* pages at a time ... we simply discard the last 12 */ 00841 /* uint8_ts */ 00842 memcpy (buffer, pn532_packetbuffer+8, 4); 00843 } 00844 else 00845 { 00846 #ifdef MIFAREDEBUG 00847 SERIAL_PRINTln("Unexpected response reading block: "); 00848 Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 26); 00849 #endif 00850 return 0; 00851 } 00852 00853 /* Display data for debug if requested */ 00854 #ifdef MIFAREDEBUG 00855 SERIAL_PRINT("Page ");SERIAL_PRINT(page);SERIAL_PRINTln(":"); 00856 Adafruit_PN532::PrintHexChar(buffer, 4); 00857 #endif 00858 00859 // Return OK signal 00860 return 1; 00861 } 00862 00863 00864 00865 /************** high level SPI */ 00866 00867 00868 /**************************************************************************/ 00869 /*! 00870 @brief Tries to read the SPI ACK signal 00871 */ 00872 /**************************************************************************/ 00873 bool Adafruit_PN532::spi_readack() { 00874 uint8_t ackbuff[6]; 00875 00876 readspidata(ackbuff, 6); 00877 00878 return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6)); 00879 } 00880 00881 /************** mid level SPI */ 00882 00883 /**************************************************************************/ 00884 /*! 00885 @brief Reads the SPI status register (to know if the PN532 is ready) 00886 */ 00887 /**************************************************************************/ 00888 uint8_t Adafruit_PN532::readspistatus(void) { 00889 _ss = 0; 00890 delay(2); 00891 spiwrite(PN532_SPI_STATREAD); 00892 // read uint8_t 00893 uint8_t x = spiread(); 00894 00895 _ss = 1; 00896 return x; 00897 } 00898 00899 /**************************************************************************/ 00900 /*! 00901 @brief Reads n uint8_ts of data from the PN532 via SPI 00902 00903 @param buff Pointer to the buffer where data will be written 00904 @param n Number of uint8_ts to be read 00905 */ 00906 /**************************************************************************/ 00907 void Adafruit_PN532::readspidata(uint8_t* buff, uint8_t n) { 00908 _ss = 0; 00909 delay(2); 00910 spiwrite(PN532_SPI_DATAREAD); 00911 00912 #ifdef PN532DEBUG 00913 SERIAL_PRINT("Reading: "); 00914 #endif 00915 for (uint8_t i=0; i<n; i++) { 00916 delay(1); 00917 buff[i] = spiread(); 00918 #ifdef PN532DEBUG 00919 SERIAL_PRINT(" 0x"); 00920 SERIAL_PRINT(buff[i], HEX); 00921 #endif 00922 } 00923 00924 #ifdef PN532DEBUG 00925 SERIAL_PRINTln(); 00926 #endif 00927 00928 _ss = 1; 00929 } 00930 00931 /**************************************************************************/ 00932 /*! 00933 @brief Writes a command to the PN532, automatically inserting the 00934 preamble and required frame details (checksum, len, etc.) 00935 00936 @param cmd Pointer to the command buffer 00937 @param cmdlen Command length in uint8_ts 00938 */ 00939 /**************************************************************************/ 00940 void Adafruit_PN532::spiwritecommand(uint8_t* cmd, uint8_t cmdlen) { 00941 uint8_t checksum; 00942 00943 cmdlen++; 00944 00945 #ifdef PN532DEBUG 00946 SERIAL_PRINT("\nSending: "); 00947 #endif 00948 00949 _ss = 0; 00950 delay(2); // or whatever the delay is for waking up the board 00951 spiwrite(PN532_SPI_DATAWRITE); 00952 00953 checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2; 00954 spiwrite(PN532_PREAMBLE); 00955 spiwrite(PN532_PREAMBLE); 00956 spiwrite(PN532_STARTCODE2); 00957 00958 spiwrite(cmdlen); 00959 spiwrite(~cmdlen + 1); 00960 00961 spiwrite(PN532_HOSTTOPN532); 00962 checksum += PN532_HOSTTOPN532; 00963 00964 #ifdef PN532DEBUG 00965 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX); 00966 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_PREAMBLE, HEX); 00967 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_STARTCODE2, HEX); 00968 SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmdlen, HEX); 00969 SERIAL_PRINT(" 0x"); SERIAL_PRINT(~cmdlen + 1, HEX); 00970 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_HOSTTOPN532, HEX); 00971 #endif 00972 00973 for (uint8_t i=0; i<cmdlen-1; i++) { 00974 spiwrite(cmd[i]); 00975 checksum += cmd[i]; 00976 #ifdef PN532DEBUG 00977 SERIAL_PRINT(" 0x"); SERIAL_PRINT(cmd[i], HEX); 00978 #endif 00979 } 00980 00981 spiwrite(~checksum); 00982 spiwrite(PN532_POSTAMBLE); 00983 _ss = 1; 00984 00985 #ifdef PN532DEBUG 00986 SERIAL_PRINT(" 0x"); SERIAL_PRINT(~checksum, HEX); 00987 SERIAL_PRINT(" 0x"); SERIAL_PRINT(PN532_POSTAMBLE, HEX); 00988 SERIAL_PRINTln(); 00989 #endif 00990 } 00991 /************** low level SPI */ 00992 00993 /**************************************************************************/ 00994 /*! 00995 @brief Low-level SPI write wrapper 00996 00997 @param c 8-bit command to write to the SPI bus 00998 */ 00999 /**************************************************************************/ 01000 void Adafruit_PN532::spiwrite(uint8_t c) { 01001 int8_t i; 01002 _clk = 1; 01003 01004 for (i=0; i<8; i++) { 01005 _clk = 0; 01006 if (c & _BV(i)) { 01007 _mosi = 1; 01008 } else { 01009 _mosi = 0; 01010 } 01011 _clk = 1; 01012 } 01013 } 01014 01015 /**************************************************************************/ 01016 /*! 01017 @brief Low-level SPI read wrapper 01018 01019 @returns The 8-bit value that was read from the SPI bus 01020 */ 01021 /**************************************************************************/ 01022 uint8_t Adafruit_PN532::spiread(void) { 01023 int8_t i, x; 01024 x = 0; 01025 _clk = 1; 01026 01027 for (i=0; i<8; i++) { 01028 if (_miso.read()) { 01029 x |= _BV(i); 01030 } 01031 _clk = 0; 01032 _clk = 1; 01033 } 01034 return x; 01035 }
Generated on Sun Jul 17 2022 01:45:53 by 1.7.2