MIFARE specific functions renamed.
Write for MIFARE Ultralight implemented. Cleanup.
This commit is contained in:
202
MFRC522.cpp
202
MFRC522.cpp
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* MFRC522.cpp - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
|
||||
* Please see comments in MFRC522.h
|
||||
* _Please_ see the comments in MFRC522.h - they give useful hints and background.
|
||||
* Released into the public domain.
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* Prepares the output pins.
|
||||
*/
|
||||
MFRC522::MFRC522( 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)
|
||||
) {
|
||||
// Set the chipSelectPin as digital output, do not select the slave yet
|
||||
_chipSelectPin = chipSelectPin;
|
||||
@@ -93,9 +93,9 @@ byte MFRC522::PCD_ReadRegister( byte reg ///< The register to read from. One of
|
||||
* The interface is described in the datasheet section 8.1.2.
|
||||
*/
|
||||
void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One of the PCD_Register enums.
|
||||
byte count, ///< The number of bytes to read
|
||||
byte *values, ///< Byte array to store the values in.
|
||||
byte rxAlign ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
byte count, ///< The number of bytes to read
|
||||
byte *values, ///< Byte array to store the values in.
|
||||
byte rxAlign ///< Only bit positions rxAlign..7 in values[0] are updated.
|
||||
) {
|
||||
if (count == 0) {
|
||||
return;
|
||||
@@ -104,8 +104,8 @@ void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One o
|
||||
byte address = 0x80 | (reg & 0x7E); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
|
||||
byte index = 0; // Index in values array.
|
||||
digitalWrite(_chipSelectPin, LOW); // Select slave
|
||||
count--; // One read is performed outside of the loop
|
||||
SPI.transfer(address); // Tell MFRC522 which address we want to read
|
||||
count--; // One read is performed outside of the loop
|
||||
SPI.transfer(address); // Tell MFRC522 which address we want to read
|
||||
while (index < count) {
|
||||
if (index == 0 && rxAlign) { // Only update bit positions rxAlign..7 in values[0]
|
||||
// Create bit mask for bit positions rxAlign..7
|
||||
@@ -141,7 +141,7 @@ void MFRC522::PCD_SetRegisterBitMask( byte reg, ///< The register to update. One
|
||||
/**
|
||||
* Clears the bits given in mask from register reg.
|
||||
*/
|
||||
void MFRC522::PCD_ClearRegisterBitMask(byte reg, ///< The register to update. One of the PCD_Register enums.
|
||||
void MFRC522::PCD_ClearRegisterBitMask( byte reg, ///< The register to update. One of the PCD_Register enums.
|
||||
byte mask ///< The bits to clear.
|
||||
) {
|
||||
byte tmp;
|
||||
@@ -229,7 +229,7 @@ void MFRC522::PCD_Reset() {
|
||||
while (PCD_ReadRegister(CommandReg) & (1<<4)) {
|
||||
// PCD still restarting - unlikely after waiting 50ms, but better safe than sorry.
|
||||
}
|
||||
}
|
||||
} // End PCD_Reset()
|
||||
|
||||
/**
|
||||
* Turns the antenna on by enabling pins TX1 and TX2.
|
||||
@@ -361,7 +361,7 @@ byte MFRC522::PCD_CommunicateWithPICC( byte command, ///< The command to execut
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
} // End PCD_CommunicateWithPICC
|
||||
} // End PCD_CommunicateWithPICC()
|
||||
|
||||
/**
|
||||
* Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
|
||||
@@ -373,7 +373,7 @@ byte MFRC522::PICC_RequestA(byte *bufferATQA, ///< The buffer to store the ATQA
|
||||
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
|
||||
) {
|
||||
return PICC_REQA_or_WUPA(PICC_CMD_REQA, bufferATQA, bufferSize);
|
||||
}
|
||||
} // End PICC_RequestA()
|
||||
|
||||
/**
|
||||
* Transmits a Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
|
||||
@@ -385,7 +385,7 @@ byte MFRC522::PICC_WakeupA( byte *bufferATQA, ///< The buffer to store the ATQA
|
||||
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
|
||||
) {
|
||||
return PICC_REQA_or_WUPA(PICC_CMD_WUPA, bufferATQA, bufferSize);
|
||||
}
|
||||
} // End PICC_WakeupA()
|
||||
|
||||
/**
|
||||
* Transmits REQA or WUPA commands.
|
||||
@@ -443,8 +443,8 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
|
||||
byte count;
|
||||
byte index;
|
||||
byte uidIndex; // The first index in uid->uidByte[] that is used in the current Cascade Level.
|
||||
char currentLevelKnownBits; // The number of known UID bits in the current Cascade Level.
|
||||
byte buffer[9]; // The SELECT/ANTICOLLISION commands uses a 7 byte standard frame + 2 bytes CRC_A
|
||||
char currentLevelKnownBits; // The number of known UID bits in the current Cascade Level.
|
||||
byte buffer[9]; // The SELECT/ANTICOLLISION commands uses a 7 byte standard frame + 2 bytes CRC_A
|
||||
byte bufferUsed; // The number of bytes used in the buffer, ie the number of bytes to transfer to the FIFO.
|
||||
byte rxAlign; // Used in BitFramingReg. Defines the bit position for the first bit received.
|
||||
byte txLastBits; // Used in BitFramingReg. The number of valid bits in the last transmitted byte.
|
||||
@@ -501,7 +501,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
|
||||
case 3:
|
||||
buffer[0] = PICC_CMD_SEL_CL3;
|
||||
uidIndex = 6;
|
||||
useCascadeTag = false; // Never used in CL3.
|
||||
useCascadeTag = false; // Never used in CL3.
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -567,7 +567,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
|
||||
}
|
||||
|
||||
// Set bit adjustments
|
||||
rxAlign = txLastBits; // Having a seperate variable is overkill. But it makes the next line easier to read.
|
||||
rxAlign = txLastBits; // Having a seperate variable is overkill. But it makes the next line easier to read.
|
||||
PCD_WriteRegister(BitFramingReg, (rxAlign << 4) + txLastBits); // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
|
||||
|
||||
// Transmit the buffer and receive the response.
|
||||
@@ -581,7 +581,6 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
|
||||
if (collisionPos == 0) {
|
||||
collisionPos = 32;
|
||||
}
|
||||
//Serial.print("Collision in bit "); Serial.println(collisionPos);
|
||||
if (collisionPos <= currentLevelKnownBits) { // No progress - should not happen
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
@@ -605,7 +604,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
|
||||
// Run loop again to do the SELECT.
|
||||
}
|
||||
}
|
||||
} //End of while ( ! selectDone)
|
||||
} // End of while ( ! selectDone)
|
||||
|
||||
// We do not check the CBB - it was constructed by us above.
|
||||
|
||||
@@ -681,7 +680,6 @@ byte MFRC522::PICC_HaltA() {
|
||||
// Functions for communicating with MIFARE PICCs
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Executes the MFRC522 MFAuthent command.
|
||||
* This command manages MIFARE authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card.
|
||||
@@ -694,7 +692,7 @@ byte MFRC522::PICC_HaltA() {
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you supply the wrong key.
|
||||
*/
|
||||
byte MFRC522::PCD_Authenticate(byte command, ///< PICC_CMD_AUTH_KEY_A or PICC_CMD_AUTH_KEY_B
|
||||
byte MFRC522::PCD_Authenticate(byte command, ///< PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B
|
||||
byte blockAddr, ///< The block number. See numbering in the comments in the .h file.
|
||||
MIFARE_Key *key, ///< Pointer to the Crypteo1 key to use (6 bytes)
|
||||
Uid *uid ///< Pointer to Uid struct. The first 4 bytes of the UID is used.
|
||||
@@ -741,7 +739,7 @@ void MFRC522::PCD_StopCrypto1() {
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_Read( byte blockAddr, ///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The first page to return data from.
|
||||
byte MFRC522::MIFARE_Read( byte blockAddr, ///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The first page to return data from.
|
||||
byte *buffer, ///< The buffer to store the data in
|
||||
byte *bufferSize ///< Buffer size, at least 18 bytes. Also number of bytes returned if STATUS_OK.
|
||||
) {
|
||||
@@ -753,7 +751,7 @@ byte MFRC522::PICC_Read( byte blockAddr, ///< MIFARE Classic: The block (0-0xff
|
||||
}
|
||||
|
||||
// Build command buffer
|
||||
buffer[0] = PICC_CMD_READ;
|
||||
buffer[0] = PICC_CMD_MF_READ;
|
||||
buffer[1] = blockAddr;
|
||||
// Calculate CRC_A
|
||||
result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
|
||||
@@ -763,7 +761,7 @@ byte MFRC522::PICC_Read( byte blockAddr, ///< MIFARE Classic: The block (0-0xff
|
||||
|
||||
// Transmit the buffer and receive the response, validate CRC_A.
|
||||
return PCD_TransceiveData(buffer, 4, buffer, bufferSize, NULL, 0, true);
|
||||
} // End PICC_Read()
|
||||
} // End MIFARE_Read()
|
||||
|
||||
/**
|
||||
* Writes 16 bytes to the active PICC.
|
||||
@@ -776,12 +774,11 @@ byte MFRC522::PICC_Read( byte blockAddr, ///< MIFARE Classic: The block (0-0xff
|
||||
* *
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_Write( byte blockAddr, ///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The page (2-15) to write to.
|
||||
byte *buffer, ///< The 16 bytes to write to the PICC
|
||||
byte MFRC522::MIFARE_Write( byte blockAddr, ///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The page (2-15) to write to.
|
||||
byte *buffer, ///< The 16 bytes to write to the PICC
|
||||
byte bufferSize ///< Buffer size, must be at least 16 bytes. Exactly 16 bytes are written.
|
||||
) {
|
||||
byte result;
|
||||
byte cmdBuffer[18]; // We need room for the 16 bytes and CRC_A.
|
||||
|
||||
// Sanity check
|
||||
if (buffer == NULL || bufferSize < 16) {
|
||||
@@ -790,7 +787,8 @@ byte MFRC522::PICC_Write( byte blockAddr, ///< MIFARE Classic: The block (0-0xf
|
||||
|
||||
// Mifare Classic protocol requires two communications to perform a write.
|
||||
// Step 1: Tell the PICC we want to write to block blockAddr.
|
||||
cmdBuffer[0] = PICC_CMD_WRITE;
|
||||
byte cmdBuffer[2];
|
||||
cmdBuffer[0] = PICC_CMD_MF_WRITE;
|
||||
cmdBuffer[1] = blockAddr;
|
||||
result = PCD_MIFARE_Transceive(cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
|
||||
if (result != STATUS_OK) {
|
||||
@@ -804,60 +802,90 @@ byte MFRC522::PICC_Write( byte blockAddr, ///< MIFARE Classic: The block (0-0xf
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
} // End PICC_Write()
|
||||
} // End MIFARE_Write()
|
||||
|
||||
/**
|
||||
* Writes a 4 byte page to the active MIFARE Ultralight PICC.
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::MIFARE_Ultralight_Write( byte page, ///< The page (2-15) to write to.
|
||||
byte *buffer, ///< The 4 bytes to write to the PICC
|
||||
byte bufferSize ///< Buffer size, must be at least 4 bytes. Exactly 4 bytes are written.
|
||||
) {
|
||||
byte result;
|
||||
|
||||
// Sanity check
|
||||
if (buffer == NULL || bufferSize < 4) {
|
||||
return STATUS_INVALID;
|
||||
}
|
||||
|
||||
// Build commmand buffer
|
||||
byte cmdBuffer[6];
|
||||
cmdBuffer[0] = PICC_CMD_UL_WRITE;
|
||||
cmdBuffer[1] = page;
|
||||
memcpy(&cmdBuffer[2], buffer, 4);
|
||||
|
||||
// Perform the write
|
||||
result = PCD_MIFARE_Transceive(cmdBuffer, 6); // Adds CRC_A and checks that the response is MF_ACK.
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
return STATUS_OK;
|
||||
} // End MIFARE_Ultralight_Write()
|
||||
|
||||
/**
|
||||
* MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.
|
||||
* For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
|
||||
* Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
|
||||
* Use PICC_Transfer() to store the result in a block.
|
||||
* Use MIFARE_Transfer() to store the result in a block.
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_Decrement( byte blockAddr, ///< The block (0-0xff) number.
|
||||
byte MFRC522::MIFARE_Decrement( byte blockAddr, ///< The block (0-0xff) number.
|
||||
long delta ///< This number is subtracted from the value of block blockAddr.
|
||||
) {
|
||||
return PICC_TwoStepHelper(PICC_CMD_DECREMENT, blockAddr, delta);
|
||||
} // End PICC_Decrement()
|
||||
return MIFARE_TwoStepHelper(PICC_CMD_MF_DECREMENT, blockAddr, delta);
|
||||
} // End MIFARE_Decrement()
|
||||
|
||||
/**
|
||||
* MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.
|
||||
* For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
|
||||
* Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
|
||||
* Use PICC_Transfer() to store the result in a block.
|
||||
* Use MIFARE_Transfer() to store the result in a block.
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_Increment( byte blockAddr, ///< The block (0-0xff) number.
|
||||
byte MFRC522::MIFARE_Increment( byte blockAddr, ///< The block (0-0xff) number.
|
||||
long delta ///< This number is added to the value of block blockAddr.
|
||||
) {
|
||||
return PICC_TwoStepHelper(PICC_CMD_INCREMENT, blockAddr, delta);
|
||||
} // End PICC_Increment()
|
||||
return MIFARE_TwoStepHelper(PICC_CMD_MF_INCREMENT, blockAddr, delta);
|
||||
} // End MIFARE_Increment()
|
||||
|
||||
/**
|
||||
* MIFARE Restore copies the value of the addressed block into a volatile memory.
|
||||
* For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
|
||||
* Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
|
||||
* Use PICC_Transfer() to store the result in a block.
|
||||
* Use MIFARE_Transfer() to store the result in a block.
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_Restore( byte blockAddr ///< The block (0-0xff) number.
|
||||
byte MFRC522::MIFARE_Restore( byte blockAddr ///< The block (0-0xff) number.
|
||||
) {
|
||||
// The datasheet describes Restore as a two step operation, but does not explain what data to transfer in step 2.
|
||||
// Doing only a single step does not work, so I chose to transfer 0L in step two.
|
||||
return PICC_TwoStepHelper(PICC_CMD_RESTORE, blockAddr, 0L);
|
||||
} // End PICC_Restore()
|
||||
return MIFARE_TwoStepHelper(PICC_CMD_MF_RESTORE, blockAddr, 0L);
|
||||
} // End MIFARE_Restore()
|
||||
|
||||
/**
|
||||
* Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_TwoStepHelper( byte command, ///< The command to use
|
||||
byte MFRC522::MIFARE_TwoStepHelper( byte command, ///< The command to use
|
||||
byte blockAddr, ///< The block (0-0xff) number.
|
||||
long data ///< The data to transfer in step 2
|
||||
) {
|
||||
) {
|
||||
byte result;
|
||||
byte cmdBuffer[2]; // We only need room for 2 bytes.
|
||||
|
||||
@@ -876,7 +904,7 @@ byte MFRC522::PICC_TwoStepHelper( byte command, ///< The command to use
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
} // End PICC_TwoStepHelper()
|
||||
} // End MIFARE_TwoStepHelper()
|
||||
|
||||
/**
|
||||
* MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.
|
||||
@@ -885,20 +913,20 @@ byte MFRC522::PICC_TwoStepHelper( byte command, ///< The command to use
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
byte MFRC522::PICC_Transfer( byte blockAddr ///< The block (0-0xff) number.
|
||||
byte MFRC522::MIFARE_Transfer( byte blockAddr ///< The block (0-0xff) number.
|
||||
) {
|
||||
byte result;
|
||||
byte cmdBuffer[2]; // We only need room for 2 bytes.
|
||||
|
||||
// Tell the PICC we want to transfer the result into block blockAddr.
|
||||
cmdBuffer[0] = PICC_CMD_TRANSFER;
|
||||
cmdBuffer[0] = PICC_CMD_MF_TRANSFER;
|
||||
cmdBuffer[1] = blockAddr;
|
||||
result = PCD_MIFARE_Transceive( cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
return STATUS_OK;
|
||||
} // End PICC_Transfer()
|
||||
} // End MIFARE_Transfer()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -986,33 +1014,14 @@ byte MFRC522::PICC_GetType(byte sak ///< The SAK byte returned from PICC_Select
|
||||
}
|
||||
|
||||
switch (sak) {
|
||||
case 0x09:
|
||||
return PICC_TYPE_MIFARE_MINI;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
return PICC_TYPE_MIFARE_1K;
|
||||
break;
|
||||
|
||||
case 0x18:
|
||||
return PICC_TYPE_MIFARE_4K;
|
||||
break;
|
||||
|
||||
case 0x00:
|
||||
return PICC_TYPE_MIFARE_UL;
|
||||
break;
|
||||
|
||||
case 0x09: return PICC_TYPE_MIFARE_MINI; break;
|
||||
case 0x08: return PICC_TYPE_MIFARE_1K; break;
|
||||
case 0x18: return PICC_TYPE_MIFARE_4K; break;
|
||||
case 0x00: return PICC_TYPE_MIFARE_UL; break;
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
return PICC_TYPE_MIFARE_PLUS;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
return PICC_TYPE_TNP3XXX;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case 0x11: return PICC_TYPE_MIFARE_PLUS; break;
|
||||
case 0x01: return PICC_TYPE_TNP3XXX; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (sak & 0x20) {
|
||||
@@ -1033,27 +1042,26 @@ byte MFRC522::PICC_GetType(byte sak ///< The SAK byte returned from PICC_Select
|
||||
const char *MFRC522::PICC_GetTypeName(byte piccType ///< One of the PICC_Type enums.
|
||||
) {
|
||||
switch (piccType) {
|
||||
case PICC_TYPE_ISO_14443_4: return "PICC compliant with ISO/IEC 14443-4"; break;
|
||||
case PICC_TYPE_ISO_18092: return "PICC compliant with ISO/IEC 18092 (NFC)"; break;
|
||||
case PICC_TYPE_MIFARE_MINI: return "MIFARE Mini, 320 bytes"; break;
|
||||
case PICC_TYPE_MIFARE_1K: return "MIFARE 1KB"; break;
|
||||
case PICC_TYPE_MIFARE_4K: return "MIFARE 4KB"; break;
|
||||
case PICC_TYPE_MIFARE_UL: return "MIFARE Ultralight or Ultralight C"; break;
|
||||
case PICC_TYPE_MIFARE_PLUS: return "MIFARE Plus"; break;
|
||||
case PICC_TYPE_TNP3XXX: return "MIFARE TNP3XXX"; break;
|
||||
case PICC_TYPE_NOT_COMPLETE: return "SAK indicates UID is not complete."; break;
|
||||
case PICC_TYPE_ISO_14443_4: return "PICC compliant with ISO/IEC 14443-4"; break;
|
||||
case PICC_TYPE_ISO_18092: return "PICC compliant with ISO/IEC 18092 (NFC)"; break;
|
||||
case PICC_TYPE_MIFARE_MINI: return "MIFARE Mini, 320 bytes"; break;
|
||||
case PICC_TYPE_MIFARE_1K: return "MIFARE 1KB"; break;
|
||||
case PICC_TYPE_MIFARE_4K: return "MIFARE 4KB"; break;
|
||||
case PICC_TYPE_MIFARE_UL: return "MIFARE Ultralight or Ultralight C"; break;
|
||||
case PICC_TYPE_MIFARE_PLUS: return "MIFARE Plus"; break;
|
||||
case PICC_TYPE_TNP3XXX: return "MIFARE TNP3XXX"; break;
|
||||
case PICC_TYPE_NOT_COMPLETE: return "SAK indicates UID is not complete."; break;
|
||||
case PICC_TYPE_UNKNOWN:
|
||||
default:
|
||||
return "Unknown type";
|
||||
break;
|
||||
default: return "Unknown type"; break;
|
||||
}
|
||||
} // End PICC_GetTypeName()
|
||||
|
||||
/**
|
||||
* 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(Uid *uid ///< Pointer to Uid struct returned from a successful PICC_Select().
|
||||
void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned from a successful PICC_Select().
|
||||
) {
|
||||
MIFARE_Key key;
|
||||
|
||||
@@ -1145,8 +1153,8 @@ void MFRC522::PICC_DumpMifareClassicToSerial( Uid *uid, ///< Pointer to Uid str
|
||||
|
||||
/**
|
||||
* Dumps memory contents of a sector of a MIFARE Classic PICC.
|
||||
* Uses PCD_Authenticate(), PICC_Read() and PCD_StopCrypto1.
|
||||
* Always uses PICC_CMD_AUTH_KEY_A because only Key A can always read the sector trailer access bits.
|
||||
* Uses PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1.
|
||||
* Always uses PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer access bits.
|
||||
*/
|
||||
void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to Uid struct returned from a successful PICC_Select().
|
||||
MIFARE_Key *key, ///< Key A for the sector.
|
||||
@@ -1207,7 +1215,7 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
|
||||
Serial.print(" ");
|
||||
// Establish encrypted communications before reading the first block
|
||||
if (isSectorTrailer) {
|
||||
status = PCD_Authenticate(PICC_CMD_AUTH_KEY_A, firstBlock, key, uid);
|
||||
status = PCD_Authenticate(PICC_CMD_MF_AUTH_KEY_A, firstBlock, key, uid);
|
||||
if (status != STATUS_OK) {
|
||||
Serial.print("PCD_Authenticate() failed: ");
|
||||
Serial.println(GetStatusCodeName(status));
|
||||
@@ -1216,9 +1224,9 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
|
||||
}
|
||||
// Read block
|
||||
byteCount = sizeof(buffer);
|
||||
status = PICC_Read(blockAddr, buffer, &byteCount);
|
||||
status = MIFARE_Read(blockAddr, buffer, &byteCount);
|
||||
if (status != STATUS_OK) {
|
||||
Serial.print("PICC_Read() failed: ");
|
||||
Serial.print("MIFARE_Read() failed: ");
|
||||
Serial.println(GetStatusCodeName(status));
|
||||
continue;
|
||||
}
|
||||
@@ -1289,13 +1297,13 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() {
|
||||
byte i;
|
||||
|
||||
Serial.println("Page 0 1 2 3");
|
||||
// Try reading all pages of an Ultralight C. Stop when a read fails.
|
||||
for (byte page = 0; page < 48; page +=4) { // Read returns data for 4 pages at a time.
|
||||
// Try the mpages of the original Ultralight. Ultralight C has more pages.
|
||||
for (byte page = 0; page < 16; page +=4) { // Read returns data for 4 pages at a time.
|
||||
// Read pages
|
||||
byteCount = sizeof(buffer);
|
||||
status = PICC_Read(page, buffer, &byteCount);
|
||||
status = MIFARE_Read(page, buffer, &byteCount);
|
||||
if (status != STATUS_OK) {
|
||||
Serial.print("PICC_Read() failed: ");
|
||||
Serial.print("MIFARE_Read() failed: ");
|
||||
Serial.println(GetStatusCodeName(status));
|
||||
break;
|
||||
}
|
||||
@@ -1318,7 +1326,7 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() {
|
||||
/**
|
||||
* Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tupples C1 is MSB (=4) and C3 is LSB (=1).
|
||||
*/
|
||||
void MFRC522::PICC_SetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
|
||||
void MFRC522::MIFARE_SetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
|
||||
byte g0, ///< Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
|
||||
byte g1, ///< Access bits C1 C2 C3] for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
|
||||
byte g2, ///< Access bits C1 C2 C3] for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
|
||||
@@ -1331,7 +1339,7 @@ void MFRC522::PICC_SetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6,
|
||||
accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF);
|
||||
accessBitBuffer[1] = c1 << 4 | (~c3 & 0xF);
|
||||
accessBitBuffer[2] = c3 << 4 | c2;
|
||||
} // End PICC_SetAccessBits()
|
||||
} // End MIFARE_SetAccessBits()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Convenience functions - does not add extra functionality
|
||||
@@ -1362,4 +1370,4 @@ bool MFRC522::PICC_ReadCardSerial() {
|
||||
byte result = PICC_Select(&uid);
|
||||
return (result == STATUS_OK);
|
||||
} // End PICC_ReadCardSerial()
|
||||
|
||||
|
||||
|
||||
47
MFRC522.h
47
MFRC522.h
@@ -5,6 +5,9 @@
|
||||
* Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.)
|
||||
* Released into the public domain.
|
||||
*
|
||||
* Please read this file for an overview and then MFRC522.c for comments on the specific functions.
|
||||
* Search for "mf-rc522" on ebay.com to purchase the MF-RC522 board.
|
||||
*
|
||||
* There are three hardware components involved:
|
||||
* 1) The micro controller: An Arduino
|
||||
* 2) The PCD (short for Proximity Coupling Device): NXP MFRC522 Contactless Reader IC
|
||||
@@ -57,7 +60,7 @@
|
||||
* Page 2 contains the last chech digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
|
||||
* Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
|
||||
* Pages 4-15 are read/write unless blocked by the lock bytes in page 2.
|
||||
* MIFARE Ultralight C (MF0ICUC):
|
||||
* MIFARE Ultralight C (MF0ICU2):
|
||||
* Has 48 pages of 4 bytes = 64 bytes.
|
||||
* Pages 0 + 1 is used for the 7-byte UID.
|
||||
* Page 2 contains the last chech digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
|
||||
@@ -159,7 +162,7 @@ public:
|
||||
PCD_GenerateRandomID = 0x02, // generates a 10-byte random ID number
|
||||
PCD_CalcCRC = 0x03, // activates the CRC coprocessor or performs a self test
|
||||
PCD_Transmit = 0x04, // transmits data from the FIFO buffer
|
||||
PCD_NoCmdChange = 0x07, // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
|
||||
PCD_NoCmdChange = 0x07, // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
|
||||
PCD_Receive = 0x08, // activates the receiver circuits
|
||||
PCD_Transceive = 0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
|
||||
PCD_MFAuthent = 0x0E, // performs the MIFARE standard authentication as a reader
|
||||
@@ -178,14 +181,18 @@ public:
|
||||
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
|
||||
// The commands used for MIFARE Classic (from http://www.nxp.com/documents/data_sheet/MF1S503x.pdf, Section 9)
|
||||
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
|
||||
PICC_CMD_AUTH_KEY_A = 0x60, // Perform authentication with Key A
|
||||
PICC_CMD_AUTH_KEY_B = 0x61, // Perform authentication with Key B
|
||||
PICC_CMD_READ = 0x30, // Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
|
||||
PICC_CMD_WRITE = 0xA0, // Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
|
||||
PICC_CMD_DECREMENT = 0xC0, // Decrements the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_INCREMENT = 0xC1, // Increments the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
|
||||
PICC_CMD_TRANSFER = 0xB0 // Writes the contents of the internal data register to a block.
|
||||
// The read/write commands can also be used for MIFARE Ultralight.
|
||||
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
|
||||
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
|
||||
PICC_CMD_MF_READ = 0x30, // Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
|
||||
PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
|
||||
PICC_CMD_MF_DECREMENT = 0xC0, // Decrements the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_MF_INCREMENT = 0xC1, // Increments the contents of a block and stores the result in the internal data register.
|
||||
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
|
||||
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
|
||||
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
|
||||
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
|
||||
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 byte page to the PICC.
|
||||
};
|
||||
|
||||
// MIFARE constants that does not fit anywhere else
|
||||
@@ -281,15 +288,13 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
|
||||
void PCD_StopCrypto1();
|
||||
byte PICC_Read(byte blockAddr, byte *buffer, byte *bufferSize);
|
||||
byte PICC_Write(byte blockAddr, byte *buffer, byte bufferSize);
|
||||
/*
|
||||
XXX Hvad med ultralight write/compatibility write()????
|
||||
*/
|
||||
byte PICC_Decrement(byte blockAddr, long delta);
|
||||
byte PICC_Increment(byte blockAddr, long delta);
|
||||
byte PICC_Restore(byte blockAddr);
|
||||
byte PICC_Transfer(byte blockAddr);
|
||||
byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
|
||||
byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
|
||||
byte MIFARE_Decrement(byte blockAddr, long delta);
|
||||
byte MIFARE_Increment(byte blockAddr, long delta);
|
||||
byte MIFARE_Restore(byte blockAddr);
|
||||
byte MIFARE_Transfer(byte blockAddr);
|
||||
byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Support functions
|
||||
@@ -302,7 +307,7 @@ public:
|
||||
void PICC_DumpMifareClassicToSerial(Uid *uid, byte piccType, MIFARE_Key *key);
|
||||
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
|
||||
void PICC_DumpMifareUltralightToSerial();
|
||||
void PICC_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
|
||||
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Convenience functions - does not add extra functionality
|
||||
@@ -313,7 +318,7 @@ public:
|
||||
private:
|
||||
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 PICC_TwoStepHelper(byte command, byte blockAddr, long data);
|
||||
byte MIFARE_TwoStepHelper(byte command, byte blockAddr, long data);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user