pn532_error_t pn532_mifareclassic_ReadDataBlock (uint8_t uiBlockNumber, byte_t * pbtData) { pn532_error_t error; byte_t abtCommand[4]; byte_t abtResponse[PN532_RESPONSELEN_INDATAEXCHANGE]; size_t szLen; #ifdef PN532_DEBUGMODE PN532_DEBUG("Reading 16 bytes at block %03d%s", uiBlockNumber, CFG_PRINTF_NEWLINE); #endif /* Prepare the command */ abtCommand[0] = PN532_COMMAND_INDATAEXCHANGE; abtCommand[1] = 1; /* Card number */ abtCommand[2] = PN532_MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ abtCommand[3] = uiBlockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ /* Send the commands */ error = pn532Write(abtCommand, sizeof(abtCommand)); if (error) { /* Bus error, etc. */ #ifdef PN532_DEBUGMODE PN532_DEBUG("Read failed%s", CFG_PRINTF_NEWLINE); #endif return error; } /* Read the response */ memset(abtResponse, 0, PN532_RESPONSELEN_INDATAEXCHANGE); do { systickDelay(50); error = pn532Read(abtResponse, &szLen); } while (error == PN532_ERROR_RESPONSEBUFFEREMPTY); if (error) { #ifdef PN532_DEBUGMODE PN532_DEBUG("Read failed%s", CFG_PRINTF_NEWLINE); #endif return error; } /* Make sure we have a valid response (should be 26 bytes long) */ if (szLen == 26) { /* Copy the 16 data bytes to the output buffer */ /* Block content starts at byte 9 of a valid response */ memcpy (pbtData, abtResponse+8, 16); } else { #ifdef PN532_DEBUGMODE PN532_DEBUG("Unexpected response reading block %d. Bad key?%s", uiBlockNumber, CFG_PRINTF_NEWLINE); #endif return PN532_ERROR_BLOCKREADFAILED; } /* Display data for debug if requested */ #ifdef PN532_DEBUGMODE PN532_DEBUG("Block %03d: ", uiBlockNumber, CFG_PRINTF_NEWLINE); pn532PrintHexVerbose(pbtData, 16); #endif // Return OK signal return PN532_ERROR_NONE; }
pn532_error_t pn532_mifareclassic_AuthenticateBlock (byte_t * pbtCUID, size_t szCUIDLen, uint32_t uiBlockNumber, uint8_t uiKeyType, byte_t * pbtKeys) { pn532_error_t error; byte_t abtCommand[17]; byte_t abtResponse[PN532_RESPONSELEN_INDATAEXCHANGE]; size_t szLen; #ifdef PN532_DEBUGMODE PN532_DEBUG("Trying to authenticate card "); pn532PrintHex(pbtCUID, szCUIDLen); #endif /* Prepare the authentication command */ abtCommand[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ abtCommand[1] = 1; /* Max card numbers */ abtCommand[2] = (uiKeyType) ? PN532_MIFARE_CMD_AUTH_A : PN532_MIFARE_CMD_AUTH_B; abtCommand[3] = uiBlockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ memcpy (abtCommand+4, pbtKeys, 6); uint8_t i; for (i = 0; i < szCUIDLen; i++) { abtCommand[10+i] = pbtCUID[i]; /* 4 byte card ID */ } /* Send the command */ error = pn532Write(abtCommand, 10+szCUIDLen); if (error) { /* Problem with the serial bus, etc. */ #ifdef PN532_DEBUGMODE PN532_DEBUG("Authentification failed%s", CFG_PRINTF_NEWLINE); #endif return error; } /* Read the authentication response */ memset(abtResponse, 0, PN532_RESPONSELEN_INDATAEXCHANGE); do { systickDelay(25); error = pn532Read(abtResponse, &szLen); } while (error == PN532_ERROR_RESPONSEBUFFEREMPTY); if (error) { #ifdef PN532_DEBUGMODE PN532_DEBUG("Authentification failed%s", CFG_PRINTF_NEWLINE); #endif return error; } // ToDo: How to check if authentification really worked (bad key, etc.)? /* Output the authentification data */ #ifdef PN532_DEBUGMODE PN532_DEBUG("Authenticated block %d %s", uiBlockNumber, CFG_PRINTF_NEWLINE); #endif // Return OK signal return PN532_ERROR_NONE; }
int main (void) { #ifdef CFG_INTERFACE #error "CFG_INTERFACE must be disabled in projectconfig.h for this demo" #endif #if !defined CFG_PRINTF_USBCDC #error "CFG_PRINTF_USBCDC must be enabled in projectconfig.h for this demo" #endif // Configure cpu and mandatory peripherals systemInit(); // Wait 5 second for someone to open the USB connection for printf systickDelay(5000); // Initialise the PN532 pn532Init(); byte_t response[256]; size_t responseLen; pn532_error_t error; // Setup command to initialise a single ISO14443A target at 106kbps byte_t abtCommand[] = { PN532_COMMAND_INLISTPASSIVETARGET, 0x01, PN532_MODULATION_ISO14443A_106KBPS }; while (1) { printf("%s", CFG_PRINTF_NEWLINE); printf("Waiting for an ISO14443A card (Mifare Classic, etc.)%s", CFG_PRINTF_NEWLINE); // Send the command (and handle the most common errors) error = pn532Write(abtCommand, sizeof(abtCommand)); if (error) { // Something went wrong sending the command (probably the bus selection or wiring) switch(error) { case (PN532_ERROR_NOACK): // No ACK frame received in UART mode (bus pins not set correctly?) printf("Ooops ... No ACK frame was received! Are the bus pins sets to UART?%s", CFG_PRINTF_NEWLINE); break; case (PN532_ERROR_I2C_NACK): // No ACK bit received to I2C start (bus pins not set correctly?) printf("Ooops ... No ACK bit received for I2C start! Are the bus pins sets to I2C?%s", CFG_PRINTF_NEWLINE); break; default: printf("Ooops ... something went wrong! [PN532 Error Code: 0x%02X]%s", error, CFG_PRINTF_NEWLINE); break; } } else { // Commmand seems to have gone through ... do { // Keep reading until we get a response or an unexpected error condition error = pn532Read(response, &responseLen); systickDelay(25); } while (error == PN532_ERROR_RESPONSEBUFFEREMPTY); // Print the card details if possible if (!error) { /* Response for ISO14443A 106KBPS (Mifare Classic, etc.) See UM0701-02 section 7.3.5 for more information byte Description ------------- ------------------------------------------ b7 Tags Found b8 Tag Number (only one used in this example) b9..10 SENS_RES b11 SEL_RES b12 NFCID Length b13..NFCIDLen NFCID SENS_RES SEL_RES Manufacturer/Card Type NFCID Len -------- ------- ----------------------- --------- 00 04 08 NXP Mifare Classic 1K 4 bytes */ printf("%s", CFG_PRINTF_NEWLINE); printf("%-12s: %d %s", "Tags Found", response[7], CFG_PRINTF_NEWLINE); printf("%-12s: %02X %02X %s", "SENS_RES", response[9], response[10], CFG_PRINTF_NEWLINE); printf("%-12s: %02X %s", "SEL_RES", response[11], CFG_PRINTF_NEWLINE); printf("%-12s: ", "NFCID"); size_t pos; for (pos=0; pos < response[12]; pos++) { printf("%02x ", response[13 + pos]); } printf(CFG_PRINTF_NEWLINE); if ((response[9] == 0x00) && (response[10] == 0x04) && (response[11] == 0x08)) { printf("Seems to be a Mifare Classic 1K Card%s", CFG_PRINTF_NEWLINE); } } else { // Oops .... something bad happened. Check 'error' printf("Ooops! Error %02X %s", error, CFG_PRINTF_NEWLINE); } } // Wait at least one second before trying again systickDelay(1000); } }
pn532_error_t pn532_mifareclassic_WaitForPassiveTarget (byte_t * pbtCUID, size_t * szCUIDLen) { byte_t abtResponse[PN532_RESPONSELEN_INLISTPASSIVETARGET]; pn532_error_t error; size_t szLen; #ifdef PN532_DEBUGMODE PN532_DEBUG("Waiting for an ISO14443A Card%s", CFG_PRINTF_NEWLINE); #endif /* Try to initialise a single ISO14443A tag at 106KBPS */ /* Note: To wait for a card with a known UID, append the four byte */ /* UID to the end of the command. */ byte_t abtCommand[] = { PN532_COMMAND_INLISTPASSIVETARGET, 0x01, PN532_MODULATION_ISO14443A_106KBPS}; error = pn532Write(abtCommand, sizeof(abtCommand)); if (error) return error; /* Wait until we get a valid response or a timeout */ do { systickDelay(25); error = pn532Read(abtResponse, &szLen); } while (error == PN532_ERROR_RESPONSEBUFFEREMPTY); if (error) return error; /* Check SENSE_RES to make sure this is a Mifare Classic card */ /* Classic 1K = 00 04 */ /* Classic 4K = 00 02 */ /* Classic Emulated = 00 08 */ if ((abtResponse[10] == 0x02) || (abtResponse[10] == 0x04) || (abtResponse[10] == 0x08)) { /* Card appears to be Mifare Classic */ *szCUIDLen = abtResponse[12]; uint8_t i; for (i=0; i < *szCUIDLen; i++) { pbtCUID[i] = abtResponse[13+i]; } #ifdef PN532_DEBUGMODE PN532_DEBUG("Card Found: %s", CFG_PRINTF_NEWLINE); PN532_DEBUG(" ATQA: "); pn532PrintHex(abtResponse+9, 2); PN532_DEBUG(" SAK: %02x%s", abtResponse[11], CFG_PRINTF_NEWLINE); PN532_DEBUG(" UID: "); pn532PrintHex(pbtCUID, *szCUIDLen); #endif } else { /* Card is ISO14443A but doesn't appear to be Mifare Classic */ /* Mifare Ultralight = 0x0044 */ /* Mifare DESFire = 0x0344 */ /* Innovision Jewel = 0x0C00 */ #ifdef PN532_DEBUGMODE PN532_DEBUG("Wrong Card Type (Expected ATQA 00 02, 00 04 or 00 08) %s%s", CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE); PN532_DEBUG(" ATQA : "); pn532PrintHex(abtResponse+9, 2); PN532_DEBUG(" SAK : %02x%s", abtResponse[11], CFG_PRINTF_NEWLINE); PN532_DEBUG(" UID Length : %d%s", abtResponse[12], CFG_PRINTF_NEWLINE); PN532_DEBUG(" UID : "); size_t pos; for (pos=0; pos < abtResponse[12]; pos++) { printf("%02x ", abtResponse[13 + pos]); } printf("%s%s", CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE); #endif return PN532_ERROR_WRONGCARDTYPE; } return PN532_ERROR_NONE; }
int main (void) { #ifdef CFG_INTERFACE //#error "CFG_INTERFACE must be disabled in projectconfig.h for this demo" #endif #if !defined CFG_PRINTF_USBCDC #error "CFG_PRINTF_USBCDC must be enabled in projectconfig.h for this demo" #endif // Configure cpu and mandatory peripherals systemInit(); // Wait a bit for someone to open the USB connection for printf systickDelay(5000); // Initialise the PN532 pn532Init(); pn532_error_t error; byte_t response[64]; size_t responseLen; // Setup command to initialise a single ISO14443A target at 106kbps (Mifare Classic, Ultralight, etc.) byte_t abtCommand[] = { PN532_COMMAND_INLISTPASSIVETARGET, 0x01, PN532_MODULATION_ISO14443A_106KBPS }; while (1) { printf("%s", CFG_PRINTF_NEWLINE); printf("Waiting for an ISO14443A card (Mifare Classic, etc.)%s", CFG_PRINTF_NEWLINE); // Send the command (and handle the most common errors) error = pn532Write(abtCommand, sizeof(abtCommand)); if (error) { // Something went wrong sending the command (probably the bus selection or wiring) switch(error) { case (PN532_ERROR_NOACK): case (PN532_ERROR_INVALIDACK): // No ACK response frame received from the PN532 printf("Ooops ... No valid ACK frame received!%s", CFG_PRINTF_NEWLINE); break; case (PN532_ERROR_I2C_NACK): // No ACK bit received to I2C start ... not same as PN532 ACK frame (bus pins not set correctly?) printf("Ooops ... No I2C ACK received! Are the bus select pins sets to I2C?%s", CFG_PRINTF_NEWLINE); break; case (PN532_ERROR_READYSTATUSTIMEOUT): // Timed out waiting for the ready bit to clear ... this can be intentional, though, in the // case of PN532_COMMAND_INLISTPASSIVETARGET since it will only clear when a card // enters the magnetic field! Handle with caution because it isn't always an error // Note: Only valid for I2C and SPI printf("Timed out waiting for Ready/IRQ%s", CFG_PRINTF_NEWLINE); break; default: printf("Ooops ... something went wrong! [PN532 Error Code: 0x%02X]%s", error, CFG_PRINTF_NEWLINE); break; } } else { // Commmand seems to have gone through ... do { // Keep reading until we get a response or an unexpected error condition error = pn532Read(response, &responseLen); systickDelay(25); } while (error == PN532_ERROR_RESPONSEBUFFEREMPTY); printf("%s", CFG_PRINTF_NEWLINE); printf("%-12s: ", "Received"); pn532PrintHex(response, responseLen); // Try to handle some potential frame errors // Unhandled errors are caught further down switch (error) { case (PN532_ERROR_PREAMBLEMISMATCH): // Frame should start with 0x00 0x00 0xFF! printf("Response frame doesn't start with expected preamble (00 00 FF)%s", CFG_PRINTF_NEWLINE); break; case (PN532_ERROR_APPLEVELERROR): printf("Application level error reported by PN532%s", CFG_PRINTF_NEWLINE); break; case (PN532_ERROR_LENCHECKSUMMISMATCH): printf("Frame length check/checksum mismatch%s", CFG_PRINTF_NEWLINE); break; default: // Other errors handled below break; } // Print the card details if possible if (!error) { /* Response for ISO14443A 106KBPS (Mifare Classic, etc.) See UM0701-02 section 7.3.5 for more information byte Description ------------- ------------------------------------------ b7 Tags Found b8 Tag Number (only one used in this example) b9..10 SENS_RES b11 SEL_RES b12 NFCID Length b13..NFCIDLen NFCID SENS_RES SEL_RES Manufacturer/Card Type NFCID Len -------- ------- ----------------------- --------- 00 04 08 NXP Mifare Classic 1K 4 bytes */ printf("%-12s: %d %s", "Tags Found", response[7], CFG_PRINTF_NEWLINE); printf("%-12s: %02X %02X %s", "SENS_RES", response[9], response[10], CFG_PRINTF_NEWLINE); printf("%-12s: %02X %s", "SEL_RES", response[11], CFG_PRINTF_NEWLINE); printf("%-12s: ", "NFCID"); size_t pos; for (pos=0; pos < response[12]; pos++) { printf("%02x ", response[13 + pos]); } printf(CFG_PRINTF_NEWLINE); if ((response[9] == 0x00) && (response[10] == 0x04) && (response[11] == 0x08)) { printf("Seems to be a Mifare Classic 1K Card%s", CFG_PRINTF_NEWLINE); } } else { // Oops .... something bad happened. Check 'error' printf("Ooops! Error %02X %s", error, CFG_PRINTF_NEWLINE); } } // Wait at least one second before trying again systickDelay(1000); } }