refactor class
move new rats functions to extra class
This commit is contained in:
888
MFRC522.cpp
888
MFRC522.cpp
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <MFRC522.h>
|
#include "MFRC522.h"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Functions for setting up the Arduino
|
// Functions for setting up the Arduino
|
||||||
@@ -791,102 +791,6 @@ MFRC522::StatusCode MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct
|
|||||||
// Set correct uid->size
|
// Set correct uid->size
|
||||||
uid->size = 3 * cascadeLevel + 1;
|
uid->size = 3 * cascadeLevel + 1;
|
||||||
|
|
||||||
// IF SAK bit 6 = 1 then it is ISO/IEC 14443-4 (T=CL)
|
|
||||||
// A Request ATS command should be sent
|
|
||||||
// We also check SAK bit 3 is cero, as it stands for UID complete (1 would tell us it is incomplete)
|
|
||||||
if ((uid->sak & 0x24) == 0x20) {
|
|
||||||
Ats ats;
|
|
||||||
result = PICC_RequestATS(&ats);
|
|
||||||
if (result == STATUS_OK) {
|
|
||||||
// Check the ATS
|
|
||||||
if (ats.size > 0)
|
|
||||||
{
|
|
||||||
// TA1 has been transmitted?
|
|
||||||
// PPS must be supported...
|
|
||||||
if (ats.ta1.transmitted)
|
|
||||||
{
|
|
||||||
// TA1
|
|
||||||
// 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | Description
|
|
||||||
// ---+---+---+---+---+---+---+---+------------------------------------------
|
|
||||||
// 0 | - | - | - | 0 | - | - | - | Different D for each direction supported
|
|
||||||
// 1 | - | - | - | 0 | - | - | - | Only same D for both direction supported
|
|
||||||
// - | x | x | x | 0 | - | - | - | DS (Send D)
|
|
||||||
// - | - | - | - | 0 | x | x | x | DR (Receive D)
|
|
||||||
//
|
|
||||||
// D to bitrate table
|
|
||||||
// 3 | 2 | 1 | Value
|
|
||||||
// ---+---+---+-----------------------------
|
|
||||||
// 1 | - | - | 848 kBaud is supported
|
|
||||||
// - | 1 | - | 424 kBaud is supported
|
|
||||||
// - | - | 1 | 212 kBaud is supported
|
|
||||||
// 0 | 0 | 0 | Only 106 kBaud is supported
|
|
||||||
//
|
|
||||||
// Note: 106 kBaud is always supported
|
|
||||||
//
|
|
||||||
// I have almost constant timeouts when changing speeds :(
|
|
||||||
TagBitRates ds = BITRATE_106KBITS;
|
|
||||||
TagBitRates dr = BITRATE_106KBITS;
|
|
||||||
|
|
||||||
//// Not working at 848 or 424
|
|
||||||
//if (ats.ta1.ds & 0x04)
|
|
||||||
//{
|
|
||||||
// ds = BITRATE_848KBITS;
|
|
||||||
//}
|
|
||||||
//else if (ats.ta1.ds & 0x02)
|
|
||||||
//{
|
|
||||||
// ds = BITRATE_424KBITS;
|
|
||||||
//}
|
|
||||||
//else if (ats.ta1.ds & 0x01)
|
|
||||||
//{
|
|
||||||
// ds = BITRATE_212KBITS;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// ds = BITRATE_106KBITS;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ats.ta1.ds & 0x01)
|
|
||||||
{
|
|
||||||
ds = BITRATE_212KBITS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ds = BITRATE_106KBITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//// Not working at 848 or 424
|
|
||||||
//if (ats.ta1.dr & 0x04)
|
|
||||||
//{
|
|
||||||
// dr = BITRATE_848KBITS;
|
|
||||||
//}
|
|
||||||
//else if (ats.ta1.dr & 0x02)
|
|
||||||
//{
|
|
||||||
// dr = BITRATE_424KBITS;
|
|
||||||
//}
|
|
||||||
//else if (ats.ta1.dr & 0x01)
|
|
||||||
//{
|
|
||||||
// dr = BITRATE_212KBITS;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// dr = BITRATE_106KBITS;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ats.ta1.dr & 0x01)
|
|
||||||
{
|
|
||||||
dr = BITRATE_212KBITS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dr = BITRATE_106KBITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICC_PPS(ds, dr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
} // End PICC_Select()
|
} // End PICC_Select()
|
||||||
|
|
||||||
@@ -923,615 +827,6 @@ MFRC522::StatusCode MFRC522::PICC_HaltA() {
|
|||||||
return result;
|
return result;
|
||||||
} // End PICC_HaltA()
|
} // End PICC_HaltA()
|
||||||
|
|
||||||
/**
|
|
||||||
* Transmits a Request command for Answer To Select (ATS).
|
|
||||||
*
|
|
||||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
|
||||||
*/
|
|
||||||
MFRC522::StatusCode MFRC522::PICC_RequestATS(Ats *ats)
|
|
||||||
{
|
|
||||||
byte count;
|
|
||||||
MFRC522::StatusCode result;
|
|
||||||
|
|
||||||
byte bufferATS[FIFO_SIZE];
|
|
||||||
byte bufferSize = FIFO_SIZE;
|
|
||||||
|
|
||||||
memset(bufferATS, 0, FIFO_SIZE);
|
|
||||||
|
|
||||||
// Build command buffer
|
|
||||||
bufferATS[0] = PICC_CMD_RATS;
|
|
||||||
|
|
||||||
// The CID defines the logical number of the addressed card and has a range of 0
|
|
||||||
// through 14; 15 is reserved for future use (RFU).
|
|
||||||
//
|
|
||||||
// FSDI codes the maximum frame size (FSD) that the terminal can receive.
|
|
||||||
//
|
|
||||||
// FSDI | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9-F
|
|
||||||
// ------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------
|
|
||||||
// FSD (bytes) | 16 | 24 | 32 | 40 | 48 | 64 | 96 | 128 | 256 | RFU > 256
|
|
||||||
//
|
|
||||||
bufferATS[1] = 0x50; // FSD=64, CID=0
|
|
||||||
|
|
||||||
// Calculate CRC_A
|
|
||||||
result = PCD_CalculateCRC(bufferATS, 2, &bufferATS[2]);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transmit the buffer and receive the response, validate CRC_A.
|
|
||||||
result = PCD_TransceiveData(bufferATS, 4, bufferATS, &bufferSize, NULL, 0, true);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
PICC_HaltA();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the ats structure data
|
|
||||||
ats->size = bufferATS[0];
|
|
||||||
|
|
||||||
// T0 byte:
|
|
||||||
//
|
|
||||||
// b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Meaning
|
|
||||||
//----+----+----+----+----+----+----+----+---------------------------
|
|
||||||
// 0 | ...| ...| ...| ...|... | ...| ...| Set to 0 (RFU)
|
|
||||||
// 0 | 1 | x | x | ...|... | ...| ...| TC1 transmitted
|
|
||||||
// 0 | x | 1 | x | ...|... | ...| ...| TB1 transmitted
|
|
||||||
// 0 | x | x | 1 | ...|... | ...| ...| TA1 transmitted
|
|
||||||
// 0 | ...| ...| ...| x | x | x | x | Maximum frame size (FSCI)
|
|
||||||
//
|
|
||||||
// FSCI | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9-F
|
|
||||||
// ------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------
|
|
||||||
// FSC (bytes) | 16 | 24 | 32 | 40 | 48 | 64 | 96 | 128 | 256 | RFU > 256
|
|
||||||
//
|
|
||||||
// Default FSCI is 2 (32 bytes)
|
|
||||||
if (ats->size > 0x01)
|
|
||||||
{
|
|
||||||
// TC1, TB1 and TA1 where NOT transmitted
|
|
||||||
ats->ta1.transmitted = (bool)(bufferATS[1] & 0x40);
|
|
||||||
ats->tb1.transmitted = (bool)(bufferATS[1] & 0x20);
|
|
||||||
ats->tc1.transmitted = (bool)(bufferATS[1] & 0x10);
|
|
||||||
|
|
||||||
// Decode FSCI
|
|
||||||
switch (bufferATS[1] & 0x0F)
|
|
||||||
{
|
|
||||||
case 0x00:
|
|
||||||
ats->fsc = 16;
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
ats->fsc = 24;
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
ats->fsc = 32;
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
ats->fsc = 40;
|
|
||||||
break;
|
|
||||||
case 0x04:
|
|
||||||
ats->fsc = 48;
|
|
||||||
break;
|
|
||||||
case 0x05:
|
|
||||||
ats->fsc = 64;
|
|
||||||
break;
|
|
||||||
case 0x06:
|
|
||||||
ats->fsc = 96;
|
|
||||||
break;
|
|
||||||
case 0x07:
|
|
||||||
ats->fsc = 128;
|
|
||||||
break;
|
|
||||||
case 0x08:
|
|
||||||
// This value cannot be hold by a byte
|
|
||||||
// The reason I ignore it is that MFRC255 FIFO is 64 bytes so this is not a possible value (or atleast it shouldn't)
|
|
||||||
//ats->fsc = 256;
|
|
||||||
break;
|
|
||||||
// TODO: What to do with RFU (Reserved for future use)?
|
|
||||||
}
|
|
||||||
|
|
||||||
// TA1
|
|
||||||
if (ats->ta1.transmitted)
|
|
||||||
{
|
|
||||||
ats->ta1.sameD = (bool)(bufferATS[2] & 0x80);
|
|
||||||
ats->ta1.ds = (TagBitRates)((bufferATS[2] & 0x70) >> 4);
|
|
||||||
ats->ta1.dr = (TagBitRates)(bufferATS[2] & 0x07);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Default TA1
|
|
||||||
ats->ta1.ds = BITRATE_106KBITS;
|
|
||||||
ats->ta1.dr = BITRATE_106KBITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TB1
|
|
||||||
if (ats->tb1.transmitted)
|
|
||||||
{
|
|
||||||
uint8_t tb1Index = 2;
|
|
||||||
|
|
||||||
if (ats->ta1.transmitted)
|
|
||||||
tb1Index++;
|
|
||||||
|
|
||||||
ats->tb1.fwi = (bufferATS[tb1Index] & 0xF0) >> 4;
|
|
||||||
ats->tb1.sfgi = bufferATS[tb1Index] & 0x0F;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Defaults for TB1
|
|
||||||
ats->tb1.fwi = 0; // TODO: Don't know the default for this!
|
|
||||||
ats->tb1.sfgi = 0; // The default value of SFGI is 0 (meaning that the card does not need any particular SFGT)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TC1
|
|
||||||
if (ats->tc1.transmitted)
|
|
||||||
{
|
|
||||||
uint8_t tc1Index = 2;
|
|
||||||
|
|
||||||
if (ats->ta1.transmitted)
|
|
||||||
tc1Index++;
|
|
||||||
if (ats->tb1.transmitted)
|
|
||||||
tc1Index++;
|
|
||||||
|
|
||||||
ats->tc1.supportsCID = (bool)(bufferATS[tc1Index] & 0x02);
|
|
||||||
ats->tc1.supportsNAD = (bool)(bufferATS[tc1Index] & 0x01);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Defaults for TC1
|
|
||||||
ats->tc1.supportsCID = true;
|
|
||||||
ats->tc1.supportsNAD = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TC1, TB1 and TA1 where NOT transmitted
|
|
||||||
ats->ta1.transmitted = false;
|
|
||||||
ats->tb1.transmitted = false;
|
|
||||||
ats->tc1.transmitted = false;
|
|
||||||
|
|
||||||
// Default FSCI
|
|
||||||
ats->fsc = 32; // Defaults to FSCI 2 (32 bytes)
|
|
||||||
|
|
||||||
// Default TA1
|
|
||||||
ats->ta1.sameD = false;
|
|
||||||
ats->ta1.ds = BITRATE_106KBITS;
|
|
||||||
ats->ta1.dr = BITRATE_106KBITS;
|
|
||||||
|
|
||||||
// Defaults for TB1
|
|
||||||
ats->tb1.transmitted = false;
|
|
||||||
ats->tb1.fwi = 0; // TODO: Don't know the default for this!
|
|
||||||
ats->tb1.sfgi = 0; // The default value of SFGI is 0 (meaning that the card does not need any particular SFGT)
|
|
||||||
|
|
||||||
// Defaults for TC1
|
|
||||||
ats->tc1.transmitted = false;
|
|
||||||
ats->tc1.supportsCID = true;
|
|
||||||
ats->tc1.supportsNAD = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(ats->data, bufferATS, bufferSize - 2);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // End PICC_RequestATS()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transmits Protocol and Parameter Selection Request (PPS) without parameter 1
|
|
||||||
*
|
|
||||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
|
||||||
*/
|
|
||||||
MFRC522::StatusCode MFRC522::PICC_PPS()
|
|
||||||
{
|
|
||||||
StatusCode result;
|
|
||||||
|
|
||||||
byte ppsBuffer[4];
|
|
||||||
byte ppsBufferSize = 4;
|
|
||||||
// Start byte: The start byte (PPS) consists of two parts:
|
|
||||||
// –The upper nibble(b8–b5) is set to’D'to identify the PPS. All other values are RFU.
|
|
||||||
// -The lower nibble(b4–b1), which is called the ‘card identifier’ (CID), defines the logical number of the addressed card.
|
|
||||||
ppsBuffer[0] = 0xD0; // CID is hardcoded as 0 in RATS
|
|
||||||
ppsBuffer[1] = 0x00; // PPS0 indicates whether PPS1 is present
|
|
||||||
|
|
||||||
// Calculate CRC_A
|
|
||||||
result = PCD_CalculateCRC(ppsBuffer, 2, &ppsBuffer[2]);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transmit the buffer and receive the response, validate CRC_A.
|
|
||||||
result = PCD_TransceiveData(ppsBuffer, 4, ppsBuffer, &ppsBufferSize, NULL, 0, true);
|
|
||||||
if (result == STATUS_OK)
|
|
||||||
{
|
|
||||||
// Enable CRC for T=CL
|
|
||||||
byte txReg = PCD_ReadRegister(TxModeReg) | 0x80;
|
|
||||||
byte rxReg = PCD_ReadRegister(RxModeReg) | 0x80;
|
|
||||||
|
|
||||||
PCD_WriteRegister(TxModeReg, txReg);
|
|
||||||
PCD_WriteRegister(RxModeReg, rxReg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // End PICC_PPS()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transmits Protocol and Parameter Selection Request (PPS)
|
|
||||||
*
|
|
||||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
|
||||||
*/
|
|
||||||
MFRC522::StatusCode MFRC522::PICC_PPS(TagBitRates sendBitRate, ///< DS
|
|
||||||
TagBitRates receiveBitRate ///< DR
|
|
||||||
) {
|
|
||||||
StatusCode result;
|
|
||||||
|
|
||||||
byte txReg = PCD_ReadRegister(TxModeReg) & 0x8F;
|
|
||||||
byte rxReg = PCD_ReadRegister(RxModeReg) & 0x8F;
|
|
||||||
|
|
||||||
byte ppsBuffer[5];
|
|
||||||
byte ppsBufferSize = 5;
|
|
||||||
// Start byte: The start byte (PPS) consists of two parts:
|
|
||||||
// –The upper nibble(b8–b5) is set to’D'to identify the PPS. All other values are RFU.
|
|
||||||
// -The lower nibble(b4–b1), which is called the ‘card identifier’ (CID), defines the logical number of the addressed card.
|
|
||||||
ppsBuffer[0] = 0xD0; // CID is hardcoded as 0 in RATS
|
|
||||||
ppsBuffer[1] = 0x11; // PPS0 indicates whether PPS1 is present
|
|
||||||
|
|
||||||
// Bit 8 - Set to '0' as MFRC522 allows different bit rates for send and receive
|
|
||||||
// Bit 4 - Set to '0' as it is Reserved for future use.
|
|
||||||
//ppsBuffer[2] = (((sendBitRate & 0x03) << 4) | (receiveBitRate & 0x03)) & 0xE7;
|
|
||||||
ppsBuffer[2] = (((sendBitRate & 0x03) << 2) | (receiveBitRate & 0x03)) & 0xE7;
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
// Make sure it is an answer to our PPS
|
|
||||||
// We should receive our PPS byte and 2 CRC bytes
|
|
||||||
if ((ppsBufferSize == 3) && (ppsBuffer[0] == 0xD0)) {
|
|
||||||
byte txReg = PCD_ReadRegister(TxModeReg) & 0x8F;
|
|
||||||
byte rxReg = PCD_ReadRegister(RxModeReg) & 0x8F;
|
|
||||||
|
|
||||||
// Set bit rate and enable CRC for T=CL
|
|
||||||
txReg = (txReg & 0x8F) | ((receiveBitRate & 0x03) << 4) | 0x80;
|
|
||||||
rxReg = (rxReg & 0x8F) | ((sendBitRate & 0x03) << 4) | 0x80;
|
|
||||||
rxReg &= 0xF0; //Enforce although this should be set already
|
|
||||||
|
|
||||||
// From ConfigIsoType
|
|
||||||
//rxReg |= 0x06;
|
|
||||||
|
|
||||||
PCD_WriteRegister(TxModeReg, txReg);
|
|
||||||
PCD_WriteRegister(RxModeReg, rxReg);
|
|
||||||
|
|
||||||
// At 212kBps
|
|
||||||
switch (sendBitRate) {
|
|
||||||
case BITRATE_212KBITS:
|
|
||||||
{
|
|
||||||
//PCD_WriteRegister(ModWidthReg, 0x13);
|
|
||||||
PCD_WriteRegister(ModWidthReg, 0x15);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BITRATE_424KBITS:
|
|
||||||
{
|
|
||||||
PCD_WriteRegister(ModWidthReg, 0x0A);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BITRATE_848KBITS:
|
|
||||||
{
|
|
||||||
PCD_WriteRegister(ModWidthReg, 0x05);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
PCD_WriteRegister(ModWidthReg, 0x26); // Default value
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//PCD_WriteRegister(RxThresholdReg, 0x84); // ISO-14443.4 Type A (default)
|
|
||||||
//PCD_WriteRegister(ControlReg, 0x10);
|
|
||||||
|
|
||||||
delayMicroseconds(10);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // End PICC_PPS()
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Functions for communicating with ISO/IEC 14433-4 cards
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
MFRC522::StatusCode MFRC522::TCL_Transceive(PcbBlock *send, PcbBlock *back)
|
|
||||||
{
|
|
||||||
MFRC522::StatusCode result;
|
|
||||||
byte inBuffer[FIFO_SIZE];
|
|
||||||
byte inBufferSize = FIFO_SIZE;
|
|
||||||
byte outBuffer[send->inf.size + 5]; // PCB + CID + NAD + INF + EPILOGUE (CRC)
|
|
||||||
byte outBufferOffset = 1;
|
|
||||||
byte inBufferOffset = 1;
|
|
||||||
|
|
||||||
// Set the PCB byte
|
|
||||||
outBuffer[0] = send->prologue.pcb;
|
|
||||||
|
|
||||||
// Set the CID byte if available
|
|
||||||
if (send->prologue.pcb & 0x08) {
|
|
||||||
outBuffer[outBufferOffset] = send->prologue.cid;
|
|
||||||
outBufferOffset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the NAD byte if available
|
|
||||||
if (send->prologue.pcb & 0x04) {
|
|
||||||
outBuffer[outBufferOffset] = send->prologue.nad;
|
|
||||||
outBufferOffset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the INF field if available
|
|
||||||
if (send->inf.size > 0) {
|
|
||||||
memcpy(&outBuffer[outBufferOffset], send->inf.data, send->inf.size);
|
|
||||||
outBufferOffset += send->inf.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the CRC enabled for transmission?
|
|
||||||
byte txModeReg = PCD_ReadRegister(TxModeReg);
|
|
||||||
if ((txModeReg & 0x80) != 0x80) {
|
|
||||||
// Calculate CRC_A
|
|
||||||
result = PCD_CalculateCRC(outBuffer, outBufferOffset, &outBuffer[outBufferOffset]);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
outBufferOffset += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transceive the block
|
|
||||||
result = PCD_TransceiveData(outBuffer, outBufferOffset, inBuffer, &inBufferSize);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to turn the received array back to a PcbBlock
|
|
||||||
back->prologue.pcb = inBuffer[0];
|
|
||||||
|
|
||||||
// CID byte is present?
|
|
||||||
if (send->prologue.pcb & 0x08) {
|
|
||||||
back->prologue.cid = inBuffer[inBufferOffset];
|
|
||||||
inBufferOffset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NAD byte is present?
|
|
||||||
if (send->prologue.pcb & 0x04) {
|
|
||||||
back->prologue.nad = inBuffer[inBufferOffset];
|
|
||||||
inBufferOffset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if CRC is taken care of by MFRC522
|
|
||||||
byte rxModeReg = PCD_ReadRegister(TxModeReg);
|
|
||||||
if ((rxModeReg & 0x80) != 0x80) {
|
|
||||||
Serial.print("CRC is not taken care of by MFRC522: ");
|
|
||||||
Serial.println(rxModeReg, HEX);
|
|
||||||
|
|
||||||
// Check the CRC
|
|
||||||
// We need at least the CRC_A value.
|
|
||||||
if ((int)(inBufferSize - inBufferOffset) < 2) {
|
|
||||||
return STATUS_CRC_WRONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify CRC_A - do our own calculation and store the control in controlBuffer.
|
|
||||||
byte controlBuffer[2];
|
|
||||||
MFRC522::StatusCode status = PCD_CalculateCRC(inBuffer, inBufferSize - 2, controlBuffer);
|
|
||||||
if (status != STATUS_OK) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((inBuffer[inBufferSize - 2] != controlBuffer[0]) || (inBuffer[inBufferSize - 1] != controlBuffer[1])) {
|
|
||||||
return STATUS_CRC_WRONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take away the CRC bytes
|
|
||||||
inBufferSize -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Got more data?
|
|
||||||
if (inBufferSize > inBufferOffset) {
|
|
||||||
if ((inBufferSize - inBufferOffset) > back->inf.size) {
|
|
||||||
return STATUS_NO_ROOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(back->inf.data, &inBuffer[inBufferOffset], inBufferSize - inBufferOffset);
|
|
||||||
back->inf.size = inBufferSize - inBufferOffset;
|
|
||||||
} else {
|
|
||||||
back->inf.size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the response is a R-Block check NACK
|
|
||||||
if (((inBuffer[0] & 0xC0) == 0x80) && (inBuffer[0] & 0x20)) {
|
|
||||||
return STATUS_MIFARE_NACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Send an I-Block (Application)
|
|
||||||
*/
|
|
||||||
MFRC522::StatusCode MFRC522::TCL_Transceive(TagInfo *tag, byte *sendData, byte sendLen, byte *backData, byte *backLen)
|
|
||||||
{
|
|
||||||
MFRC522::StatusCode result;
|
|
||||||
|
|
||||||
PcbBlock out;
|
|
||||||
PcbBlock in;
|
|
||||||
byte outBuffer[FIFO_SIZE];
|
|
||||||
byte outBufferSize = FIFO_SIZE;
|
|
||||||
byte totalBackLen = *backLen;
|
|
||||||
|
|
||||||
// This command sends an I-Block
|
|
||||||
out.prologue.pcb = 0x02;
|
|
||||||
|
|
||||||
if (tag->ats.tc1.supportsCID) {
|
|
||||||
out.prologue.pcb |= 0x08;
|
|
||||||
out.prologue.cid = 0x00; // CID is curentlly hardcoded as 0x00
|
|
||||||
}
|
|
||||||
|
|
||||||
// This command doe not support NAD
|
|
||||||
out.prologue.pcb &= 0xFB;
|
|
||||||
out.prologue.nad = 0x00;
|
|
||||||
|
|
||||||
// Set the block number
|
|
||||||
if (tag->blockNumber) {
|
|
||||||
out.prologue.pcb |= 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we have data to send?
|
|
||||||
if (sendData && (sendLen > 0)) {
|
|
||||||
out.inf.size = sendLen;
|
|
||||||
out.inf.data = sendData;
|
|
||||||
} else {
|
|
||||||
out.inf.size = 0;
|
|
||||||
out.inf.data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the receiving data
|
|
||||||
in.inf.data = outBuffer;
|
|
||||||
in.inf.size = outBufferSize;
|
|
||||||
|
|
||||||
result = TCL_Transceive(&out, &in);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap block number on success
|
|
||||||
if (tag->blockNumber)
|
|
||||||
tag->blockNumber = false;
|
|
||||||
else
|
|
||||||
tag->blockNumber = true;
|
|
||||||
|
|
||||||
if (backData && (backLen > 0)) {
|
|
||||||
if (*backLen < in.inf.size)
|
|
||||||
return STATUS_NO_ROOM;
|
|
||||||
|
|
||||||
*backLen = in.inf.size;
|
|
||||||
memcpy(backData, in.inf.data, in.inf.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check chaining
|
|
||||||
if (in.prologue.pcb & 0x10 == 0x00)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Result is chained
|
|
||||||
// Send an ACK to receive more data
|
|
||||||
// TODO: Should be checked I've never needed to send an ACK
|
|
||||||
while (in.prologue.pcb & 0x10) {
|
|
||||||
byte ackData[FIFO_SIZE];
|
|
||||||
byte ackDataSize = FIFO_SIZE;
|
|
||||||
|
|
||||||
result = TCL_TransceiveRBlock(tag, true, ackData, &ackDataSize);
|
|
||||||
if (result != STATUS_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (backData && (backLen > 0)) {
|
|
||||||
if ((*backLen + ackDataSize) > totalBackLen)
|
|
||||||
return STATUS_NO_ROOM;
|
|
||||||
|
|
||||||
memcpy(&(backData[*backLen]), ackData, ackDataSize);
|
|
||||||
*backLen += ackDataSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // End TCL_Transceive()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send R-Block to the PICC.
|
|
||||||
*/
|
|
||||||
MFRC522::StatusCode MFRC522::TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData, byte *backLen)
|
|
||||||
{
|
|
||||||
MFRC522::StatusCode result;
|
|
||||||
|
|
||||||
PcbBlock out;
|
|
||||||
PcbBlock in;
|
|
||||||
byte outBuffer[FIFO_SIZE];
|
|
||||||
byte outBufferSize = FIFO_SIZE;
|
|
||||||
|
|
||||||
// This command sends an R-Block
|
|
||||||
if (ack)
|
|
||||||
out.prologue.pcb = 0xA2; // ACK
|
|
||||||
else
|
|
||||||
out.prologue.pcb = 0xB2; // NAK
|
|
||||||
|
|
||||||
|
|
||||||
if (tag->ats.tc1.supportsCID) {
|
|
||||||
out.prologue.pcb |= 0x08;
|
|
||||||
out.prologue.cid = 0x00; // CID is curentlly hardcoded as 0x00
|
|
||||||
}
|
|
||||||
|
|
||||||
// This command doe not support NAD
|
|
||||||
out.prologue.pcb &= 0xFB;
|
|
||||||
out.prologue.nad = 0x00;
|
|
||||||
|
|
||||||
// Set the block number
|
|
||||||
if (tag->blockNumber) {
|
|
||||||
out.prologue.pcb |= 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No INF data for R-Block
|
|
||||||
out.inf.size = 0;
|
|
||||||
out.inf.data = NULL;
|
|
||||||
|
|
||||||
// Initialize the receiving data
|
|
||||||
in.inf.data = outBuffer;
|
|
||||||
in.inf.size = outBufferSize;
|
|
||||||
|
|
||||||
result = TCL_Transceive(&out, &in);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap block number on success
|
|
||||||
if (tag->blockNumber)
|
|
||||||
tag->blockNumber = false;
|
|
||||||
else
|
|
||||||
tag->blockNumber = true;
|
|
||||||
|
|
||||||
if (backData && backLen) {
|
|
||||||
if (*backLen < in.inf.size)
|
|
||||||
return STATUS_NO_ROOM;
|
|
||||||
|
|
||||||
*backLen = in.inf.size;
|
|
||||||
memcpy(backData, in.inf.data, in.inf.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // End TCL_TransceiveRBlock()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an S-Block to deselect the card.
|
|
||||||
*/
|
|
||||||
MFRC522::StatusCode MFRC522::TCL_Deselect(TagInfo *tag)
|
|
||||||
{
|
|
||||||
MFRC522::StatusCode result;
|
|
||||||
byte outBuffer[4];
|
|
||||||
byte outBufferSize = 1;
|
|
||||||
byte inBuffer[FIFO_SIZE];
|
|
||||||
byte inBufferSize = FIFO_SIZE;
|
|
||||||
|
|
||||||
outBuffer[0] = 0xC2;
|
|
||||||
if (tag->ats.tc1.supportsCID)
|
|
||||||
{
|
|
||||||
outBuffer[0] |= 0x08;
|
|
||||||
outBuffer[1] = 0x00; // CID is hardcoded
|
|
||||||
outBufferSize = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = PCD_TransceiveData(outBuffer, outBufferSize, inBuffer, &inBufferSize);
|
|
||||||
if (result != STATUS_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:Maybe do some checks? In my test it returns: CA 00 (Same data as I sent to my card)
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} // End TCL_Deselect()
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Functions for communicating with MIFARE PICCs
|
// Functions for communicating with MIFARE PICCs
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1963,36 +1258,6 @@ const __FlashStringHelper *MFRC522::GetStatusCodeName(MFRC522::StatusCode code /
|
|||||||
}
|
}
|
||||||
} // End GetStatusCodeName()
|
} // End GetStatusCodeName()
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the PICC type.
|
|
||||||
*
|
|
||||||
* @return PICC_Type
|
|
||||||
*/
|
|
||||||
MFRC522::PICC_Type MFRC522::PICC_GetType(TagInfo *tag ///< The TagInfo returned from PICC_Select().
|
|
||||||
) {
|
|
||||||
// http://www.nxp.com/documents/application_note/AN10833.pdf
|
|
||||||
// 3.2 Coding of Select Acknowledge (SAK)
|
|
||||||
// ignore 8-bit (iso14443 starts with LSBit = bit 1)
|
|
||||||
// fixes wrong type for manufacturer Infineon (http://nfc-tools.org/index.php?title=ISO14443A)
|
|
||||||
byte sak = tag->uid.sak & 0x7F;
|
|
||||||
switch (sak) {
|
|
||||||
case 0x04: return PICC_TYPE_NOT_COMPLETE; // UID not complete
|
|
||||||
case 0x09: return PICC_TYPE_MIFARE_MINI;
|
|
||||||
case 0x08: return PICC_TYPE_MIFARE_1K;
|
|
||||||
case 0x18: return PICC_TYPE_MIFARE_4K;
|
|
||||||
case 0x00: return PICC_TYPE_MIFARE_UL;
|
|
||||||
case 0x10:
|
|
||||||
case 0x11: return PICC_TYPE_MIFARE_PLUS;
|
|
||||||
case 0x01: return PICC_TYPE_TNP3XXX;
|
|
||||||
case 0x20:
|
|
||||||
if (tag->atqa == 0x0344)
|
|
||||||
return PICC_TYPE_MIFARE_DESFIRE;
|
|
||||||
return PICC_TYPE_ISO_14443_4;
|
|
||||||
case 0x40: return PICC_TYPE_ISO_18092;
|
|
||||||
default: return PICC_TYPE_UNKNOWN;
|
|
||||||
}
|
|
||||||
} // End PICC_GetType()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the SAK (Select Acknowledge) to a PICC type.
|
* Translates the SAK (Select Acknowledge) to a PICC type.
|
||||||
*
|
*
|
||||||
@@ -2065,56 +1330,6 @@ void MFRC522::PCD_DumpVersionToSerial() {
|
|||||||
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
|
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
|
||||||
} // End PCD_DumpVersionToSerial()
|
} // End PCD_DumpVersionToSerial()
|
||||||
|
|
||||||
/**
|
|
||||||
* Dumps debug info about the selected PICC to Serial.
|
|
||||||
* On success the PICC is halted after dumping the data.
|
|
||||||
* For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.
|
|
||||||
*/
|
|
||||||
void MFRC522::PICC_DumpToSerial(TagInfo *tag)
|
|
||||||
{
|
|
||||||
MIFARE_Key key;
|
|
||||||
|
|
||||||
// Dump UID, SAK and Type
|
|
||||||
PICC_DumpDetailsToSerial(tag);
|
|
||||||
|
|
||||||
// Dump contents
|
|
||||||
PICC_Type piccType = PICC_GetType(tag->uid.sak);
|
|
||||||
switch (piccType) {
|
|
||||||
case PICC_TYPE_MIFARE_MINI:
|
|
||||||
case PICC_TYPE_MIFARE_1K:
|
|
||||||
case PICC_TYPE_MIFARE_4K:
|
|
||||||
// All keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
|
|
||||||
for (byte i = 0; i < 6; i++) {
|
|
||||||
key.keyByte[i] = 0xFF;
|
|
||||||
}
|
|
||||||
PICC_DumpMifareClassicToSerial(&tag->uid, piccType, &key);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PICC_TYPE_MIFARE_UL:
|
|
||||||
PICC_DumpMifareUltralightToSerial();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PICC_TYPE_ISO_14443_4:
|
|
||||||
case PICC_TYPE_MIFARE_DESFIRE:
|
|
||||||
PICC_DumpISO14443_4(tag);
|
|
||||||
Serial.println(F("Dumping memory contents not implemented for that PICC type."));
|
|
||||||
break;
|
|
||||||
case PICC_TYPE_ISO_18092:
|
|
||||||
case PICC_TYPE_MIFARE_PLUS:
|
|
||||||
case PICC_TYPE_TNP3XXX:
|
|
||||||
Serial.println(F("Dumping memory contents not implemented for that PICC type."));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PICC_TYPE_UNKNOWN:
|
|
||||||
case PICC_TYPE_NOT_COMPLETE:
|
|
||||||
default:
|
|
||||||
break; // No memory dump here
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.println();
|
|
||||||
PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps debug info about the selected PICC to Serial.
|
* Dumps debug info about the selected PICC to Serial.
|
||||||
* On success the PICC is halted after dumping the data.
|
* On success the PICC is halted after dumping the data.
|
||||||
@@ -2164,45 +1379,6 @@ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned fro
|
|||||||
PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
|
PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
|
||||||
} // End PICC_DumpToSerial()
|
} // End PICC_DumpToSerial()
|
||||||
|
|
||||||
/**
|
|
||||||
* Dumps card info (UID,SAK,Type) about the selected PICC to Serial.
|
|
||||||
*/
|
|
||||||
void MFRC522::PICC_DumpDetailsToSerial(TagInfo *tag ///< Pointer to TagInfo struct returned from a successful PICC_Select().
|
|
||||||
) {
|
|
||||||
// ATQA
|
|
||||||
Serial.print(F("Card ATQA:"));
|
|
||||||
if (((tag->atqa & 0xFF00u) >> 8) < 0x10)
|
|
||||||
Serial.print(F(" 0"));
|
|
||||||
Serial.print((tag->atqa & 0xFF00u) >> 8, HEX);
|
|
||||||
if ((tag->atqa & 0x00FFu) < 0x10)
|
|
||||||
Serial.print(F("0"));
|
|
||||||
else
|
|
||||||
Serial.print(F(" "));
|
|
||||||
Serial.println(tag->atqa & 0x00FFu, HEX);
|
|
||||||
|
|
||||||
// UID
|
|
||||||
Serial.print(F("Card UID:"));
|
|
||||||
for (byte i = 0; i < tag->uid.size; i++) {
|
|
||||||
if (tag->uid.uidByte[i] < 0x10)
|
|
||||||
Serial.print(F(" 0"));
|
|
||||||
else
|
|
||||||
Serial.print(F(" "));
|
|
||||||
Serial.print(tag->uid.uidByte[i], HEX);
|
|
||||||
}
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
// SAK
|
|
||||||
Serial.print(F("Card SAK: "));
|
|
||||||
if (tag->uid.sak < 0x10)
|
|
||||||
Serial.print(F("0"));
|
|
||||||
Serial.println(tag->uid.sak, HEX);
|
|
||||||
|
|
||||||
// (suggested) PICC type
|
|
||||||
PICC_Type piccType = PICC_GetType(tag);
|
|
||||||
Serial.print(F("PICC type: "));
|
|
||||||
Serial.println(PICC_GetTypeName(piccType));
|
|
||||||
} // End PICC_DumpDetailsToSerial()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps card info (UID,SAK,Type) about the selected PICC to Serial.
|
* Dumps card info (UID,SAK,Type) about the selected PICC to Serial.
|
||||||
*
|
*
|
||||||
@@ -2465,26 +1641,6 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() {
|
|||||||
}
|
}
|
||||||
} // End PICC_DumpMifareUltralightToSerial()
|
} // End PICC_DumpMifareUltralightToSerial()
|
||||||
|
|
||||||
/**
|
|
||||||
* Dumps memory contents of a ISO-14443-4 PICC.
|
|
||||||
*/
|
|
||||||
void MFRC522::PICC_DumpISO14443_4(TagInfo *tag)
|
|
||||||
{
|
|
||||||
// ATS
|
|
||||||
if (tag->ats.size > 0x00) { // The first byte is the ATS length including the length byte
|
|
||||||
Serial.print(F("Card ATS:"));
|
|
||||||
for (byte offset = 0; offset < tag->ats.size; offset++) {
|
|
||||||
if (tag->ats.data[offset] < 0x10)
|
|
||||||
Serial.print(F(" 0"));
|
|
||||||
else
|
|
||||||
Serial.print(F(" "));
|
|
||||||
Serial.print(tag->ats.data[offset], HEX);
|
|
||||||
}
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End PICC_DumpISO14443_4
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).
|
* Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).
|
||||||
*/
|
*/
|
||||||
@@ -2725,34 +1881,7 @@ bool MFRC522::PICC_IsNewCardPresent() {
|
|||||||
PCD_WriteRegister(ModWidthReg, 0x26);
|
PCD_WriteRegister(ModWidthReg, 0x26);
|
||||||
|
|
||||||
MFRC522::StatusCode result = PICC_RequestA(bufferATQA, &bufferSize);
|
MFRC522::StatusCode result = PICC_RequestA(bufferATQA, &bufferSize);
|
||||||
|
return (result == STATUS_OK || result == STATUS_COLLISION);
|
||||||
if (result == STATUS_OK || result == STATUS_COLLISION) {
|
|
||||||
tag.atqa = ((uint16_t)bufferATQA[1] << 8) | bufferATQA[0];
|
|
||||||
tag.ats.size = 0;
|
|
||||||
tag.ats.fsc = 32; // default FSC value
|
|
||||||
|
|
||||||
// Defaults for TA1
|
|
||||||
tag.ats.ta1.transmitted = false;
|
|
||||||
tag.ats.ta1.sameD = false;
|
|
||||||
tag.ats.ta1.ds = BITRATE_106KBITS;
|
|
||||||
tag.ats.ta1.dr = BITRATE_106KBITS;
|
|
||||||
|
|
||||||
// Defaults for TB1
|
|
||||||
tag.ats.tb1.transmitted = false;
|
|
||||||
tag.ats.tb1.fwi = 0; // TODO: Don't know the default for this!
|
|
||||||
tag.ats.tb1.sfgi = 0; // The default value of SFGI is 0 (meaning that the card does not need any particular SFGT)
|
|
||||||
|
|
||||||
// Defaults for TC1
|
|
||||||
tag.ats.tc1.transmitted = false;
|
|
||||||
tag.ats.tc1.supportsCID = true;
|
|
||||||
tag.ats.tc1.supportsNAD = false;
|
|
||||||
|
|
||||||
memset(tag.ats.data, 0, FIFO_SIZE - 2);
|
|
||||||
|
|
||||||
tag.blockNumber = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} // End PICC_IsNewCardPresent()
|
} // End PICC_IsNewCardPresent()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2764,15 +1893,6 @@ bool MFRC522::PICC_IsNewCardPresent() {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
bool MFRC522::PICC_ReadCardSerial() {
|
bool MFRC522::PICC_ReadCardSerial() {
|
||||||
MFRC522::StatusCode result = PICC_Select(&tag.uid);
|
MFRC522::StatusCode result = PICC_Select(&uid);
|
||||||
|
return (result == STATUS_OK);
|
||||||
// Backward compatibility
|
|
||||||
uid.size = tag.uid.size;
|
|
||||||
uid.sak = tag.uid.sak;
|
|
||||||
memcpy(uid.uidByte, tag.uid.uidByte, sizeof(tag.uid.uidByte));
|
|
||||||
|
|
||||||
if (result != STATUS_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} // End
|
} // End
|
||||||
|
|||||||
84
MFRC522.h
84
MFRC522.h
@@ -77,6 +77,7 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define MFRC522_SPICLOCK SPI_CLOCK_DIV4 // MFRC522 accept upto 10MHz
|
#define MFRC522_SPICLOCK SPI_CLOCK_DIV4 // MFRC522 accept upto 10MHz
|
||||||
|
|
||||||
@@ -307,14 +308,6 @@ public:
|
|||||||
STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
|
STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
|
||||||
};
|
};
|
||||||
|
|
||||||
// ISO/IEC 14443-4 bit rates
|
|
||||||
enum TagBitRates : byte {
|
|
||||||
BITRATE_106KBITS = 0x00,
|
|
||||||
BITRATE_212KBITS = 0x01,
|
|
||||||
BITRATE_424KBITS = 0x02,
|
|
||||||
BITRATE_848KBITS = 0x03
|
|
||||||
};
|
|
||||||
|
|
||||||
// A struct used for passing the UID of a PICC.
|
// A struct used for passing the UID of a PICC.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte size; // Number of bytes in the UID. 4, 7 or 10.
|
byte size; // Number of bytes in the UID. 4, 7 or 10.
|
||||||
@@ -322,65 +315,13 @@ public:
|
|||||||
byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
|
byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
|
||||||
} Uid;
|
} Uid;
|
||||||
|
|
||||||
// Structure to store ISO/IEC 14443-4 ATS
|
|
||||||
typedef struct {
|
|
||||||
byte size;
|
|
||||||
byte fsc; // Frame size for proximity card
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool transmitted;
|
|
||||||
bool sameD; // Only the same D for both directions supported
|
|
||||||
TagBitRates ds; // Send D
|
|
||||||
TagBitRates dr; // Receive D
|
|
||||||
} ta1;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool transmitted;
|
|
||||||
byte fwi; // Frame waiting time integer
|
|
||||||
byte sfgi; // Start-up frame guard time integer
|
|
||||||
} tb1;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool transmitted;
|
|
||||||
bool supportsCID;
|
|
||||||
bool supportsNAD;
|
|
||||||
} tc1;
|
|
||||||
|
|
||||||
// Raw data from ATS
|
|
||||||
byte data[FIFO_SIZE - 2]; // ATS cannot be bigger than FSD - 2 bytes (CRC), according to ISO 14443-4 5.2.2
|
|
||||||
} Ats;
|
|
||||||
|
|
||||||
// A struct used for passing the PICC information
|
|
||||||
typedef struct {
|
|
||||||
uint16_t atqa;
|
|
||||||
Uid uid;
|
|
||||||
Ats ats;
|
|
||||||
|
|
||||||
// For Block PCB
|
|
||||||
bool blockNumber;
|
|
||||||
} TagInfo;
|
|
||||||
|
|
||||||
// A struct used for passing a MIFARE Crypto1 key
|
// A struct used for passing a MIFARE Crypto1 key
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte keyByte[MF_KEY_SIZE];
|
byte keyByte[MF_KEY_SIZE];
|
||||||
} MIFARE_Key;
|
} MIFARE_Key;
|
||||||
|
|
||||||
// A struct used for passing PCB Block
|
|
||||||
typedef struct {
|
|
||||||
struct {
|
|
||||||
byte pcb;
|
|
||||||
byte cid;
|
|
||||||
byte nad;
|
|
||||||
} prologue;
|
|
||||||
struct {
|
|
||||||
byte size;
|
|
||||||
byte *data;
|
|
||||||
} inf;
|
|
||||||
} PcbBlock;
|
|
||||||
|
|
||||||
// Member variables
|
// Member variables
|
||||||
Uid uid; // Used by PICC_ReadCardSerial().
|
Uid uid; // Used by PICC_ReadCardSerial().
|
||||||
TagInfo tag;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Functions for setting up the Arduino
|
// Functions for setting up the Arduino
|
||||||
@@ -422,19 +363,8 @@ public:
|
|||||||
StatusCode PICC_RequestA(byte *bufferATQA, byte *bufferSize);
|
StatusCode PICC_RequestA(byte *bufferATQA, byte *bufferSize);
|
||||||
StatusCode PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
|
StatusCode PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
|
||||||
StatusCode PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
|
StatusCode PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
|
||||||
StatusCode PICC_Select(Uid *uid, byte validBits = 0);
|
virtual StatusCode PICC_Select(Uid *uid, byte validBits = 0);
|
||||||
StatusCode PICC_HaltA();
|
StatusCode PICC_HaltA();
|
||||||
StatusCode PICC_RequestATS(Ats *ats);
|
|
||||||
StatusCode PICC_PPS(); // PPS command without bitrate parameter
|
|
||||||
StatusCode PICC_PPS(TagBitRates sendBitRate, TagBitRates receiveBitRate); // Different D values
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Functions for communicating with ISO/IEC 14433-4 cards
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
StatusCode TCL_Transceive(PcbBlock *send, PcbBlock *back);
|
|
||||||
StatusCode TCL_Transceive(TagInfo * tag, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL);
|
|
||||||
StatusCode TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData = NULL, byte *backLen = NULL);
|
|
||||||
StatusCode TCL_Deselect(TagInfo *tag);
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Functions for communicating with MIFARE PICCs
|
// Functions for communicating with MIFARE PICCs
|
||||||
@@ -460,21 +390,17 @@ public:
|
|||||||
//const char *GetStatusCodeName(byte code);
|
//const char *GetStatusCodeName(byte code);
|
||||||
static const __FlashStringHelper *GetStatusCodeName(StatusCode code);
|
static const __FlashStringHelper *GetStatusCodeName(StatusCode code);
|
||||||
static PICC_Type PICC_GetType(byte sak);
|
static PICC_Type PICC_GetType(byte sak);
|
||||||
static PICC_Type PICC_GetType(TagInfo *tag);
|
|
||||||
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
|
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
|
||||||
//const char *PICC_GetTypeName(byte type);
|
//const char *PICC_GetTypeName(byte type);
|
||||||
static const __FlashStringHelper *PICC_GetTypeName(PICC_Type type);
|
static const __FlashStringHelper *PICC_GetTypeName(PICC_Type type);
|
||||||
|
|
||||||
// Support functions for debuging
|
// Support functions for debuging
|
||||||
void PCD_DumpVersionToSerial();
|
void PCD_DumpVersionToSerial();
|
||||||
void PICC_DumpToSerial(TagInfo *tag);
|
|
||||||
void PICC_DumpToSerial(Uid *uid);
|
void PICC_DumpToSerial(Uid *uid);
|
||||||
void PICC_DumpDetailsToSerial(TagInfo *tag);
|
|
||||||
void PICC_DumpDetailsToSerial(Uid *uid);
|
void PICC_DumpDetailsToSerial(Uid *uid);
|
||||||
void PICC_DumpMifareClassicToSerial(Uid *uid, PICC_Type piccType, MIFARE_Key *key);
|
void PICC_DumpMifareClassicToSerial(Uid *uid, PICC_Type piccType, MIFARE_Key *key);
|
||||||
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
|
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
|
||||||
void PICC_DumpMifareUltralightToSerial();
|
void PICC_DumpMifareUltralightToSerial();
|
||||||
void PICC_DumpISO14443_4(TagInfo *tag);
|
|
||||||
|
|
||||||
// Advanced functions for MIFARE
|
// Advanced functions for MIFARE
|
||||||
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
|
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
|
||||||
@@ -485,10 +411,10 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Convenience functions - does not add extra functionality
|
// Convenience functions - does not add extra functionality
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
bool PICC_IsNewCardPresent();
|
virtual bool PICC_IsNewCardPresent();
|
||||||
bool PICC_ReadCardSerial();
|
virtual bool PICC_ReadCardSerial();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
byte _chipSelectPin; // Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
|
byte _chipSelectPin; // Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
|
||||||
byte _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
|
byte _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
|
||||||
StatusCode MIFARE_TwoStepHelper(byte command, byte blockAddr, int32_t data);
|
StatusCode MIFARE_TwoStepHelper(byte command, byte blockAddr, int32_t data);
|
||||||
|
|||||||
1161
MFRC522Extended.cpp
Normal file
1161
MFRC522Extended.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
MFRC522Extended.h
Normal file
110
MFRC522Extended.h
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* Library extends MFRC522.h to support RATS for ISO-14443-4 PICC.
|
||||||
|
* RATS - Request for Answer To Select.
|
||||||
|
* @author JPG-Consulting
|
||||||
|
*/
|
||||||
|
#ifndef MFRC522Extended_h
|
||||||
|
#define MFRC522Extended_h
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "MFRC522.h"
|
||||||
|
|
||||||
|
class MFRC522Extended : public MFRC522 {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// ISO/IEC 14443-4 bit rates
|
||||||
|
enum TagBitRates : byte {
|
||||||
|
BITRATE_106KBITS = 0x00,
|
||||||
|
BITRATE_212KBITS = 0x01,
|
||||||
|
BITRATE_424KBITS = 0x02,
|
||||||
|
BITRATE_848KBITS = 0x03
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structure to store ISO/IEC 14443-4 ATS
|
||||||
|
typedef struct {
|
||||||
|
byte size;
|
||||||
|
byte fsc; // Frame size for proximity card
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool transmitted;
|
||||||
|
bool sameD; // Only the same D for both directions supported
|
||||||
|
TagBitRates ds; // Send D
|
||||||
|
TagBitRates dr; // Receive D
|
||||||
|
} ta1;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool transmitted;
|
||||||
|
byte fwi; // Frame waiting time integer
|
||||||
|
byte sfgi; // Start-up frame guard time integer
|
||||||
|
} tb1;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool transmitted;
|
||||||
|
bool supportsCID;
|
||||||
|
bool supportsNAD;
|
||||||
|
} tc1;
|
||||||
|
|
||||||
|
// Raw data from ATS
|
||||||
|
byte data[FIFO_SIZE - 2]; // ATS cannot be bigger than FSD - 2 bytes (CRC), according to ISO 14443-4 5.2.2
|
||||||
|
} Ats;
|
||||||
|
|
||||||
|
// A struct used for passing the PICC information
|
||||||
|
typedef struct {
|
||||||
|
uint16_t atqa;
|
||||||
|
Uid uid;
|
||||||
|
Ats ats;
|
||||||
|
|
||||||
|
// For Block PCB
|
||||||
|
bool blockNumber;
|
||||||
|
} TagInfo;
|
||||||
|
|
||||||
|
// A struct used for passing PCB Block
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
byte pcb;
|
||||||
|
byte cid;
|
||||||
|
byte nad;
|
||||||
|
} prologue;
|
||||||
|
struct {
|
||||||
|
byte size;
|
||||||
|
byte *data;
|
||||||
|
} inf;
|
||||||
|
} PcbBlock;
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
TagInfo tag;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions for communicating with PICCs
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StatusCode PICC_Select(Uid *uid, byte validBits = 0); // overwrite
|
||||||
|
StatusCode PICC_RequestATS(Ats *ats);
|
||||||
|
StatusCode PICC_PPS(); // PPS command without bitrate parameter
|
||||||
|
StatusCode PICC_PPS(TagBitRates sendBitRate, TagBitRates receiveBitRate); // Different D values
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions for communicating with ISO/IEC 14433-4 cards
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
StatusCode TCL_Transceive(PcbBlock *send, PcbBlock *back);
|
||||||
|
StatusCode TCL_Transceive(TagInfo * tag, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL);
|
||||||
|
StatusCode TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData = NULL, byte *backLen = NULL);
|
||||||
|
StatusCode TCL_Deselect(TagInfo *tag);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Support functions
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static PICC_Type PICC_GetType(TagInfo *tag);
|
||||||
|
|
||||||
|
// Support functions for debuging
|
||||||
|
void PICC_DumpToSerial(TagInfo *tag);
|
||||||
|
void PICC_DumpDetailsToSerial(TagInfo *tag);
|
||||||
|
void PICC_DumpISO14443_4(TagInfo *tag);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Convenience functions - does not add extra functionality
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool PICC_IsNewCardPresent(); // overwrite
|
||||||
|
bool PICC_ReadCardSerial(); // overwrite
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user