mirror of
https://gitlab.com/fabinfra/fabhardware/fabreader3.git
synced 2025-03-12 22:51:42 +01:00
Adapt to new PN532 hardware + some cleanup
This commit is contained in:
parent
eb1d124040
commit
a8596314ff
@ -1,971 +0,0 @@
|
|||||||
#include <Desfire.h>
|
|
||||||
|
|
||||||
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("-------------------------------------------------------------"));
|
|
||||||
}
|
|
@ -1,187 +0,0 @@
|
|||||||
#ifndef DESFIRE_h
|
|
||||||
#define DESFIRE_h
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <MFRC522.h>
|
|
||||||
|
|
||||||
/* --------------------------------------
|
|
||||||
* 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
|
|
@ -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.
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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 <SPI.h>
|
|
||||||
#include <MFRC522.h>
|
|
||||||
#include <Desfire.h>
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
@ -21,3 +21,6 @@ lib_deps =
|
|||||||
uipethernet/UIPEthernet@^2.0.12
|
uipethernet/UIPEthernet@^2.0.12
|
||||||
bblanchon/ArduinoJson@^6.19.4
|
bblanchon/ArduinoJson@^6.19.4
|
||||||
mbed-feb11/Crypto@0.0.0+sha.f04410cef037
|
mbed-feb11/Crypto@0.0.0+sha.f04410cef037
|
||||||
|
adafruit/Adafruit PN532@^1.3.3
|
||||||
|
build_flags =
|
||||||
|
-D PN532_I2C_ADDRESS=0x24
|
@ -1,21 +1,48 @@
|
|||||||
#include "nfc.h"
|
#include "NFC.h"
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <DESFire.h>
|
|
||||||
#include "helpers.h"
|
#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 = new Adafruit_PN532(PN532_IRQ, PN532_RESET);
|
||||||
rfid->PCD_Init();
|
|
||||||
rfid->PCD_DumpVersionToSerial();
|
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()
|
bool NFC::hasCardSelected()
|
||||||
@ -25,72 +52,129 @@ bool NFC::hasCardSelected()
|
|||||||
|
|
||||||
bool NFC::testNFC()
|
bool NFC::testNFC()
|
||||||
{
|
{
|
||||||
return rfid->PCD_PerformSelfTest();
|
// return rfid->PCD_PerformSelfTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NFC::checkforCard()
|
bool NFC::checkforCard()
|
||||||
{
|
{
|
||||||
// RequestA
|
// Attempt to read a card (timeout in milliseconds, adjust as needed)
|
||||||
if (!rfid->PICC_IsNewCardPresent())
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PICC_Select ???
|
// At this point, a card has been detected and its UID is in 'uid' with length 'uidLength'
|
||||||
if (!rfid->PICC_ReadCardSerial())
|
// 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 we're getting 4 bytes, we might be scanning a MIFARE Classic or another ISO14443A card.
|
||||||
if (rfid->uid.sak != 0x20)
|
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()
|
bool NFC::connecttoCard()
|
||||||
{
|
{
|
||||||
// RATS
|
// --- RATS (Request for ATS) ---
|
||||||
byte ats[16];
|
// RATS command format: [0xE0, param]
|
||||||
byte atsLength = 16;
|
// The parameter byte encodes the Frame Size and other options.
|
||||||
MFRC522::StatusCode state = rfid->PICC_RequestATS(ats, &atsLength);
|
// Here we use 0x80 as an example parameter (adjust as needed for your card).
|
||||||
if (state != MFRC522::STATUS_OK)
|
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(F("Failed ATS"));
|
||||||
Serial.println(state);
|
// PN532 does not offer a dedicated halt command,
|
||||||
rfid->PICC_HaltA();
|
// so you may simply return false to abort communication.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PPS
|
// (Optional) Process the ATS response here if needed.
|
||||||
state = rfid->PICC_ProtocolAndParameterSelection(0x00, 0x11, 0x00);
|
// The ATS provides card-specific information, such as supported protocols and frame sizes.
|
||||||
if (state != MFRC522::STATUS_OK)
|
|
||||||
|
// --- 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(F("Failed PPS"));
|
||||||
Serial.println(state);
|
|
||||||
rfid->PICC_HaltA();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If both exchanges were successful, mark the card as selected.
|
||||||
cardSelected = true;
|
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;
|
pcb = 0x0A;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NFC::disconnectCard()
|
bool NFC::disconnectCard()
|
||||||
{
|
{
|
||||||
MFRC522::StatusCode state = rfid->PICC_HaltA();
|
// ISO14443A HALT command: 0x50, 0x00, followed by the two-byte CRC.
|
||||||
if (state != MFRC522::STATUS_OK)
|
// 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(F("Failed to send HALT command"));
|
||||||
Serial.println(state);
|
Serial.println(status);
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,48 +182,3 @@ bool NFC::testCard()
|
|||||||
{
|
{
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
@ -2,29 +2,31 @@
|
|||||||
#define NFC_H
|
#define NFC_H
|
||||||
|
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <Desfire.h>
|
#include <Pins.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_PN532.h>
|
||||||
|
|
||||||
#define APDU_BUFFER_SIZE 256
|
#define APDU_BUFFER_SIZE 256
|
||||||
|
|
||||||
class NFC
|
class NFC
|
||||||
{
|
{
|
||||||
private:
|
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 pcb = 0x0A;
|
||||||
byte cid = 0x00;
|
byte cid = 0x00;
|
||||||
bool cardSelected = false;
|
bool cardSelected = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DESFire *rfid;
|
Adafruit_PN532 *rfid;
|
||||||
NFC(int pin_ss, int pin_rst);
|
NFC(int pin_sda, int pin_scl);
|
||||||
bool testNFC();
|
bool testNFC();
|
||||||
bool checkforCard();
|
bool checkforCard();
|
||||||
bool connecttoCard();
|
bool connecttoCard();
|
||||||
bool disconnectCard();
|
bool disconnectCard();
|
||||||
bool testCard();
|
bool testCard();
|
||||||
bool hasCardSelected();
|
bool hasCardSelected();
|
||||||
MFRC522::Uid getUID();
|
String getUID();
|
||||||
|
|
||||||
MFRC522::StatusCode Transceive(byte *command, byte command_len, byte *response, byte *response_len);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "otaproxy.h"
|
#include "OTAProxy.h"
|
||||||
#include "nfc.h"
|
#include "NFC.h"
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
OTAProxy::OTAProxy(PubSubClient *mqttClient, NFC *nfc, int id)
|
OTAProxy::OTAProxy(PubSubClient *mqttClient, NFC *nfc, int id)
|
||||||
@ -24,39 +24,45 @@ void OTAProxy::startOTA()
|
|||||||
|
|
||||||
char topic[] = "fabreader/00000/startOTA";
|
char topic[] = "fabreader/00000/startOTA";
|
||||||
sprintf(topic, "fabreader/%05d/startOTA", id);
|
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");
|
Serial.println("Start OTA");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OTAProxy::continueOTA(char *topic, byte *payload, unsigned int length)
|
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);
|
sprintf(topic_requestOTA, "fabreader/%05d/requestOTA", id);
|
||||||
|
|
||||||
char topic_responseOTA[] = "fabreader/00000/responseOTA";
|
char topic_responseOTA[32];
|
||||||
sprintf(topic_responseOTA, "fabreader/%05d/responseOTA", id);
|
sprintf(topic_responseOTA, "fabreader/%05d/responseOTA", id);
|
||||||
|
|
||||||
char topic_stopOTA[] = "fabreader/00000/stopOTA";
|
char topic_stopOTA[32];
|
||||||
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", id);
|
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", id);
|
||||||
|
|
||||||
char topic_restartOTA[] = "fabreader/00000/restartOTA";
|
char topic_restartOTA[32];
|
||||||
sprintf(topic_restartOTA, "fabreader/%05d/restartOTA", id);
|
sprintf(topic_restartOTA, "fabreader/%05d/restartOTA", id);
|
||||||
|
|
||||||
if (!strcmp(topic, topic_requestOTA))
|
if (!strcmp(topic, topic_requestOTA))
|
||||||
{
|
{
|
||||||
Serial.println("Request OTA");
|
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");
|
Serial.println("Run Transceive");
|
||||||
status = nfc->Transceive(payload, length, response, &response_len);
|
int status = nfc->rfid->inDataExchange(payload, sendLength, response, &response_len);
|
||||||
Serial.printf("PICC_Tranceive: 0x%02x\n", status);
|
Serial.printf("PICC_Transceive: 0x%02x\n", status);
|
||||||
|
|
||||||
if (status != MFRC522::STATUS_OK)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
cancelOTA();
|
cancelOTA();
|
||||||
return;
|
return;
|
||||||
@ -71,14 +77,11 @@ void OTAProxy::continueOTA(char *topic, byte *payload, unsigned int length)
|
|||||||
nfc->disconnectCard();
|
nfc->disconnectCard();
|
||||||
activeOTA = false;
|
activeOTA = false;
|
||||||
}
|
}
|
||||||
// else if(!strcmp(topic, topic_restartOTA))
|
// else if (!strcmp(topic, topic_restartOTA))
|
||||||
// {
|
// {
|
||||||
// Serial.println("Restart OTA");
|
// Serial.println("Restart OTA");
|
||||||
// while(!(nfc->deselectCard()));
|
// // Add your PN532-specific card deselection logic here if needed.
|
||||||
// // if(nfc->hasNewCard())
|
// // For example, you might send a halt command or wait until the card is removed.
|
||||||
// // {
|
|
||||||
// // startOTA();
|
|
||||||
// // }
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,11 +89,14 @@ void OTAProxy::cancelOTA()
|
|||||||
{
|
{
|
||||||
char topic_cancelOTA[] = "fabreader/00000/cancelOTA";
|
char topic_cancelOTA[] = "fabreader/00000/cancelOTA";
|
||||||
sprintf(topic_cancelOTA, "fabreader/%05d/cancelOTA", id);
|
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()))
|
while (!(nfc->disconnectCard()))
|
||||||
;
|
{
|
||||||
|
yield();
|
||||||
|
}
|
||||||
activeOTA = false;
|
activeOTA = false;
|
||||||
|
|
||||||
Serial.println("Cancel OTA");
|
Serial.println("Cancel OTA");
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define OTAProxy_H
|
#define OTAProxy_H
|
||||||
|
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include "nfc.h"
|
#include "NFC.h"
|
||||||
#define MSG_BUFFER_SIZE 50
|
#define MSG_BUFFER_SIZE 50
|
||||||
|
|
||||||
class OTAProxy
|
class OTAProxy
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
#ifndef PINS_H
|
#ifndef PINS_H
|
||||||
#define PINS_H
|
#define PINS_H
|
||||||
|
|
||||||
// Pins for ESP8266
|
#define PN532_IRQ 4
|
||||||
#define PIN_SDA 4
|
#define PN532_RESET 5
|
||||||
#define PIN_SCL 5
|
|
||||||
|
|
||||||
#define PIN_SPI_MOSI 13
|
#define PIN_SDA 16
|
||||||
#define PIN_SPI_MISO 12
|
#define PIN_SCL 17
|
||||||
#define PIN_SPI_SCK 14
|
|
||||||
|
|
||||||
#define PIN_RFID_RST 0
|
#define PIN_BUZZER 2
|
||||||
#define PIN_RFID_SPI_SS 2
|
|
||||||
#define PIN_ETH_SPI_SS 15
|
|
||||||
|
|
||||||
#define PIN_BUZZER 16
|
|
||||||
#define PIN_BUTTON A0
|
|
||||||
#endif
|
#endif
|
@ -6,7 +6,6 @@
|
|||||||
#include <NFC.h>
|
#include <NFC.h>
|
||||||
#include <OTAProxy.h>
|
#include <OTAProxy.h>
|
||||||
#include <helpers.h>
|
#include <helpers.h>
|
||||||
#include <Desfire.h>
|
|
||||||
#include <Display.h>
|
#include <Display.h>
|
||||||
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
@ -14,10 +13,8 @@
|
|||||||
|
|
||||||
#include <WiFiClient.h>
|
#include <WiFiClient.h>
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
WiFiClient espClient;
|
WiFiClient espClient;
|
||||||
// Config_Data config;
|
|
||||||
|
|
||||||
PubSubClient *mqtt;
|
PubSubClient *mqtt;
|
||||||
NFC *nfc;
|
NFC *nfc;
|
||||||
@ -115,20 +112,15 @@ void setup()
|
|||||||
Serial.println("Booting ...");
|
Serial.println("Booting ...");
|
||||||
|
|
||||||
pinMode(PIN_BUZZER, OUTPUT);
|
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 = new Display(PIN_SDA, PIN_SCL, FABREADERID);
|
||||||
display->clearReaderInfo();
|
display->clearReaderInfo();
|
||||||
|
|
||||||
display->writeInfo("Start NFC ...");
|
display->writeInfo("Start NFC ...");
|
||||||
Serial.println("Connecting NFC ...");
|
Serial.println("Connecting NFC ...");
|
||||||
nfc = new NFC(PIN_RFID_SPI_SS, PIN_RFID_RST);
|
|
||||||
if (!(nfc->rfid->PCD_PerformSelfTest()))
|
nfc = new NFC(PIN_SDA, PIN_SCL);
|
||||||
{
|
|
||||||
Serial.println("NFC Test failed");
|
|
||||||
}
|
|
||||||
Serial.println("NFC connected");
|
Serial.println("NFC connected");
|
||||||
|
|
||||||
display->writeInfo("Start WIFI ...");
|
display->writeInfo("Start WIFI ...");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user