diff --git a/Software/lib/rfid-desfire/Desfire.cpp b/Software/lib/rfid-desfire/Desfire.cpp deleted file mode 100644 index 0acb3c0..0000000 --- a/Software/lib/rfid-desfire/Desfire.cpp +++ /dev/null @@ -1,971 +0,0 @@ -#include - -MFRC522::StatusCode DESFire::PICC_RequestATS(byte *atsBuffer, byte *atsLength) -{ - MFRC522::StatusCode result; - - // Build command buffer - atsBuffer[0] = 0xE0; //PICC_CMD_RATS; - atsBuffer[1] = 0x50; // FSD=64, CID=0 - - // Calculate CRC_A - result = PCD_CalculateCRC(atsBuffer, 2, &atsBuffer[2]); - if (result != STATUS_OK) { - return result; - } - - // Transmit the buffer and receive the response, validate CRC_A. - result = PCD_TransceiveData(atsBuffer, 4, atsBuffer, atsLength, NULL, 0, true); - if (result != STATUS_OK) { - PICC_HaltA(); - Serial.println("WTF???"); - return result; - } - - return result; -} // End PICC_RequestATS() - - /** - * Transmits Protocol and Parameter Selection Request (PPS) - * - * @return STATUS_OK on success, STATUS_??? otherwise. - */ -MFRC522::StatusCode DESFire::PICC_ProtocolAndParameterSelection(byte cid, ///< The lower nibble indicates the CID of the selected PICC in the range of 0x00 and 0x0E - byte pps0, ///< PPS0 - byte pps1 ///< PPS1 -) { - MFRC522::StatusCode result; - - byte ppsBuffer[5]; - byte ppsBufferSize = 5; - ppsBuffer[0] = 0xD0 | (cid & 0x0F); - ppsBuffer[1] = pps0; - ppsBuffer[2] = pps1; - - // Calculate CRC_A - result = PCD_CalculateCRC(ppsBuffer, 3, &ppsBuffer[3]); - if (result != STATUS_OK) { - return result; - } - - // Transmit the buffer and receive the response, validate CRC_A. - result = PCD_TransceiveData(ppsBuffer, 5, ppsBuffer, &ppsBufferSize, NULL, 0, true); - if (result == STATUS_OK) { - // This is how my MFRC522 is by default. - // Reading https://www.nxp.com/documents/data_sheet/MFRC522.pdf it seems CRC generation can only be disabled in this mode. - if (pps1 == 0x00) { - PCD_WriteRegister(TxModeReg, 0x00); - PCD_WriteRegister(RxModeReg, 0x00); - } - } - - return result; -} // End PICC_ProtocolAndParameterSelection() - -/** - * @see MIFARE_BlockExchangeWithData() - */ -DESFire::StatusCode DESFire::MIFARE_BlockExchange(mifare_desfire_tag *tag, byte cmd, byte *backData, byte *backLen) -{ - return MIFARE_BlockExchangeWithData(tag, cmd, NULL, NULL, backData, backLen); -} // End MIFARE_BlockExchange() - -/** - * - * Frame Format for DESFire APDUs - * ============================== - * - * The frame format for DESFire APDUs is based on only the ISO 14443-4 specifications for block formats. - * This is the format used by the example firmware, and seen in Figure 3. - * - PCB – Protocol Control Byte, this byte is used to transfer format information about each PDU block. - * - CID – Card Identifier field, this byte is used to identify specific tags. It contains a 4 bit CID value as well - * as information on the signal strength between the reader and the tag. - * - NAD – Node Address field, the example firmware does not support the use of NAD. - * - DESFire Command Code – This is discussed in the next section. - * - Data Bytes – This field contains all of the Data Bytes for the command - * - * |-----|-----|-----|---------|------|----------| - * | PCB | CID | NAD | Command | Data | Checksum | - * |-----|-----|-----|---------|------|----------| - * - * Documentation: http://read.pudn.com/downloads64/ebook/225463/M305_DESFireISO14443.pdf - * http://www.ti.com.cn/cn/lit/an/sloa213/sloa213.pdf - */ -DESFire::StatusCode DESFire::MIFARE_BlockExchangeWithData(mifare_desfire_tag *tag, byte cmd, byte *sendData, byte *sendLen, byte *backData, byte *backLen) -{ - StatusCode result; - - byte buffer[64]; - byte bufferSize = 64; - byte sendSize = 3; - - buffer[0] = tag->pcb; - buffer[1] = tag->cid; - buffer[2] = cmd; - - // Append data if available - if (sendData != NULL && sendLen != NULL) { - if (*sendLen > 0) { - memcpy(&buffer[3], sendData, *sendLen); - sendSize = sendSize + *sendLen; - } - } - - // Update the PCB - if (tag->pcb == 0x0A) - tag->pcb = 0x0B; - else - tag->pcb = 0x0A; - - // Calculate CRC_A - result.mfrc522 = PCD_CalculateCRC(buffer, sendSize, &buffer[sendSize]); - if (result.mfrc522 != STATUS_OK) { - return result; - } - - result.mfrc522 = PCD_TransceiveData(buffer, sendSize + 2, buffer, &bufferSize); - if (result.mfrc522 != STATUS_OK) { - return result; - } - - // Set the DESFire status code - result.desfire = (DesfireStatusCode)(buffer[2]); - - // Copy data to backData and backLen - if (backData != NULL && backLen != NULL) { - memcpy(backData, &buffer[3], bufferSize - 5); - *backLen = bufferSize - 5; - } - - return result; -} // End MIFARE_BlockExchangeWithData() - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetVersion(mifare_desfire_tag *tag, MIFARE_DESFIRE_Version_t *versionInfo) -{ - StatusCode result; - byte versionBuffer[64]; - byte versionBufferSize = 64; - - result = MIFARE_BlockExchange(tag, 0x60, versionBuffer, &versionBufferSize); - if (result.mfrc522 == STATUS_OK) { - byte hardwareVersion[2]; - byte storageSize; - - versionInfo->hardware.vendor_id = versionBuffer[0]; - versionInfo->hardware.type = versionBuffer[1]; - versionInfo->hardware.subtype = versionBuffer[2]; - versionInfo->hardware.version_major = versionBuffer[3]; - versionInfo->hardware.version_minor = versionBuffer[4]; - versionInfo->hardware.storage_size = versionBuffer[5]; - versionInfo->hardware.protocol = versionBuffer[6]; - - if (result.desfire == MF_ADDITIONAL_FRAME) { - result = MIFARE_BlockExchange(tag, 0xAF, versionBuffer, &versionBufferSize); - if (result.mfrc522 == STATUS_OK) { - versionInfo->software.vendor_id = versionBuffer[0]; - versionInfo->software.type = versionBuffer[1]; - versionInfo->software.subtype = versionBuffer[2]; - versionInfo->software.version_major = versionBuffer[3]; - versionInfo->software.version_minor = versionBuffer[4]; - versionInfo->software.storage_size = versionBuffer[5]; - versionInfo->software.protocol = versionBuffer[6]; - } else { - Serial.print("Failed to send AF: "); - Serial.println(GetStatusCodeName(result)); - } - - if (result.desfire == MF_ADDITIONAL_FRAME) { - byte nad = 0x60; - result = MIFARE_BlockExchange(tag, 0xAF, versionBuffer, &versionBufferSize); - if (result.mfrc522 == STATUS_OK) { - memcpy(versionInfo->uid, &versionBuffer[0], 7); - memcpy(versionInfo->batch_number, &versionBuffer[7], 5); - versionInfo->production_week = versionBuffer[12]; - versionInfo->production_year = versionBuffer[13]; - } else { - Serial.print("Failed to send AF: "); - Serial.println(GetStatusCodeName(result)); - } - } - - if (result.desfire == MF_ADDITIONAL_FRAME) { - Serial.println("GetVersion(): More data???"); - } - } - } - else { - Serial.println("Version(): Failure."); - } - - return result; -} // End MIFARE_DESFIRE_GetVersion - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_SelectApplication(mifare_desfire_tag *tag, mifare_desfire_aid_t *aid) -{ - StatusCode result; - - byte buffer[64]; - byte bufferSize = MIFARE_AID_SIZE; - - for (byte i = 0; i < MIFARE_AID_SIZE; i++) { - buffer[i] = aid->data[i]; - } - - result = MIFARE_BlockExchangeWithData(tag, 0x5A, buffer, &bufferSize, buffer, &bufferSize); - if (IsStatusCodeOK(result)) { - // keep track of the application - memcpy(tag->selected_application, aid->data, MIFARE_AID_SIZE); - } - - return result; -} - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetFileIDs(mifare_desfire_tag *tag, byte *files, byte *filesCount) -{ - StatusCode result; - - byte bufferSize = MIFARE_MAX_FILE_COUNT + 5; - byte buffer[bufferSize]; - - result = MIFARE_BlockExchange(tag, 0x6F, buffer, &bufferSize); - if (IsStatusCodeOK(result)) { - *filesCount = bufferSize; - memcpy(files, &buffer, *filesCount); - } - - return result; -} // End MIFARE_DESFIRE_GetFileIDs - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetFileSettings(mifare_desfire_tag *tag, byte *file, mifare_desfire_file_settings_t *fileSettings) -{ - StatusCode result; - - byte buffer[21]; - byte bufferSize = 21; - byte sendLen = 1; - - buffer[0] = *file; - - result = MIFARE_BlockExchangeWithData(tag, 0xF5, buffer, &sendLen, buffer, &bufferSize); - if (IsStatusCodeOK(result)) { - fileSettings->file_type = buffer[0]; - fileSettings->communication_settings = buffer[1]; - fileSettings->access_rights = ((uint16_t)(buffer[2]) << 8) | (buffer[3]); - - switch (buffer[0]) { - case MDFT_STANDARD_DATA_FILE: - case MDFT_BACKUP_DATA_FILE: - fileSettings->settings.standard_file.file_size = ((uint32_t)(buffer[4])) | ((uint32_t)(buffer[5]) << 8) | ((uint32_t)(buffer[6]) << 16); - break; - - case MDFT_VALUE_FILE_WITH_BACKUP: - fileSettings->settings.value_file.lower_limit = ((uint32_t)(buffer[4])) | ((uint32_t)(buffer[5]) << 8) | ((uint32_t)(buffer[6]) << 16) | ((uint32_t)(buffer[7]) << 24); - fileSettings->settings.value_file.upper_limit = ((uint32_t)(buffer[8])) | ((uint32_t)(buffer[9]) << 8) | ((uint32_t)(buffer[10]) << 16) | ((uint32_t)(buffer[11]) << 24); - fileSettings->settings.value_file.limited_credit_value = ((uint32_t)(buffer[12])) | ((uint32_t)(buffer[13]) << 8) | ((uint32_t)(buffer[14]) << 16) | ((uint32_t)(buffer[15]) << 24); - fileSettings->settings.value_file.limited_credit_enabled = buffer[16]; - break; - - case MDFT_LINEAR_RECORD_FILE_WITH_BACKUP: - case MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP: - fileSettings->settings.record_file.record_size = ((uint32_t)(buffer[4])) | ((uint32_t)(buffer[5]) << 8) | ((uint32_t)(buffer[6]) << 16); - fileSettings->settings.record_file.max_number_of_records = ((uint32_t)(buffer[7])) | ((uint32_t)(buffer[8]) << 8) | ((uint32_t)(buffer[9]) << 16); - fileSettings->settings.record_file.current_number_of_records = ((uint32_t)(buffer[10])) | ((uint32_t)(buffer[11]) << 8) | ((uint32_t)(buffer[12]) << 16); - break; - - default: - //return FAIL; - result.mfrc522 = STATUS_ERROR; - return result; - } - } - - return result; -} // End MIFARE_DESFIRE_GetFileSettings - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetKeySettings(mifare_desfire_tag *tag, byte *settings, byte *maxKeys) -{ - StatusCode result; - - byte buffer[7]; - byte bufferSize = 7; - - result = MIFARE_BlockExchange(tag, 0x45, buffer, &bufferSize); - if (IsStatusCodeOK(result)) { - *settings = buffer[0]; - *maxKeys = buffer[1]; - } - - return result; -} // End MIFARE_DESFIRE_GetKeySettings() - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetKeyVersion(mifare_desfire_tag *tag, byte key, byte *version) -{ - StatusCode result; - - byte buffer[6]; - byte bufferSize = 6; - byte sendLen = 1; - - buffer[0] = key; - - result = MIFARE_BlockExchangeWithData(tag, 0x64, buffer, &sendLen, buffer, &bufferSize); - if (IsStatusCodeOK(result)) { - *version = buffer[0]; - } - - return result; -} - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_ReadData(mifare_desfire_tag *tag, byte fid, uint32_t offset, uint32_t length, byte *backData, size_t *backLen) -{ - StatusCode result; - - byte buffer[64]; - byte bufferSize = 64; - byte sendLen = 7; - size_t outSize = 0; - - // file ID - buffer[0] = fid; - // offset - buffer[1] = (offset & 0x00000F); - buffer[2] = (offset & 0x00FF00) >> 8; - buffer[3] = (offset & 0xFF0000) >> 16; - // length - buffer[4] = (length & 0x0000FF); - buffer[5] = (length & 0x00FF00) >> 8; - buffer[6] = (length & 0xFF0000) >> 16; - - result = MIFARE_BlockExchangeWithData(tag, 0xBD, buffer, &sendLen, buffer, &bufferSize); - if (result.mfrc522 == STATUS_OK) { - do { - // Copy the data - memcpy(backData + outSize, buffer, bufferSize); - outSize += bufferSize; - *backLen = outSize; - - if (result.desfire == MF_ADDITIONAL_FRAME) { - result = MIFARE_BlockExchange(tag, 0xAF, buffer, &bufferSize); - } - } while (result.mfrc522 == STATUS_OK && result.desfire == MF_ADDITIONAL_FRAME); - } - - return result; -} - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetValue(mifare_desfire_tag *tag, byte fid, int32_t *value) -{ - StatusCode result; - - byte buffer[MFRC522::FIFO_SIZE]; - byte bufferSize = MFRC522::FIFO_SIZE; - byte sendLen = 1; - size_t outSize = 0; - - buffer[0] = fid; - - result = MIFARE_BlockExchangeWithData(tag, 0x6C, buffer, &sendLen, buffer, &bufferSize); - if (IsStatusCodeOK(result)) { - *value = ((uint32_t)buffer[0] | ((uint32_t)buffer[1] << 8) | ((uint32_t)buffer[2] << 16) | ((uint32_t)buffer[3] << 24)); - } - - return result; -} // End MIFARE_DESFIRE_GetValue() - -DESFire::StatusCode DESFire::MIFARE_DESFIRE_GetApplicationIds(mifare_desfire_tag *tag, mifare_desfire_aid_t *aids, byte *applicationCount) -{ - StatusCode result; - - // MIFARE_MAX_APPLICATION_COUNT * MIFARE_AID_SIZE + PCB (1 byte) + CID (1 byte) + Checksum (2 bytes) - // I also add an extra byte in case NAD is needed - byte bufferSize = (MIFARE_MAX_APPLICATION_COUNT * MIFARE_AID_SIZE) + 5; - byte buffer[bufferSize]; - byte aidBuffer[MIFARE_MAX_APPLICATION_COUNT * MIFARE_AID_SIZE]; - byte aidBufferSize = 0; - - result = MIFARE_BlockExchange(tag, 0x6A, buffer, &bufferSize); - if (result.mfrc522 != STATUS_OK) - return result; - - // MIFARE_MAX_APPLICATION_COUNT (28) * MIFARE_AID_SIZE + PCB (1) + CID (1) + Checksum (2) = 88 - // Even if the NAD byte is not present we could GET a 0xAF response. - if (result.desfire == MF_OPERATION_OK && bufferSize == 0x00) { - // Empty application list - *applicationCount = 0; - return result; - } - - memcpy(aidBuffer, buffer, bufferSize); - aidBufferSize = bufferSize; - - while (result.desfire == MF_ADDITIONAL_FRAME) { - bufferSize = (MIFARE_MAX_APPLICATION_COUNT * MIFARE_AID_SIZE) + 5; - result = MIFARE_BlockExchange(tag, 0xAF, buffer, &bufferSize); - if (result.mfrc522 != STATUS_OK) - return result; - - // Make sure we have space (Just in case) - if ((aidBufferSize + bufferSize) > (MIFARE_MAX_APPLICATION_COUNT * MIFARE_AID_SIZE)) { - result.mfrc522 = STATUS_NO_ROOM; - return result; - } - - // Append the new data - memcpy(aidBuffer + aidBufferSize, buffer, bufferSize); - } - - - // Applications are identified with a 3 byte application identifier(AID) - // we also received the status byte: - if ((aidBufferSize % 3) != 0) { - Serial.println(F("MIFARE_DESFIRE_GetApplicationIds(): Data is not a modulus of 3.")); - // TODO: Some kind of failure - result.mfrc522 = STATUS_ERROR; - return result; - } - - *applicationCount = aidBufferSize / 3; - - for (byte i = 0; i < *applicationCount; i++) { - aids[i].data[0] = aidBuffer[(i * 3)]; - aids[i].data[1] = aidBuffer[1 + (i * 3)]; - aids[i].data[2] = aidBuffer[2 + (i * 3)]; - } - - return result; -} // End MIFARE_DESFIRE_GetApplicationIds() - -/** - * Returns a __FlashStringHelper pointer to a status code name. - * - * @return const __FlashStringHelper * - */ -const __FlashStringHelper *DESFire::GetStatusCodeName(StatusCode code) -{ - if (code.mfrc522 != MFRC522::STATUS_OK) { - return MFRC522::GetStatusCodeName(code.mfrc522); - } - - switch (code.desfire) { - case MF_OPERATION_OK: return F("Successful operation."); - case MF_NO_CHANGES: return F("No changes done to backup files."); - case MF_OUT_OF_EEPROM_ERROR: return F("Insufficient NV-Mem. to complete cmd."); - case MF_ILLEGAL_COMMAND_CODE: return F("Command code not supported."); - case MF_INTEGRITY_ERROR: return F("CRC or MAC does not match data."); - case MF_NO_SUCH_KEY: return F("Invalid key number specified."); - case MF_LENGTH_ERROR: return F("Length of command string invalid."); - case MF_PERMISSION_ERROR: return F("Curr conf/status doesnt allow cmd."); - case MF_PARAMETER_ERROR: return F("Value of the parameter(s) invalid."); - case MF_APPLICATION_NOT_FOUND: return F("Requested AID not present on PICC."); - case MF_APPL_INTEGRITY_ERROR: return F("Unrecoverable err within app."); - case MF_AUTHENTICATION_ERROR: return F("Current authentication status doesn't allow requested command."); - case MF_ADDITIONAL_FRAME: return F("Additional data frame to be sent."); - case MF_BOUNDARY_ERROR: return F("Attempt to read/write beyond limits."); - case MF_PICC_INTEGRITY_ERROR: return F("Unrecoverable error within PICC."); - case MF_COMMAND_ABORTED: return F("Previous command not fully completed."); - case MF_PICC_DISABLED_ERROR: return F("PICC disabled by unrecoverable error."); - case MF_COUNT_ERROR: return F("Cant create more apps, already @ 28."); - case MF_DUPLICATE_ERROR: return F("Cant create dup. file/app."); - case MF_EEPROM_ERROR: return F("Couldnt complete NV-write operation."); - case MF_FILE_NOT_FOUND: return F("Specified file number doesnt exist."); - case MF_FILE_INTEGRITY_ERROR: return F("Unrecoverable error within file."); - default: return F("Unknown error"); - } -} // End GetStatusCodeName() - -const __FlashStringHelper *DESFire::GetFileTypeName(mifare_desfire_file_types fileType) -{ - switch (fileType) { - case MDFT_STANDARD_DATA_FILE: return F("Standard data file."); - case MDFT_BACKUP_DATA_FILE: return F("Backup data file."); - case MDFT_VALUE_FILE_WITH_BACKUP: return F("Value file with backup."); - case MDFT_LINEAR_RECORD_FILE_WITH_BACKUP: return F("Linear record file with backup."); - case MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP: return F("Cyclic record file with backup."); - default: return F("Unknown file type."); - } -} // End GetFileTypeName() - -const __FlashStringHelper *DESFire::GetCommunicationModeName(mifare_desfire_communication_modes communicationMode) -{ - switch (communicationMode) { - case MDCM_PLAIN: return(F("Plain Communication.")); - case MDCM_MACED: return(F("Plain Comm secured by DES/3DES MACing.")); - case MDCM_ENCIPHERED: return(F("Fully DES/3DES enciphered comm.")); - default: return F("Unknown communication mode."); - } -} // End GetCommunicationModeName() - -bool DESFire::IsStatusCodeOK(StatusCode code) -{ - if (code.mfrc522 != STATUS_OK) - return false; - if (code.desfire != MF_OPERATION_OK) - return false; - - return true; -} // End IsStatusCodeOK(); - -void DESFire::PICC_DumpMifareDesfireMasterKey(mifare_desfire_tag *tag) -{ - StatusCode response; - mifare_desfire_aid_t aid; - - aid.data[0] = 0x00; - aid.data[1] = 0x00; - aid.data[2] = 0x00; - - Serial.println(F("-- Desfire Master Key ---------------------------------------")); - Serial.println(F("-------------------------------------------------------------")); - // Select the current application. - response = MIFARE_DESFIRE_SelectApplication(tag, &aid); - if (!IsStatusCodeOK(response)) { - Serial.println(F("Error: Failed to select application.")); - Serial.println(GetStatusCodeName(response)); - Serial.println(F("-------------------------------------------------------------")); - return; - } - - // Get Key settings - byte keySettings; - byte keyCount = 0; - byte keyVersion; - - response = MIFARE_DESFIRE_GetKeySettings(tag, &keySettings, &keyCount); - if (IsStatusCodeOK(response)) { - Serial.print(F(" Key settings : 0x")); - if (keySettings < 0x10) - Serial.print(F("0")); - Serial.println(keySettings, HEX); - - Serial.print(F(" Max num keys : ")); - Serial.println(keyCount); - - // Output key versions - if (keyCount > 0) { - Serial.println(F(" ----------------------------------------------------------")); - Serial.println(F(" Key Versions")); - - // Get key versions (No output will be outputed later) - for (byte ixKey = 0; ixKey < keyCount; ixKey++) { - response = MIFARE_DESFIRE_GetKeyVersion(tag, ixKey, &keyVersion); - Serial.print(F(" Key 0x")); - if (ixKey < 0x10) - Serial.print(F("0")); - Serial.print(ixKey, HEX); - Serial.print(F(" : ")); - - if (IsStatusCodeOK(response)) { - Serial.print(F("0x")); - if (keyVersion < 0x10) - Serial.print(F("0")); - Serial.println(keyVersion, HEX); - } else { - Serial.println(GetStatusCodeName(response)); - } - } - } - } - else { - Serial.println(F(" Error: Failed to get application key settings.")); - // Just to be sure.. - keyCount = 0; - } - - Serial.println(F("-------------------------------------------------------------")); -} // End PICC_DumpMifareDesfireMasterKey() - -void DESFire::PICC_DumpMifareDesfireVersion(mifare_desfire_tag *tag, MIFARE_DESFIRE_Version_t *versionInfo) -{ - Serial.println(F("-- Desfire Information --------------------------------------")); - Serial.println(F("-------------------------------------------------------------")); - switch (versionInfo->hardware.version_major) { - case 0x00: - Serial.println(F(" Card type : MIFARE DESFire (MF3ICD40)")); - switch (versionInfo->hardware.storage_size) { - case 0x16: - Serial.print(F(" 2K")); - break; - case 0x18: - Serial.print(F(" 4K")); - break; - case 0x1A: - Serial.print(F(" 8K")); - break; - } - Serial.println(); - break; - case 0x01: - Serial.print(F(" Card type : MIFARE DESFire EV1")); - switch (versionInfo->hardware.storage_size) { - case 0x16: - Serial.print(F(" 2K")); - break; - case 0x18: - Serial.print(F(" 4K")); - break; - case 0x1A: - Serial.print(F(" 8K")); - break; - } - Serial.println(); - break; - case 0x12: - Serial.print(F(" Card type : MIFARE DESFire EV2")); - switch (versionInfo->hardware.storage_size) { - case 0x16: - Serial.print(F(" 2K")); - break; - case 0x18: - Serial.print(F(" 4K")); - break; - case 0x1A: - Serial.print(F(" 8K")); - break; - } - Serial.println(); - break; - } - - // UID - Serial.print(F(" UID :")); - for (byte i = 0; i < 7; i++) { - if (versionInfo->uid[i] < 0x10) - Serial.print(F(" 0")); - else - Serial.print(F(" ")); - Serial.print(versionInfo->uid[i], HEX); - } - Serial.println(); - - // Batch - Serial.print(F(" Batch number :")); - for (byte i = 0; i < 5; i++) { - if (versionInfo->batch_number[i] < 0x10) - Serial.print(F(" 0")); - else - Serial.print(F(" ")); - Serial.print(versionInfo->batch_number[i], HEX); - } - Serial.println(); - - Serial.print(F(" Production week : 0x")); - if (versionInfo->production_week < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->production_week, HEX); - - Serial.print(F(" Production year : 0x")); - if (versionInfo->production_year < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->production_year, HEX); - - Serial.println(F(" ----------------------------------------------------------")); - Serial.println(F(" Hardware Information")); - Serial.print(F(" Vendor ID : 0x")); - if (versionInfo->hardware.vendor_id < 0x10) - Serial.print(F("0")); - Serial.print(versionInfo->hardware.vendor_id, HEX); - if (versionInfo->hardware.vendor_id == 0x04) - Serial.print(F(" (NXP)")); - Serial.println(); - - Serial.print(F(" Type : 0x")); - if (versionInfo->hardware.type < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->hardware.type, HEX); - - Serial.print(F(" Subtype : 0x")); - if (versionInfo->hardware.subtype < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->hardware.subtype, HEX); - - Serial.print(F(" Version : ")); - Serial.print(versionInfo->hardware.version_major); - Serial.print(F(".")); - Serial.println(versionInfo->hardware.version_minor); - - Serial.print(F(" Storage size : 0x")); - if (versionInfo->hardware.storage_size < 0x10) - Serial.print(F("0")); - Serial.print(versionInfo->hardware.storage_size, HEX); - switch (versionInfo->hardware.storage_size) { - case 0x16: - Serial.print(F(" (2048 bytes)")); - break; - case 0x18: - Serial.print(F(" (4096 bytes)")); - break; - case 0x1A: - Serial.print(F(" (8192 bytes)")); - break; - } - Serial.println(); - - Serial.print(F(" Protocol : 0x")); - if (versionInfo->hardware.protocol < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->hardware.protocol, HEX); - - Serial.println(F(" ----------------------------------------------------------")); - Serial.println(F(" Software Information")); - Serial.print(F(" Vendor ID : 0x")); - if (versionInfo->software.vendor_id < 0x10) - Serial.print(F("0")); - Serial.print(versionInfo->software.vendor_id, HEX); - if (versionInfo->software.vendor_id == 0x04) - Serial.print(F(" (NXP)")); - Serial.println(); - - Serial.print(F(" Type : 0x")); - if (versionInfo->software.type < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->software.type, HEX); - - Serial.print(F(" Subtype : 0x")); - if (versionInfo->software.subtype < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->software.subtype, HEX); - - Serial.print(F(" Version : ")); - Serial.print(versionInfo->software.version_major); - Serial.print(F(".")); - Serial.println(versionInfo->software.version_minor); - - Serial.print(F(" Storage size : 0x")); - if (versionInfo->software.storage_size < 0x10) - Serial.print(F("0")); - Serial.print(versionInfo->software.storage_size, HEX); - switch (versionInfo->software.storage_size) { - case 0x16: - Serial.print(F(" (2048 bytes)")); - break; - case 0x18: - Serial.print(F(" (4096 bytes)")); - break; - case 0x1A: - Serial.print(F(" (8192 bytes)")); - break; - } - Serial.println(); - - Serial.print(F(" Protocol : 0x")); - if (versionInfo->software.protocol < 0x10) - Serial.print(F("0")); - Serial.println(versionInfo->software.protocol, HEX); - - Serial.println(F("-------------------------------------------------------------")); -} - -void DESFire::PICC_DumpMifareDesfireApplication(mifare_desfire_tag *tag, mifare_desfire_aid_t *aid) -{ - StatusCode response; - - Serial.println(F("-- Desfire Application --------------------------------------")); - Serial.println(F("-------------------------------------------------------------")); - Serial.print(F(" AID :")); - for (byte i = 0; i < 3; i++) { - if (aid->data[i] < 0x10) - Serial.print(F(" 0")); - else - Serial.print(F(" ")); - Serial.print(aid->data[i], HEX); - } - Serial.println(); - - // Select the current application. - response = MIFARE_DESFIRE_SelectApplication(tag, aid); - if (!IsStatusCodeOK(response)) { - Serial.println(F("Error: Failed to select application.")); - Serial.println(GetStatusCodeName(response)); - Serial.println(F("-------------------------------------------------------------")); - return; - } - - // Get Key settings - byte keySettings; - byte keyCount = 0; - byte keyVersion[16]; - - response = MIFARE_DESFIRE_GetKeySettings(tag, &keySettings, &keyCount); - if (IsStatusCodeOK(response)) { - Serial.print(F(" Key settings : 0x")); - if (keySettings < 0x10) - Serial.print(F("0")); - Serial.println(keySettings, HEX); - - Serial.print(F(" Max num keys : ")); - Serial.println(keyCount); - - // Get key versions (No output will be outputed later) - for (byte ixKey = 0; ixKey < keyCount; ixKey++) { - response = MIFARE_DESFIRE_GetKeyVersion(tag, ixKey, &(keyVersion[ixKey])); - if (!IsStatusCodeOK(response)) - keyVersion[ixKey] = 0x00; - } - - } else { - Serial.println(F(" Error: Failed to get application key settings.")); - // Just to be sure.. - keyCount = 0; - } - - // Get the files - byte files[MIFARE_MAX_FILE_COUNT]; - byte filesCount = 0; - response = MIFARE_DESFIRE_GetFileIDs(tag, files, &filesCount); - if (!IsStatusCodeOK(response)) { - Serial.println(F(" Error: Failed to get application file IDs.")); - Serial.print(F(" ")); - Serial.println(GetStatusCodeName(response)); - Serial.println(F("-------------------------------------------------------------")); - return; - } - - // Number of files - Serial.print(F(" Num. Files : ")); - Serial.println(filesCount); - - // Output key versions - if (keyCount > 0) { - Serial.println(F(" ----------------------------------------------------------")); - Serial.println(F(" Key Versions")); - for (byte ixKey = 0; ixKey < keyCount; ixKey++) { - Serial.print(F(" Key 0x")); - if (ixKey < 0x10) - Serial.print(F("0")); - Serial.print(ixKey, HEX); - Serial.print(F(" : 0x")); - if (keyVersion[ixKey] < 0x10) - Serial.print(F("0")); - Serial.println(keyVersion[ixKey], HEX); - } - } - - for (byte i = 0; i < filesCount; i++) { - Serial.println(F(" ----------------------------------------------------------")); - Serial.println(F(" File Information")); - Serial.print(F(" File ID : 0x")); - if (files[i] < 0x10) - Serial.print(F("0")); - Serial.println(files[i], HEX); - - // Get file settings - mifare_desfire_file_settings_t fileSettings; - - response = MIFARE_DESFIRE_GetFileSettings(tag, &(files[i]), &fileSettings); - if (IsStatusCodeOK(response)) { - Serial.print(F(" File Type : 0x")); - if (fileSettings.file_type < 0x10) - Serial.print(F("0")); - Serial.print(fileSettings.file_type, HEX); - Serial.print(F(" (")); - Serial.print(GetFileTypeName((mifare_desfire_file_types)fileSettings.file_type)); - Serial.println(F(")")); - - Serial.print(F(" Communication : 0x")); - if (fileSettings.communication_settings < 0x10) - Serial.print(F("0")); - Serial.print(fileSettings.communication_settings, HEX); - Serial.print(F(" (")); - Serial.print(GetCommunicationModeName((mifare_desfire_communication_modes)fileSettings.communication_settings)); - Serial.println(F(")")); - - Serial.print(F(" Access rights : 0x")); - Serial.println(fileSettings.access_rights, HEX); - - switch (fileSettings.file_type) { - case MDFT_STANDARD_DATA_FILE: - case MDFT_BACKUP_DATA_FILE: - Serial.print(F(" File Size : ")); - Serial.print(fileSettings.settings.standard_file.file_size); - Serial.println(F(" bytes")); - break; - case MDFT_VALUE_FILE_WITH_BACKUP: - Serial.print(F(" Lower Limit : ")); - Serial.println(fileSettings.settings.value_file.lower_limit); - Serial.print(F(" Upper Limit : ")); - Serial.println(fileSettings.settings.value_file.upper_limit); - Serial.print(F(" Limited credit : ")); - Serial.println(fileSettings.settings.value_file.limited_credit_value); - Serial.print(F(" Limited credit : ")); - - if (fileSettings.settings.value_file.limited_credit_enabled == 0x00) - Serial.print(F("Disabled (")); - else - Serial.print(F("Enabled (0x")); - if (fileSettings.settings.value_file.limited_credit_enabled < 0x10) - Serial.print(F("0")); - Serial.print(fileSettings.settings.value_file.limited_credit_enabled, HEX); - Serial.println(F(")")); - - break; - - case MDFT_LINEAR_RECORD_FILE_WITH_BACKUP: - case MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP: - Serial.print(F(" Record size : ")); - Serial.println(fileSettings.settings.record_file.record_size); - Serial.print(F(" max num records: ")); - Serial.println(fileSettings.settings.record_file.max_number_of_records); - Serial.print(F(" num records : ")); - Serial.println(fileSettings.settings.record_file.current_number_of_records); - break; - } - - switch (fileSettings.file_type) { - case MDFT_STANDARD_DATA_FILE: - case MDFT_BACKUP_DATA_FILE: - { - // Get file data - byte fileContent[fileSettings.settings.standard_file.file_size]; - size_t fileContentLength = fileSettings.settings.standard_file.file_size; - response = MIFARE_DESFIRE_ReadData(tag, files[i], 0, fileSettings.settings.standard_file.file_size, fileContent, &fileContentLength); - if (response.mfrc522 == STATUS_OK) { - Serial.println(F(" ------------------------------------------------------")); - Serial.println(F(" Data")); - - if (response.desfire == MF_OPERATION_OK || response.desfire == MF_ADDITIONAL_FRAME) { - for (unsigned int iByte = 0; iByte < fileContentLength; iByte++) { - if ((iByte % 16) == 0) { - if (iByte != 0) - Serial.println(); - Serial.print(F(" ")); - } - if (fileContent[iByte] < 0x10) - Serial.print(F(" 0")); - else - Serial.print(F(" ")); - Serial.print(fileContent[iByte], HEX); - } - Serial.println(); - } - else { - Serial.print(F(" ")); - Serial.println(GetStatusCodeName(response)); - } - } - } - break; - case MDFT_VALUE_FILE_WITH_BACKUP: - { - // Get value - int32_t fileValue; - response = MIFARE_DESFIRE_GetValue(tag, files[i], &fileValue); - Serial.print(F(" Value : ")); - if (IsStatusCodeOK(response)) { - Serial.println(fileValue); - } else { - Serial.println(GetStatusCodeName(response)); - } - } - break; - } - - } else { - Serial.println(F(" Error: Failed to get file settings.")); - Serial.print(F(" ")); - Serial.println(GetStatusCodeName(response)); - } - } - - - Serial.println(F("-------------------------------------------------------------")); -} \ No newline at end of file diff --git a/Software/lib/rfid-desfire/Desfire.h b/Software/lib/rfid-desfire/Desfire.h deleted file mode 100644 index 7c28d42..0000000 --- a/Software/lib/rfid-desfire/Desfire.h +++ /dev/null @@ -1,187 +0,0 @@ -#ifndef DESFIRE_h -#define DESFIRE_h - -#include -#include -#include - -/* -------------------------------------- -* DESFire Logical Structure -* -------------------------------------- -*/ -#define MIFARE_MAX_APPLICATION_COUNT 28 /* max applications on one PICC */ -#define MIFARE_MAX_FILE_COUNT 16 /* max # of files in each application */ -#define MIFARE_UID_BYTES 7 /* number of UID bytes */ -#define MIFARE_AID_SIZE 3 /* number of AID bytes */ - -class DESFire : public MFRC522 { -public: - // DESFire Status and Error Codes. - enum DesfireStatusCode : byte { - MF_OPERATION_OK = 0x00, /* successful operation */ - MF_NO_CHANGES = 0x0C, /* no changes done to backup files */ - MF_OUT_OF_EEPROM_ERROR = 0x0E, /* insufficient NV-Mem. to complete cmd */ - MF_ILLEGAL_COMMAND_CODE = 0x1C, /* command code not supported */ - MF_INTEGRITY_ERROR = 0x1E, /* CRC or MAC does not match data */ - MF_NO_SUCH_KEY = 0x40, /* invalid key number specified */ - MF_LENGTH_ERROR = 0x7E, /* length of command string invalid */ - MF_PERMISSION_ERROR = 0x9D, /* curr conf/status doesnt allow cmd */ - MF_PARAMETER_ERROR = 0x9E, /* value of the parameter(s) invalid */ - MF_APPLICATION_NOT_FOUND = 0xA0, /* requested AID not present on PICC */ - MF_APPL_INTEGRITY_ERROR = 0xA1, /* unrecoverable err within app */ - MF_AUTHENTICATION_ERROR = 0xAE, /* cur auth status doesnt allow req cmd */ - MF_ADDITIONAL_FRAME = 0xAF, /* additional data frame to be sent */ - MF_BOUNDARY_ERROR = 0xBE, /* attempt to read/write beyond limits */ - MF_PICC_INTEGRITY_ERROR = 0xC1, /* unrecoverable error within PICC */ - MF_COMMAND_ABORTED = 0xCA, /* previous command not fully completed */ - MF_PICC_DISABLED_ERROR = 0xCD, /* PICC disabled by unrecoverable error */ - MF_COUNT_ERROR = 0xCE, /* cant create more apps, already @ 28 */ - MF_DUPLICATE_ERROR = 0xDE, /* cant create dup. file/app */ - MF_EEPROM_ERROR = 0xEE, /* couldnt complete NV-write operation */ - MF_FILE_NOT_FOUND = 0xF0, /* specified file number doesnt exist */ - MF_FILE_INTEGRITY_ERROR = 0xF1 /* unrecoverable error within file */ - }; - - // DESFire file types - enum mifare_desfire_file_types : byte { - MDFT_STANDARD_DATA_FILE = 0x00, - MDFT_BACKUP_DATA_FILE = 0x01, - MDFT_VALUE_FILE_WITH_BACKUP = 0x02, - MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03, - MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04 - }; - - // DESFire communication modes - enum mifare_desfire_communication_modes : byte { - MDCM_PLAIN = 0x00, /* Plain Communication */ - MDCM_MACED = 0x01, /* Plain Comm secured by DES/3DES MACing */ - MDCM_ENCIPHERED = 0x03 /* Fully DES/3DES enciphered comm. */ - }; - - // A struct used for passing a MIFARE DESFire Version - typedef struct { - struct { - uint8_t vendor_id; - uint8_t type; - uint8_t subtype; - uint8_t version_major; - uint8_t version_minor; - uint8_t storage_size; - uint8_t protocol; - } hardware; - - struct { - uint8_t vendor_id; - uint8_t type; - uint8_t subtype; - uint8_t version_major; - uint8_t version_minor; - uint8_t storage_size; - uint8_t protocol; - } software; - - uint8_t uid[7]; - uint8_t batch_number[5]; - uint8_t production_week; - uint8_t production_year; - } MIFARE_DESFIRE_Version_t; - - typedef struct { - uint8_t data[MIFARE_AID_SIZE]; - } mifare_desfire_aid_t; - - typedef struct { - MFRC522::StatusCode mfrc522; - DesfireStatusCode desfire; - } StatusCode; - - // A struct used for passing a MIFARE DESFire Version - typedef struct { - uint8_t file_type; - uint8_t communication_settings; - uint16_t access_rights; - - union { - struct { - uint32_t file_size; - } standard_file; - struct { - int32_t lower_limit; - int32_t upper_limit; - int32_t limited_credit_value; - uint8_t limited_credit_enabled; - } value_file; - struct { - uint32_t record_size; - uint32_t max_number_of_records; - uint32_t current_number_of_records; - } record_file; /* linear and cyclic record files */ - } settings; - } mifare_desfire_file_settings_t; - - typedef struct { - byte cid; // Card ID - byte pcb; // Protocol Control Byte - byte selected_application[MIFARE_AID_SIZE]; - } mifare_desfire_tag; - - ///////////////////////////////////////////////////////////////////////////////////// - // Functions for setting up the Arduino - ///////////////////////////////////////////////////////////////////////////////////// - explicit DESFire() : MFRC522() {}; - explicit DESFire(byte resetPowerDownPin) : MFRC522(resetPowerDownPin) {}; - explicit DESFire(byte chipSelectPin, byte resetPowerDownPin) : MFRC522(chipSelectPin, resetPowerDownPin) {}; - - ///////////////////////////////////////////////////////////////////////////////////// - // ISO/IEC 14443 functions not currentlly present in MFRC522 library - ///////////////////////////////////////////////////////////////////////////////////// - MFRC522::StatusCode PICC_RequestATS(byte *atsBuffer, byte *atsLength); - MFRC522::StatusCode PICC_ProtocolAndParameterSelection(byte cid, byte pps0, byte pps1 = 0x00); - - ///////////////////////////////////////////////////////////////////////////////////// - // Functions for MIFARE DESFire - ///////////////////////////////////////////////////////////////////////////////////// - StatusCode MIFARE_DESFIRE_GetVersion(mifare_desfire_tag *tag, MIFARE_DESFIRE_Version_t *versionInfo); - StatusCode MIFARE_DESFIRE_GetApplicationIds(mifare_desfire_tag *tag, mifare_desfire_aid_t *aids, byte *applicationCount); - StatusCode MIFARE_DESFIRE_SelectApplication(mifare_desfire_tag *tag, mifare_desfire_aid_t *aid); - StatusCode MIFARE_DESFIRE_GetKeySettings(mifare_desfire_tag *tag, byte *settings, byte *maxKeys); - StatusCode MIFARE_DESFIRE_GetKeyVersion(mifare_desfire_tag *tag, byte key, byte *version); - - ///////////////////////////////////////////////////////////////////////////////////// - // MIFARE DESFire application level commands - ///////////////////////////////////////////////////////////////////////////////////// - StatusCode MIFARE_DESFIRE_GetFileIDs(mifare_desfire_tag *tag, byte *files, byte *filesCount); - StatusCode MIFARE_DESFIRE_GetFileSettings(mifare_desfire_tag *tag, byte *file, mifare_desfire_file_settings_t *fileSettings); - - ///////////////////////////////////////////////////////////////////////////////////// - // MIFARE DESFire data manipulation commands - ///////////////////////////////////////////////////////////////////////////////////// - StatusCode MIFARE_DESFIRE_ReadData(mifare_desfire_tag *tag, byte fid, uint32_t offset, uint32_t length, byte *backData, size_t *backLen); - StatusCode MIFARE_DESFIRE_GetValue(mifare_desfire_tag *tag, byte fid, int32_t *value); - - ///////////////////////////////////////////////////////////////////////////////////// - // Support functions - ///////////////////////////////////////////////////////////////////////////////////// - static const __FlashStringHelper *GetDesfireStatusCodeName(DesfireStatusCode code); - virtual const __FlashStringHelper *GetStatusCodeName(MFRC522::StatusCode code) { return MFRC522::GetStatusCodeName(code); }; - static const __FlashStringHelper *GetStatusCodeName(StatusCode code); - static const __FlashStringHelper *GetFileTypeName(mifare_desfire_file_types fileType); - static const __FlashStringHelper *GetCommunicationModeName(mifare_desfire_communication_modes communicationMode); - bool IsStatusCodeOK(StatusCode code); - - ///////////////////////////////////////////////////////////////////////////////////// - // Functions for debugging - ///////////////////////////////////////////////////////////////////////////////////// - void PICC_DumpMifareDesfireMasterKey(mifare_desfire_tag *tag); - void PICC_DumpMifareDesfireVersion(mifare_desfire_tag *tag, MIFARE_DESFIRE_Version_t *versionInfo); - void PICC_DumpMifareDesfireApplication(mifare_desfire_tag *tag, mifare_desfire_aid_t *aid); - -protected: - ///////////////////////////////////////////////////////////////////////////////////// - // Helper methods - ///////////////////////////////////////////////////////////////////////////////////// - StatusCode MIFARE_BlockExchange(mifare_desfire_tag *tag, byte cmd, byte *backData = NULL, byte *backLen = NULL); - StatusCode MIFARE_BlockExchangeWithData(mifare_desfire_tag *tag, byte cmd, byte *sendData = NULL, byte *sendLen = NULL, byte *backData = NULL, byte *backLen = NULL); -}; - -#endif \ No newline at end of file diff --git a/Software/lib/rfid-desfire/README.md b/Software/lib/rfid-desfire/README.md deleted file mode 100644 index 42df717..0000000 --- a/Software/lib/rfid-desfire/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# RFID-DESFire # - -Arduino library for MFRC522 and other RFID RC522 based modules. - -This library extends the [MFRC522 library](https://github.com/miguelbalboa/rfid) adding extra functionality for MIFARE DESFire cards. - -At the current stage no crypto has been implemented and a very limited subset of commands are available. - -## Requirements ## -- [MFRC522 library](https://github.com/miguelbalboa/rfid) - -### Future requirements ### -This libraries have been planned but need to be implemented and confirmed to be working properlly with DESFire library. - -- [Arduino DES library](https://github.com/spaniakos/ArduinoDES/) (Not yet implemented) -- [Arduino AES library](https://github.com/spaniakos/AES/) (Not yet implemented) - -## Credits ## - -[EasyPay](https://github.com/nceruchalu/easypay) has been an invaluable source of information due to the great documentation in its comments. diff --git a/Software/lib/rfid-desfire/docs/DesFireProgrammingGuide.pdf b/Software/lib/rfid-desfire/docs/DesFireProgrammingGuide.pdf deleted file mode 100644 index 4337967..0000000 Binary files a/Software/lib/rfid-desfire/docs/DesFireProgrammingGuide.pdf and /dev/null differ diff --git a/Software/lib/rfid-desfire/docs/MIFAREDESFireEV1AESAuthenticationWithTRF7970A.pdf b/Software/lib/rfid-desfire/docs/MIFAREDESFireEV1AESAuthenticationWithTRF7970A.pdf deleted file mode 100644 index fcab7be..0000000 Binary files a/Software/lib/rfid-desfire/docs/MIFAREDESFireEV1AESAuthenticationWithTRF7970A.pdf and /dev/null differ diff --git a/Software/lib/rfid-desfire/docs/sloa213.pdf b/Software/lib/rfid-desfire/docs/sloa213.pdf deleted file mode 100644 index fcab7be..0000000 Binary files a/Software/lib/rfid-desfire/docs/sloa213.pdf and /dev/null differ diff --git a/Software/lib/rfid-desfire/examples/DumpInfo.ino b/Software/lib/rfid-desfire/examples/DumpInfo.ino deleted file mode 100644 index 64be0ae..0000000 --- a/Software/lib/rfid-desfire/examples/DumpInfo.ino +++ /dev/null @@ -1,143 +0,0 @@ -/* - * -------------------------------------------------------------------------------------------------------------------- - * Example sketch/program showing how to read data from a PICC to serial. - * -------------------------------------------------------------------------------------------------------------------- - * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid - * - * Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID - * Reader on the Arduino SPI interface. - * - * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE - * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When - * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output - * will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages - * when removing the PICC from reading distance too early. - * - * If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading). - * So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all - * details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so - * keep the PICCs at reading distance until complete. - * - * @license Released into the public domain. - * - * Typical pin layout used: - * ----------------------------------------------------------------------------------------- - * MFRC522 Arduino Arduino Arduino Arduino Arduino - * Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro - * Signal Pin Pin Pin Pin Pin Pin - * ----------------------------------------------------------------------------------------- - * RST/Reset RST 9 5 D9 RESET/ICSP-5 RST - * SPI SS SDA(SS) 10 53 D10 10 10 - * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16 - * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14 - * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15 - */ - -#include -#include -#include - -#define RST_PIN 9 // Configurable, see typical pin layout above -#define SS_PIN 10 // Configurable, see typical pin layout above - -DESFire mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance - -void setup() { - Serial.begin(9600); // Initialize serial communications with the PC - while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4) - SPI.begin(); // Init SPI bus - mfrc522.PCD_Init(); // Init MFRC522 - mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details - Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks...")); -} - -void loop() { - // Look for new cards - if ( ! mfrc522.PICC_IsNewCardPresent()) { - return; - } - - // Select one of the cards - if ( ! mfrc522.PICC_ReadCardSerial()) { - return; - } - - if (mfrc522.uid.sak != 0x20) { - // Dump debug info about the card; PICC_HaltA() is automatically called - mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); - return; - } - - // Show an extra line - Serial.println(); - - DESFire::mifare_desfire_tag tag; - DESFire::StatusCode response; - - tag.pcb = 0x0A; - tag.cid = 0x00; - memset(tag.selected_application, 0, 3); - - // Make sure none DESFire status codes have DESFireStatus code to OK - response.desfire = DESFire::MF_OPERATION_OK; - - byte ats[16]; - byte atsLength = 16; - response.mfrc522 = mfrc522.PICC_RequestATS(ats, &atsLength); - if ( ! mfrc522.IsStatusCodeOK(response)) { - Serial.println(F("Failed to get ATS!")); - Serial.println(mfrc522.GetStatusCodeName(response)); - Serial.println(response.mfrc522); - - mfrc522.PICC_HaltA(); - return; - } - - // TODO: Should do checks but since I know my DESFire allows and requires PPS... - // PPS1 is ommitted and, therefore, 0x00 is used (106kBd) - response.mfrc522 = mfrc522.PICC_ProtocolAndParameterSelection(0x00, 0x11); - if ( ! mfrc522.IsStatusCodeOK(response)) { - Serial.println(F("Failed to perform protocol and parameter selection (PPS)!")); - Serial.println(mfrc522.GetStatusCodeName(response)); - mfrc522.PICC_HaltA(); - return; - } - - // MIFARE DESFire should respond to a GetVersion command - DESFire::MIFARE_DESFIRE_Version_t desfireVersion; - response = mfrc522.MIFARE_DESFIRE_GetVersion(&tag, &desfireVersion); - if ( ! mfrc522.IsStatusCodeOK(response)) { - Serial.println(F("Failed to get a response for GetVersion!")); - Serial.println(mfrc522.GetStatusCodeName(response)); - mfrc522.PICC_HaltA(); - return; - } - - // Dump MIFARE DESFire version information. - // NOTE: KEEP YOUR CARD CLOSE TO THE READER! - // This method takes some time and the card will be read - // once output ends! If you remove the card too fast - // a timeout will occur! - mfrc522.PICC_DumpMifareDesfireVersion(&tag, &desfireVersion); - - mfrc522.PICC_DumpMifareDesfireMasterKey(&tag); - - DESFire::mifare_desfire_aid_t aids[MIFARE_MAX_APPLICATION_COUNT]; - byte applicationCount = 0; - response = mfrc522.MIFARE_DESFIRE_GetApplicationIds(&tag, aids, &applicationCount); - if ( ! mfrc522.IsStatusCodeOK(response)) { - Serial.println(F("Failed to get application IDs!")); - Serial.println(mfrc522.GetStatusCodeName(response)); - mfrc522.PICC_HaltA(); - return; - } - - // Dump all applications - for (byte aidIndex = 0; aidIndex < applicationCount; aidIndex++) { - mfrc522.PICC_DumpMifareDesfireApplication(&tag, &(aids[aidIndex])); - } - - // Call PICC_HaltA() - mfrc522.PICC_HaltA(); - Serial.println(); -} \ No newline at end of file diff --git a/Software/platformio.ini b/Software/platformio.ini index e81c894..53c169c 100644 --- a/Software/platformio.ini +++ b/Software/platformio.ini @@ -21,3 +21,6 @@ lib_deps = uipethernet/UIPEthernet@^2.0.12 bblanchon/ArduinoJson@^6.19.4 mbed-feb11/Crypto@0.0.0+sha.f04410cef037 + adafruit/Adafruit PN532@^1.3.3 +build_flags = + -D PN532_I2C_ADDRESS=0x24 \ No newline at end of file diff --git a/Software/src/NFC.cpp b/Software/src/NFC.cpp index 90747f3..f7ed257 100644 --- a/Software/src/NFC.cpp +++ b/Software/src/NFC.cpp @@ -1,21 +1,48 @@ -#include "nfc.h" +#include "NFC.h" #include #include -#include #include "helpers.h" -NFC::NFC(int pin_ss, int pin_rst) +NFC::NFC(int pin_sda, int pin_scl) { - rfid = new DESFire(pin_ss, pin_rst); + Serial.println("NFC: Start"); - SPI.begin(); - rfid->PCD_Init(); - rfid->PCD_DumpVersionToSerial(); + rfid = new Adafruit_PN532(PN532_IRQ, PN532_RESET); + + rfid->begin(); + + uint32_t versiondata = rfid->getFirmwareVersion(); + if (!versiondata) + { + Serial.print("Didn't find PN53x board"); + while (1) + { + yield(); // halt + } + } + + // Got ok data, print it out! + Serial.print("NFC: Found chip PN5"); + Serial.println((versiondata >> 24) & 0xFF, HEX); + Serial.print("NFC: Firmware ver. "); + Serial.print((versiondata >> 16) & 0xFF, DEC); + Serial.print('.'); + Serial.println((versiondata >> 8) & 0xFF, DEC); } -MFRC522::Uid NFC::getUID() +String NFC::getUID() { - return uid; + String uidStr; + for (int i = 0; i < uidLength; i++) + { + if (uid[i] < 0x10) + { + uidStr += "0"; + } + uidStr += String(uid[i], HEX); + } + + return uidStr; } bool NFC::hasCardSelected() @@ -25,72 +52,129 @@ bool NFC::hasCardSelected() bool NFC::testNFC() { - return rfid->PCD_PerformSelfTest(); + // return rfid->PCD_PerformSelfTest(); } bool NFC::checkforCard() { - // RequestA - if (!rfid->PICC_IsNewCardPresent()) + // Attempt to read a card (timeout in milliseconds, adjust as needed) + if (!rfid->readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000)) { + Serial.println("No card found within the timeout period"); + // No card found within the timeout period return false; } - // PICC_Select ??? - if (!rfid->PICC_ReadCardSerial()) + // At this point, a card has been detected and its UID is in 'uid' with length 'uidLength' + // If you expect a DESFire card, you might assume its UID is 7 bytes. + // (Alternatively, if you extend the library to capture the SAK, you could check that here.) + if (uidLength == 7) { - return false; + Serial.println("DESFire card detected"); + Serial.print("UID: "); + printbytes(uid, uidLength); + + return true; } - // Check for DESFire - if (rfid->uid.sak != 0x20) + // If we're getting 4 bytes, we might be scanning a MIFARE Classic or another ISO14443A card. + if (uidLength == 4) { - return false; + Serial.println("MIFARE Classic or another ISO14443A card detected"); + Serial.print("UID: "); + printbytes(uid, uidLength); + + return true; } - return true; + // The card detected does not match the expected DESFireor MIFARE Classic UID length + Serial.println("No card detected"); + + return false; } bool NFC::connecttoCard() { - // RATS - byte ats[16]; - byte atsLength = 16; - MFRC522::StatusCode state = rfid->PICC_RequestATS(ats, &atsLength); - if (state != MFRC522::STATUS_OK) + // --- RATS (Request for ATS) --- + // RATS command format: [0xE0, param] + // The parameter byte encodes the Frame Size and other options. + // Here we use 0x80 as an example parameter (adjust as needed for your card). + uint8_t ratsCmd[] = {0xE0, 0x80}; + uint8_t atsResponse[16]; // Buffer to hold the ATS response + uint8_t atsResponseLength = sizeof(atsResponse); + + // Send the RATS command via inDataExchange. + // inDataExchange() returns a negative value on error. + int result = rfid->inDataExchange(ratsCmd, sizeof(ratsCmd), atsResponse, &atsResponseLength); + if (result < 0) { Serial.println(F("Failed ATS")); - Serial.println(state); - rfid->PICC_HaltA(); + // PN532 does not offer a dedicated halt command, + // so you may simply return false to abort communication. return false; } - // PPS - state = rfid->PICC_ProtocolAndParameterSelection(0x00, 0x11, 0x00); - if (state != MFRC522::STATUS_OK) + // (Optional) Process the ATS response here if needed. + // The ATS provides card-specific information, such as supported protocols and frame sizes. + + // --- PPS (Protocol and Parameter Selection) --- + // PPS command format (example): [0xD0, PPS0, PPS1] + // In this example, PPS0 is set to 0x11 and PPS1 to 0x00. + // Adjust the values according to your protocol requirements. + uint8_t ppsCmd[] = {0xD0, 0x11, 0x00}; + uint8_t ppsResponse[16]; + uint8_t ppsResponseLength = sizeof(ppsResponse); + + result = rfid->inDataExchange(ppsCmd, sizeof(ppsCmd), ppsResponse, &ppsResponseLength); + if (result < 0) { - Serial.println("Failed PPS"); - Serial.println(state); - rfid->PICC_HaltA(); + Serial.println(F("Failed PPS")); return false; } + // If both exchanges were successful, mark the card as selected. cardSelected = true; - uid = rfid->uid; + + // Save any card-specific data if needed here. + // Note: Unlike MFRC522, Adafruit_PN532 does not store the UID in a public member. + // We save the UID when we detect the card. pcb = 0x0A; return true; } bool NFC::disconnectCard() { - MFRC522::StatusCode state = rfid->PICC_HaltA(); - if (state != MFRC522::STATUS_OK) + // ISO14443A HALT command: 0x50, 0x00, followed by the two-byte CRC. + // You can either compute the CRC or, if your setup automatically appends it, + // simply send the command without CRC bytes. + // Here, we assume you have to include the CRC. + // Note: The correct CRC for [0x50, 0x00] is usually 0x00, 0x00 if the PN532 + // is set to auto-calculate CRC, or you can compute it if needed. + + // Option 1: If your PN532 is configured to append the CRC automatically, + // you can send just the two-byte command. + uint8_t haltCmd[] = {0x50, 0x00}; + uint8_t response[8]; + uint8_t responseLength = sizeof(response); + + int status = rfid->inDataExchange(haltCmd, sizeof(haltCmd), response, &responseLength); + if (status < 0) { - Serial.println(F("Failed PICC_HaltA")); - Serial.println(state); + Serial.println(F("Failed to send HALT command")); + Serial.println(status); return false; } + // Option 2: If you need to send a complete command with CRC, you must + // calculate the CRC bytes for [0x50, 0x00]. For many ISO14443A cards, the CRC + // may be 0x00, 0x00 when using a PN532 in auto-CRC mode, so this might work: + // + // uint8_t haltCmd[] = { 0x50, 0x00, 0x00, 0x00 }; + // int status = rfid->inDataExchange(haltCmd, sizeof(haltCmd), response, &responseLength); + // if (status < 0) { ... } + // + // Uncomment the above block and comment out the Option 1 block if needed. + return true; } @@ -98,48 +182,3 @@ bool NFC::testCard() { return true; } - -MFRC522::StatusCode NFC::Transceive(byte *command, byte command_len, byte *response, byte *response_len) -{ - if (command_len >= 0xFF - 4) - { - return MFRC522::STATUS_NO_ROOM; - } - - MFRC522::StatusCode state; - byte request_buffer[APDU_BUFFER_SIZE + 4]; // APDU Size + PCB + CID + 2x CRC - byte request_buffer_size = command_len + 4; - - request_buffer[0] = pcb; - request_buffer[1] = cid; - - memcpy(&request_buffer[2], command, command_len); - - // Update the PCB - if (pcb == 0x0A) - pcb = 0x0B; - else - pcb = 0x0A; - - // Calculate CRC_A - state = rfid->PCD_CalculateCRC(request_buffer, request_buffer_size - 2, &request_buffer[request_buffer_size - 2]); - if (state != MFRC522::STATUS_OK) - { - return state; - } - - byte response_buffer[APDU_BUFFER_SIZE + 4] = {0}; // APDU Size + PCB + CID + 2x CRC - byte response_buffer_size = 0xFF; - - printbytes(request_buffer, request_buffer_size); - state = rfid->PCD_TransceiveData(request_buffer, request_buffer_size, response_buffer, &response_buffer_size); - if (state != MFRC522::STATUS_OK) - { - return state; - } - - memcpy(response, response_buffer + 2, response_buffer_size - 4); - *response_len = response_buffer_size - 4; - - return state; -} \ No newline at end of file diff --git a/Software/src/NFC.h b/Software/src/NFC.h index 31b2183..899083d 100644 --- a/Software/src/NFC.h +++ b/Software/src/NFC.h @@ -2,29 +2,31 @@ #define NFC_H #include -#include +#include +#include +#include + #define APDU_BUFFER_SIZE 256 class NFC { private: - MFRC522::Uid uid; + uint8_t uid[7]; // Buffer to hold the card's UID (PN532 supports up to 7 bytes for ISO14443A) + uint8_t uidLength; // Length of the UID (will be set by readPassiveTargetID) byte pcb = 0x0A; byte cid = 0x00; bool cardSelected = false; public: - DESFire *rfid; - NFC(int pin_ss, int pin_rst); + Adafruit_PN532 *rfid; + NFC(int pin_sda, int pin_scl); bool testNFC(); bool checkforCard(); bool connecttoCard(); bool disconnectCard(); bool testCard(); bool hasCardSelected(); - MFRC522::Uid getUID(); - - MFRC522::StatusCode Transceive(byte *command, byte command_len, byte *response, byte *response_len); + String getUID(); }; #endif diff --git a/Software/src/OTAProxy.cpp b/Software/src/OTAProxy.cpp index 88cfc7f..d0573d4 100644 --- a/Software/src/OTAProxy.cpp +++ b/Software/src/OTAProxy.cpp @@ -1,5 +1,5 @@ -#include "otaproxy.h" -#include "nfc.h" +#include "OTAProxy.h" +#include "NFC.h" #include OTAProxy::OTAProxy(PubSubClient *mqttClient, NFC *nfc, int id) @@ -24,39 +24,45 @@ void OTAProxy::startOTA() char topic[] = "fabreader/00000/startOTA"; sprintf(topic, "fabreader/%05d/startOTA", id); - MFRC522::Uid uid = nfc->getUID(); - mqtt->publish(topic, uid.uidByte, uid.size); + + String uid = nfc->getUID(); + mqtt->publish(topic, uid.c_str(), uid.length()); Serial.println("Start OTA"); } void OTAProxy::continueOTA(char *topic, byte *payload, unsigned int length) { - char topic_requestOTA[] = "fabreader/00000/requestOTA"; + // Create topic strings with sufficient buffer sizes + char topic_requestOTA[32]; sprintf(topic_requestOTA, "fabreader/%05d/requestOTA", id); - char topic_responseOTA[] = "fabreader/00000/responseOTA"; + char topic_responseOTA[32]; sprintf(topic_responseOTA, "fabreader/%05d/responseOTA", id); - char topic_stopOTA[] = "fabreader/00000/stopOTA"; + char topic_stopOTA[32]; sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", id); - char topic_restartOTA[] = "fabreader/00000/restartOTA"; + char topic_restartOTA[32]; sprintf(topic_restartOTA, "fabreader/%05d/restartOTA", id); if (!strcmp(topic, topic_requestOTA)) { Serial.println("Request OTA"); - byte response[APDU_BUFFER_SIZE] = {0}; - byte response_len; - MFRC522::StatusCode status; + byte response[APDU_BUFFER_SIZE] = {0}; + + // Maximum value for a uint8_t is 255. + uint8_t response_len = 255; // Use 255 even if APDU_BUFFER_SIZE is 256 + + // Cast length (unsigned int) to uint8_t, assuming it fits within 255 bytes. + uint8_t sendLength = (uint8_t)length; Serial.println("Run Transceive"); - status = nfc->Transceive(payload, length, response, &response_len); - Serial.printf("PICC_Tranceive: 0x%02x\n", status); + int status = nfc->rfid->inDataExchange(payload, sendLength, response, &response_len); + Serial.printf("PICC_Transceive: 0x%02x\n", status); - if (status != MFRC522::STATUS_OK) + if (status < 0) { cancelOTA(); return; @@ -71,14 +77,11 @@ void OTAProxy::continueOTA(char *topic, byte *payload, unsigned int length) nfc->disconnectCard(); activeOTA = false; } - // else if(!strcmp(topic, topic_restartOTA)) + // else if (!strcmp(topic, topic_restartOTA)) // { // Serial.println("Restart OTA"); - // while(!(nfc->deselectCard())); - // // if(nfc->hasNewCard()) - // // { - // // startOTA(); - // // } + // // Add your PN532-specific card deselection logic here if needed. + // // For example, you might send a halt command or wait until the card is removed. // } } @@ -86,11 +89,14 @@ void OTAProxy::cancelOTA() { char topic_cancelOTA[] = "fabreader/00000/cancelOTA"; sprintf(topic_cancelOTA, "fabreader/%05d/cancelOTA", id); - MFRC522::Uid uid = nfc->getUID(); - mqtt->publish(topic_cancelOTA, uid.uidByte, uid.size); + + String uid = nfc->getUID(); + mqtt->publish(topic_cancelOTA, uid.c_str(), uid.length()); while (!(nfc->disconnectCard())) - ; + { + yield(); + } activeOTA = false; Serial.println("Cancel OTA"); diff --git a/Software/src/OTAProxy.h b/Software/src/OTAProxy.h index 0095d05..90b7d65 100644 --- a/Software/src/OTAProxy.h +++ b/Software/src/OTAProxy.h @@ -2,7 +2,7 @@ #define OTAProxy_H #include -#include "nfc.h" +#include "NFC.h" #define MSG_BUFFER_SIZE 50 class OTAProxy diff --git a/Software/src/Pins.h b/Software/src/Pins.h index 958c6f8..dc23ff4 100644 --- a/Software/src/Pins.h +++ b/Software/src/Pins.h @@ -1,18 +1,12 @@ #ifndef PINS_H #define PINS_H -// Pins for ESP8266 -#define PIN_SDA 4 -#define PIN_SCL 5 +#define PN532_IRQ 4 +#define PN532_RESET 5 -#define PIN_SPI_MOSI 13 -#define PIN_SPI_MISO 12 -#define PIN_SPI_SCK 14 +#define PIN_SDA 16 +#define PIN_SCL 17 -#define PIN_RFID_RST 0 -#define PIN_RFID_SPI_SS 2 -#define PIN_ETH_SPI_SS 15 +#define PIN_BUZZER 2 -#define PIN_BUZZER 16 -#define PIN_BUTTON A0 #endif \ No newline at end of file diff --git a/Software/src/main.cpp b/Software/src/main.cpp index 0215614..8f77a39 100644 --- a/Software/src/main.cpp +++ b/Software/src/main.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -14,10 +13,8 @@ #include #include -#include WiFiClient espClient; -// Config_Data config; PubSubClient *mqtt; NFC *nfc; @@ -115,20 +112,15 @@ void setup() Serial.println("Booting ..."); pinMode(PIN_BUZZER, OUTPUT); - pinMode(PIN_BUTTON, INPUT); - pinMode(PIN_ETH_SPI_SS, OUTPUT); - digitalWrite(PIN_ETH_SPI_SS, HIGH); display = new Display(PIN_SDA, PIN_SCL, FABREADERID); display->clearReaderInfo(); display->writeInfo("Start NFC ..."); Serial.println("Connecting NFC ..."); - nfc = new NFC(PIN_RFID_SPI_SS, PIN_RFID_RST); - if (!(nfc->rfid->PCD_PerformSelfTest())) - { - Serial.println("NFC Test failed"); - } + + nfc = new NFC(PIN_SDA, PIN_SCL); + Serial.println("NFC connected"); display->writeInfo("Start WIFI ...");