Merge pull request #95 from Rotzbua/master

Style improved, keywords updated
This commit is contained in:
Miki Balboa
2015-05-06 08:36:14 -05:00
5 changed files with 376 additions and 337 deletions

View File

@@ -100,7 +100,7 @@ void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One o
if (count == 0) { if (count == 0) {
return; return;
} }
//Serial.print("Reading "); Serial.print(count); Serial.println(" bytes from register."); //Serial.print(F("Reading ")); Serial.print(count); Serial.println(F(" bytes from register."));
byte address = 0x80 | (reg & 0x7E); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3. 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. byte index = 0; // Index in values array.
digitalWrite(_chipSelectPin, LOW); // Select slave digitalWrite(_chipSelectPin, LOW); // Select slave
@@ -279,71 +279,69 @@ void MFRC522::PCD_SetAntennaGain(byte mask) {
* @return Whether or not the test passed. * @return Whether or not the test passed.
*/ */
bool MFRC522::PCD_PerformSelfTest() { bool MFRC522::PCD_PerformSelfTest() {
// This follows directly the steps outlined in 16.1.1 // This follows directly the steps outlined in 16.1.1
// 1. Perform a soft reset.
PCD_Reset();
// 1. Perform a soft reset. // 2. Clear the internal buffer by writing 25 bytes of 00h
PCD_Reset(); byte ZEROES[25] = {0x00};
PCD_SetRegisterBitMask(FIFOLevelReg, 0x80); // flush the FIFO buffer
PCD_WriteRegister(FIFODataReg, 25, ZEROES); // write 25 bytes of 00h to FIFO
PCD_WriteRegister(CommandReg, PCD_Mem); // transfer to internal buffer
// 2. Clear the internal buffer by writing 25 bytes of 00h // 3. Enable self-test
byte ZEROES[25] = {0x00}; PCD_WriteRegister(AutoTestReg, 0x09);
PCD_SetRegisterBitMask(FIFOLevelReg, 0x80); // flush the FIFO buffer
PCD_WriteRegister(FIFODataReg, 25, ZEROES); // write 25 bytes of 00h to FIFO
PCD_WriteRegister(CommandReg, PCD_Mem); // transfer to internal buffer
// 3. Enable self-test // 4. Write 00h to FIFO buffer
PCD_WriteRegister(AutoTestReg, 0x09); PCD_WriteRegister(FIFODataReg, 0x00);
// 4. Write 00h to FIFO buffer // 5. Start self-test by issuing the CalcCRC command
PCD_WriteRegister(FIFODataReg, 0x00); PCD_WriteRegister(CommandReg, PCD_CalcCRC);
// 5. Start self-test by issuing the CalcCRC command // 6. Wait for self-test to complete
PCD_WriteRegister(CommandReg, PCD_CalcCRC); word i;
byte n;
for (i = 0; i < 0xFF; i++) {
n = PCD_ReadRegister(DivIrqReg); // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved
if (n & 0x04) { // CRCIRq bit set - calculation done
break;
}
}
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO.
// 6. Wait for self-test to complete // 7. Read out resulting 64 bytes from the FIFO buffer.
word i; byte result[64];
byte n; PCD_ReadRegister(FIFODataReg, 64, result, 0);
for (i = 0; i < 0xFF; i++) {
n = PCD_ReadRegister(DivIrqReg); // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved
if (n & 0x04) { // CRCIRq bit set - calculation done
break;
}
}
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO.
// 7. Read out resulting 64 bytes from the FIFO buffer. // Auto self-test done
byte result[64]; // Reset AutoTestReg register to be 0 again. Required for normal operation.
PCD_ReadRegister(FIFODataReg, 64, result, 0); PCD_WriteRegister(AutoTestReg, 0x00);
// Auto self-test done // Determine firmware version (see section 9.3.4.8 in spec)
byte version = PCD_ReadRegister(VersionReg);
// Reset AutoTestReg register to be 0 again. Required for normal operation. // Pick the appropriate reference values
PCD_WriteRegister(AutoTestReg, 0x00); const byte *reference;
switch (version) {
case 0x91: // Version 1.0
reference = MFRC522_firmware_referenceV1_0;
break;
case 0x92: // Version 2.0
reference = MFRC522_firmware_referenceV2_0;
break;
default: // Unknown version
return false;
}
// Determine firmware version (see section 9.3.4.8 in spec) // Verify that the results match up to our expectations
byte version = PCD_ReadRegister(VersionReg); for (i = 0; i < 64; i++) {
if (result[i] != pgm_read_byte(&(reference[i]))) {
return false;
}
}
// Pick the appropriate reference values // Test passed; all is good.
const byte *reference; return true;
switch (version) {
case 0x91: // Version 1.0
reference = MFRC522_firmware_referenceV1_0;
break;
case 0x92: // Version 2.0
reference = MFRC522_firmware_referenceV2_0;
break;
default: // Unknown version
return false;
}
// Verify that the results match up to our expectations
for (i = 0; i < 64; i++) {
if (result[i] != pgm_read_byte(&(reference[i]))) {
return false;
}
}
// Test passed; all is good.
return true;
} // End PCD_PerformSelfTest() } // End PCD_PerformSelfTest()
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
@@ -389,7 +387,7 @@ byte MFRC522::PCD_CommunicateWithPICC( byte command, ///< The command to execut
// Prepare values for BitFramingReg // Prepare values for BitFramingReg
byte txLastBits = validBits ? *validBits : 0; byte txLastBits = validBits ? *validBits : 0;
byte bitFraming = (rxAlign << 4) + txLastBits; // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0] byte bitFraming = (rxAlign << 4) + txLastBits; // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command. PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command.
PCD_WriteRegister(ComIrqReg, 0x7F); // Clear all seven interrupt request bits PCD_WriteRegister(ComIrqReg, 0x7F); // Clear all seven interrupt request bits
@@ -542,7 +540,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
bool uidComplete; bool uidComplete;
bool selectDone; bool selectDone;
bool useCascadeTag; bool useCascadeTag;
byte cascadeLevel = 1; byte cascadeLevel = 1;
byte result; byte result;
byte count; byte count;
byte index; byte index;
@@ -587,7 +585,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
// Repeat Cascade Level loop until we have a complete UID. // Repeat Cascade Level loop until we have a complete UID.
uidComplete = false; uidComplete = false;
while ( ! uidComplete) { while (!uidComplete) {
// Set the Cascade Level in the SEL byte, find out if we need to use the Cascade Tag in byte 2. // Set the Cascade Level in the SEL byte, find out if we need to use the Cascade Tag in byte 2.
switch (cascadeLevel) { switch (cascadeLevel) {
case 1: case 1:
@@ -640,10 +638,10 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
// Repeat anti collision loop until we can transmit all UID bits + BCC and receive a SAK - max 32 iterations. // Repeat anti collision loop until we can transmit all UID bits + BCC and receive a SAK - max 32 iterations.
selectDone = false; selectDone = false;
while ( ! selectDone) { while (!selectDone) {
// Find out how many bits and bytes to send and receive. // Find out how many bits and bytes to send and receive.
if (currentLevelKnownBits >= 32) { // All UID bits in this Cascade Level are known. This is a SELECT. if (currentLevelKnownBits >= 32) { // All UID bits in this Cascade Level are known. This is a SELECT.
//Serial.print("SELECT: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC); //Serial.print(F("SELECT: currentLevelKnownBits=")); Serial.println(currentLevelKnownBits, DEC);
buffer[1] = 0x70; // NVB - Number of Valid Bits: Seven whole bytes buffer[1] = 0x70; // NVB - Number of Valid Bits: Seven whole bytes
// Calculate BCC - Block Check Character // Calculate BCC - Block Check Character
buffer[6] = buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5]; buffer[6] = buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5];
@@ -659,7 +657,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
responseLength = 3; responseLength = 3;
} }
else { // This is an ANTICOLLISION. else { // This is an ANTICOLLISION.
//Serial.print("ANTICOLLISION: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC); //Serial.print(F("ANTICOLLISION: currentLevelKnownBits=")); Serial.println(currentLevelKnownBits, DEC);
txLastBits = currentLevelKnownBits % 8; txLastBits = currentLevelKnownBits % 8;
count = currentLevelKnownBits / 8; // Number of whole bytes in the UID part. count = currentLevelKnownBits / 8; // Number of whole bytes in the UID part.
index = 2 + count; // Number of whole bytes: SEL + NVB + UIDs index = 2 + count; // Number of whole bytes: SEL + NVB + UIDs
@@ -708,7 +706,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
// Run loop again to do the SELECT. // 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. // We do not check the CBB - it was constructed by us above.
@@ -720,7 +718,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
} }
// Check response SAK (Select Acknowledge) // Check response SAK (Select Acknowledge)
if (responseLength != 3 || txLastBits != 0) { // SAK must be exactly 24 bits (1 byte + CRC_A). if (responseLength != 3 || txLastBits != 0) { // SAK must be exactly 24 bits (1 byte + CRC_A).
return STATUS_ERROR; return STATUS_ERROR;
} }
// Verify CRC_A - do our own calculation and store the control in buffer[2..3] - those bytes are not needed anymore. // Verify CRC_A - do our own calculation and store the control in buffer[2..3] - those bytes are not needed anymore.
@@ -738,7 +736,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
uidComplete = true; uidComplete = true;
uid->sak = responseBuffer[0]; uid->sak = responseBuffer[0];
} }
} // End of while ( ! uidComplete) } // End of while (!uidComplete)
// Set correct uid->size // Set correct uid->size
uid->size = 3 * cascadeLevel + 1; uid->size = 3 * cascadeLevel + 1;
@@ -900,7 +898,7 @@ byte MFRC522::MIFARE_Write( byte blockAddr, ///< MIFARE Classic: The block (0-0x
} }
// Step 2: Transfer the data // Step 2: Transfer the data
result = PCD_MIFARE_Transceive( buffer, bufferSize); // Adds CRC_A and checks that the response is MF_ACK. result = PCD_MIFARE_Transceive(buffer, bufferSize); // Adds CRC_A and checks that the response is MF_ACK.
if (result != STATUS_OK) { if (result != STATUS_OK) {
return result; return result;
} }
@@ -1044,17 +1042,17 @@ byte MFRC522::MIFARE_Transfer( byte blockAddr ///< The block (0-0xff) number.
* @return STATUS_OK on success, STATUS_??? otherwise. * @return STATUS_OK on success, STATUS_??? otherwise.
*/ */
byte MFRC522::MIFARE_GetValue(byte blockAddr, long *value) { byte MFRC522::MIFARE_GetValue(byte blockAddr, long *value) {
byte status; byte status;
byte buffer[18]; byte buffer[18];
byte size = sizeof(buffer); byte size = sizeof(buffer);
// Read the block // Read the block
status = MIFARE_Read(blockAddr, buffer, &size); status = MIFARE_Read(blockAddr, buffer, &size);
if (status == STATUS_OK) { if (status == STATUS_OK) {
// Extract the value // Extract the value
*value = (long(buffer[3])<<24) | (long(buffer[2])<<16) | (long(buffer[1])<<8) | long(buffer[0]); *value = (long(buffer[3])<<24) | (long(buffer[2])<<16) | (long(buffer[1])<<8) | long(buffer[0]);
} }
return status; return status;
} // End MIFARE_GetValue() } // End MIFARE_GetValue()
/** /**
@@ -1069,24 +1067,24 @@ byte MFRC522::MIFARE_GetValue(byte blockAddr, long *value) {
* @return STATUS_OK on success, STATUS_??? otherwise. * @return STATUS_OK on success, STATUS_??? otherwise.
*/ */
byte MFRC522::MIFARE_SetValue(byte blockAddr, long value) { byte MFRC522::MIFARE_SetValue(byte blockAddr, long value) {
byte buffer[18]; byte buffer[18];
// Translate the long into 4 bytes; repeated 2x in value block // Translate the long into 4 bytes; repeated 2x in value block
buffer[0] = buffer[ 8] = (value & 0xFF); buffer[0] = buffer[ 8] = (value & 0xFF);
buffer[1] = buffer[ 9] = (value & 0xFF00) >> 8; buffer[1] = buffer[ 9] = (value & 0xFF00) >> 8;
buffer[2] = buffer[10] = (value & 0xFF0000) >> 16; buffer[2] = buffer[10] = (value & 0xFF0000) >> 16;
buffer[3] = buffer[11] = (value & 0xFF000000) >> 24; buffer[3] = buffer[11] = (value & 0xFF000000) >> 24;
// Inverse 4 bytes also found in value block // Inverse 4 bytes also found in value block
buffer[4] = ~buffer[0]; buffer[4] = ~buffer[0];
buffer[5] = ~buffer[1]; buffer[5] = ~buffer[1];
buffer[6] = ~buffer[2]; buffer[6] = ~buffer[2];
buffer[7] = ~buffer[3]; buffer[7] = ~buffer[3];
// Address 2x with inverse address 2x // Address 2x with inverse address 2x
buffer[12] = buffer[14] = blockAddr; buffer[12] = buffer[14] = blockAddr;
buffer[13] = buffer[15] = ~blockAddr; buffer[13] = buffer[15] = ~blockAddr;
// Write the whole data block // Write the whole data block
return MIFARE_Write(blockAddr, buffer, 16); return MIFARE_Write(blockAddr, buffer, 16);
} // End MIFARE_SetValue() } // End MIFARE_SetValue()
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
@@ -1226,7 +1224,10 @@ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned fro
// UID // UID
Serial.print(F("Card UID:")); Serial.print(F("Card UID:"));
for (byte i = 0; i < uid->size; i++) { for (byte i = 0; i < uid->size; i++) {
Serial.print(uid->uidByte[i] < 0x10 ? " 0" : " "); if(uid->uidByte[i] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(uid->uidByte[i], HEX); Serial.print(uid->uidByte[i], HEX);
} }
Serial.println(); Serial.println();
@@ -1360,7 +1361,10 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
blockAddr = firstBlock + blockOffset; blockAddr = firstBlock + blockOffset;
// Sector number - only on first line // Sector number - only on first line
if (isSectorTrailer) { if (isSectorTrailer) {
Serial.print(sector < 10 ? " " : " "); // Pad with spaces if(sector < 10)
Serial.print(F(" ")); // Pad with spaces
else
Serial.print(F(" ")); // Pad with spaces
Serial.print(sector); Serial.print(sector);
Serial.print(F(" ")); Serial.print(F(" "));
} }
@@ -1368,7 +1372,14 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
Serial.print(F(" ")); Serial.print(F(" "));
} }
// Block number // Block number
Serial.print(blockAddr < 10 ? " " : (blockAddr < 100 ? " " : " ")); // Pad with spaces if(blockAddr < 10)
Serial.print(F(" ")); // Pad with spaces
else {
if(blockAddr < 100)
Serial.print(F(" ")); // Pad with spaces
else
Serial.print(F(" ")); // Pad with spaces
}
Serial.print(blockAddr); Serial.print(blockAddr);
Serial.print(F(" ")); Serial.print(F(" "));
// Establish encrypted communications before reading the first block // Establish encrypted communications before reading the first block
@@ -1390,7 +1401,10 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
} }
// Dump data // Dump data
for (byte index = 0; index < 16; index++) { for (byte index = 0; index < 16; index++) {
Serial.print(buffer[index] < 0x10 ? " 0" : " "); if(buffer[index] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(buffer[index], HEX); Serial.print(buffer[index], HEX);
if ((index % 4) == 3) { if ((index % 4) == 3) {
Serial.print(F(" ")); Serial.print(F(" "));
@@ -1425,8 +1439,8 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
if (firstInGroup) { if (firstInGroup) {
// Print access bits // Print access bits
Serial.print(F(" [ ")); Serial.print(F(" [ "));
Serial.print((g[group] >> 2) & 1, DEC); Serial.print(" "); Serial.print((g[group] >> 2) & 1, DEC); Serial.print(F(" "));
Serial.print((g[group] >> 1) & 1, DEC); Serial.print(" "); Serial.print((g[group] >> 1) & 1, DEC); Serial.print(F(" "));
Serial.print((g[group] >> 0) & 1, DEC); Serial.print((g[group] >> 0) & 1, DEC);
Serial.print(F(" ] ")); Serial.print(F(" ] "));
if (invertedError) { if (invertedError) {
@@ -1468,12 +1482,18 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() {
// Dump data // Dump data
for (byte offset = 0; offset < 4; offset++) { for (byte offset = 0; offset < 4; offset++) {
i = page + offset; i = page + offset;
Serial.print(i < 10 ? " " : " "); // Pad with spaces if(i < 10)
Serial.print(F(" ")); // Pad with spaces
else
Serial.print(F(" ")); // Pad with spaces
Serial.print(i); Serial.print(i);
Serial.print(F(" ")); Serial.print(F(" "));
for (byte index = 0; index < 4; index++) { for (byte index = 0; index < 4; index++) {
i = 4 * offset + index; i = 4 * offset + index;
Serial.print(buffer[i] < 0x10 ? " 0" : " "); if(buffer[i] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(buffer[i], HEX); Serial.print(buffer[i], HEX);
} }
Serial.println(); Serial.println();
@@ -1512,65 +1532,65 @@ void MFRC522::MIFARE_SetAccessBits( byte *accessBitBuffer, ///< Pointer to byte
* Of course with non-bricked devices, you're free to select them before calling this function. * Of course with non-bricked devices, you're free to select them before calling this function.
*/ */
bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) { bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) {
// Magic sequence: // Magic sequence:
// > 50 00 57 CD (HALT + CRC) // > 50 00 57 CD (HALT + CRC)
// > 40 (7 bits only) // > 40 (7 bits only)
// < A (4 bits only) // < A (4 bits only)
// > 43 // > 43
// < A (4 bits only) // < A (4 bits only)
// Then you can write to sector 0 without authenticating // Then you can write to sector 0 without authenticating
PICC_HaltA(); // 50 00 57 CD PICC_HaltA(); // 50 00 57 CD
byte cmd = 0x40; byte cmd = 0x40;
byte validBits = 7; /* Our command is only 7 bits. After receiving card response, byte validBits = 7; /* Our command is only 7 bits. After receiving card response,
this will contain amount of valid response bits. */ this will contain amount of valid response bits. */
byte response[32]; // Card's response is written here byte response[32]; // Card's response is written here
byte received; byte received;
byte status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 40 byte status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 40
if( status != STATUS_OK ) { if(status != STATUS_OK) {
if( logErrors ) { if(logErrors) {
Serial.println(F("Card did not respond to 0x40 after HALT command. Are you sure it is a UID changeable one?")); Serial.println(F("Card did not respond to 0x40 after HALT command. Are you sure it is a UID changeable one?"));
Serial.print(F("Error name: ")); Serial.print(F("Error name: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;
} }
if ( received != 1 || response[0] != 0x0A ) { if (received != 1 || response[0] != 0x0A) {
if ( logErrors ) { if (logErrors) {
Serial.print(F("Got bad response on backdoor 0x40 command: ")); Serial.print(F("Got bad response on backdoor 0x40 command: "));
Serial.print(response[0], HEX); Serial.print(response[0], HEX);
Serial.print(F(" (")); Serial.print(F(" ("));
Serial.print(validBits); Serial.print(validBits);
Serial.print(F(" valid bits)\r\n")); Serial.print(F(" valid bits)\r\n"));
} }
return false; return false;
} }
cmd = 0x43; cmd = 0x43;
validBits = 8; validBits = 8;
status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 43 status = PCD_TransceiveData(&cmd, (byte)1, response, &received, &validBits, (byte)0, false); // 43
if( status != STATUS_OK ) { if(status != STATUS_OK) {
if( logErrors ) { if(logErrors) {
Serial.println(F("Error in communication at command 0x43, after successfully executing 0x40")); Serial.println(F("Error in communication at command 0x43, after successfully executing 0x40"));
Serial.print(F("Error name: ")); Serial.print(F("Error name: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;
} }
if ( received != 1 || response[0] != 0x0A ) { if (received != 1 || response[0] != 0x0A) {
if ( logErrors ) { if (logErrors) {
Serial.print(F("Got bad response on backdoor 0x43 command: ")); Serial.print(F("Got bad response on backdoor 0x43 command: "));
Serial.print(response[0], HEX); Serial.print(response[0], HEX);
Serial.print(F(" (")); Serial.print(F(" ("));
Serial.print(validBits); Serial.print(validBits);
Serial.print(F(" valid bits)\r\n")); Serial.print(F(" valid bits)\r\n"));
} }
return false; return false;
} }
// You can now write to sector 0 without authenticating! // You can now write to sector 0 without authenticating!
return true; return true;
} // End MIFARE_OpenUidBackdoor() } // End MIFARE_OpenUidBackdoor()
/** /**
@@ -1581,122 +1601,122 @@ bool MFRC522::MIFARE_OpenUidBackdoor(bool logErrors) {
* It assumes a default KEY A of 0xFFFFFFFFFFFF. * It assumes a default KEY A of 0xFFFFFFFFFFFF.
* Make sure to have selected the card before this function is called. * Make sure to have selected the card before this function is called.
*/ */
bool MFRC522::MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors) { bool MFRC522::MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors) {
// UID + BCC byte can not be larger than 16 together // UID + BCC byte can not be larger than 16 together
if ( !newUid || !uidSize || uidSize > 15) { if (!newUid || !uidSize || uidSize > 15) {
if ( logErrors ) { if (logErrors) {
Serial.println(F("New UID buffer empty, size 0, or size > 15 given")); Serial.println(F("New UID buffer empty, size 0, or size > 15 given"));
} }
return false; return false;
} }
// Authenticate for reading // Authenticate for reading
MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; MIFARE_Key key = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
byte status = PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, (byte)1, &key, &uid); byte status = PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, (byte)1, &key, &uid);
if ( status != STATUS_OK ) { if (status != STATUS_OK) {
if ( status == STATUS_TIMEOUT ) { if (status == STATUS_TIMEOUT) {
// We get a read timeout if no card is selected yet, so let's select one // We get a read timeout if no card is selected yet, so let's select one
// Wake the card up again if sleeping // Wake the card up again if sleeping
// byte atqa_answer[2]; // byte atqa_answer[2];
// byte atqa_size = 2; // byte atqa_size = 2;
// PICC_WakeupA(atqa_answer, &atqa_size); // PICC_WakeupA(atqa_answer, &atqa_size);
if ( !PICC_IsNewCardPresent() || !PICC_ReadCardSerial() ) { if (!PICC_IsNewCardPresent() || !PICC_ReadCardSerial()) {
Serial.println(F("No card was previously selected, and none are available. Failed to set UID.")); Serial.println(F("No card was previously selected, and none are available. Failed to set UID."));
return false; return false;
} }
status = PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, (byte)1, &key, &uid); status = PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, (byte)1, &key, &uid);
if ( status != STATUS_OK ) { if (status != STATUS_OK) {
// We tried, time to give up // We tried, time to give up
if ( logErrors ) { if (logErrors) {
Serial.println(F("Failed to authenticate to card for reading, could not set UID: ")); Serial.println(F("Failed to authenticate to card for reading, could not set UID: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;
} }
} }
else { else {
if ( logErrors ) { if (logErrors) {
Serial.print(F("PCD_Authenticate() failed: ")); Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;
} }
} }
// Read block 0 // Read block 0
byte block0_buffer[18]; byte block0_buffer[18];
byte byteCount = sizeof(block0_buffer); byte byteCount = sizeof(block0_buffer);
status = MIFARE_Read((byte)0, block0_buffer, &byteCount); status = MIFARE_Read((byte)0, block0_buffer, &byteCount);
if ( status != STATUS_OK ) { if (status != STATUS_OK) {
if ( logErrors ) { if (logErrors) {
Serial.print(F("MIFARE_Read() failed: ")); Serial.print(F("MIFARE_Read() failed: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
Serial.println(F("Are you sure your KEY A for sector 0 is 0xFFFFFFFFFFFF?")); Serial.println(F("Are you sure your KEY A for sector 0 is 0xFFFFFFFFFFFF?"));
} }
return false; return false;
} }
// Write new UID to the data we just read, and calculate BCC byte // Write new UID to the data we just read, and calculate BCC byte
byte bcc = 0; byte bcc = 0;
for ( int i = 0; i < uidSize; i++ ) { for (int i = 0; i < uidSize; i++) {
block0_buffer[i] = newUid[i]; block0_buffer[i] = newUid[i];
bcc ^= newUid[i]; bcc ^= newUid[i];
} }
// Write BCC byte to buffer // Write BCC byte to buffer
block0_buffer[uidSize] = bcc; block0_buffer[uidSize] = bcc;
// Stop encrypted traffic so we can send raw bytes // Stop encrypted traffic so we can send raw bytes
PCD_StopCrypto1(); PCD_StopCrypto1();
// Activate UID backdoor // Activate UID backdoor
if ( !MIFARE_OpenUidBackdoor(logErrors) ) { if (!MIFARE_OpenUidBackdoor(logErrors)) {
if ( logErrors ) { if (logErrors) {
Serial.println(F("Activating the UID backdoor failed.")); Serial.println(F("Activating the UID backdoor failed."));
} }
return false; return false;
} }
// Write modified block 0 back to card // Write modified block 0 back to card
status = MIFARE_Write((byte)0, block0_buffer, (byte)16); status = MIFARE_Write((byte)0, block0_buffer, (byte)16);
if (status != STATUS_OK) { if (status != STATUS_OK) {
if ( logErrors ) { if (logErrors) {
Serial.print(F("MIFARE_Write() failed: ")); Serial.print(F("MIFARE_Write() failed: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;
} }
// Wake the card up again // Wake the card up again
byte atqa_answer[2]; byte atqa_answer[2];
byte atqa_size = 2; byte atqa_size = 2;
PICC_WakeupA(atqa_answer, &atqa_size); PICC_WakeupA(atqa_answer, &atqa_size);
return true; return true;
} }
/** /**
* Resets entire sector 0 to zeroes, so the card can be read again by readers. * Resets entire sector 0 to zeroes, so the card can be read again by readers.
*/ */
bool MFRC522::MIFARE_UnbrickUidSector(bool logErrors) { bool MFRC522::MIFARE_UnbrickUidSector(bool logErrors) {
MIFARE_OpenUidBackdoor( logErrors ); MIFARE_OpenUidBackdoor(logErrors);
byte block0_buffer[] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; byte block0_buffer[] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// Write modified block 0 back to card // Write modified block 0 back to card
byte status = MIFARE_Write((byte)0, block0_buffer, (byte)16); byte status = MIFARE_Write((byte)0, block0_buffer, (byte)16);
if (status != STATUS_OK) { if (status != STATUS_OK) {
if ( logErrors ) { if (logErrors) {
Serial.print(F("MIFARE_Write() failed: ")); Serial.print(F("MIFARE_Write() failed: "));
Serial.println(GetStatusCodeName(status)); Serial.println(GetStatusCodeName(status));
} }
return false; return false;
} }
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////

View File

@@ -40,7 +40,7 @@
* Bytes 6-8: Access Bits * Bytes 6-8: Access Bits
* Bytes 9: User data * Bytes 9: User data
* Bytes 10-15: Key B (or user data) * Bytes 10-15: Key B (or user data)
* Block 0 is read only manufacturer data. * Block 0 is read-only manufacturer data.
* To access a block, an authentication using a key from the block's sector must be performed first. * To access a block, an authentication using a key from the block's sector must be performed first.
* Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11). * Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11).
* All keys are set to FFFFFFFFFFFFh at chip delivery. * All keys are set to FFFFFFFFFFFFh at chip delivery.
@@ -218,8 +218,8 @@ public:
PICC_CMD_WUPA = 0x52, // 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. PICC_CMD_WUPA = 0x52, // 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.
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision. PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1 PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 1 PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 1 PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT. 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) // 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. // Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
@@ -315,14 +315,13 @@ public:
void PCD_AntennaOff(); void PCD_AntennaOff();
byte PCD_GetAntennaGain(); byte PCD_GetAntennaGain();
void PCD_SetAntennaGain(byte mask); void PCD_SetAntennaGain(byte mask);
bool PCD_PerformSelfTest(); bool PCD_PerformSelfTest();
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with PICCs // Functions for communicating with PICCs
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
byte PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false); byte PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);
byte PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false); byte PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);
byte PICC_RequestA(byte *bufferATQA, byte *bufferSize); byte PICC_RequestA(byte *bufferATQA, byte *bufferSize);
byte PICC_WakeupA(byte *bufferATQA, byte *bufferSize); byte PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
byte PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize); byte PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
@@ -336,13 +335,13 @@ public:
void PCD_StopCrypto1(); void PCD_StopCrypto1();
byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize); byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize); byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
byte MIFARE_Decrement(byte blockAddr, long delta); byte MIFARE_Decrement(byte blockAddr, long delta);
byte MIFARE_Increment(byte blockAddr, long delta); byte MIFARE_Increment(byte blockAddr, long delta);
byte MIFARE_Restore(byte blockAddr); byte MIFARE_Restore(byte blockAddr);
byte MIFARE_Transfer(byte blockAddr); byte MIFARE_Transfer(byte blockAddr);
byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize); byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
byte MIFARE_GetValue(byte blockAddr, long *value); byte MIFARE_GetValue(byte blockAddr, long *value);
byte MIFARE_SetValue(byte blockAddr, long value); byte MIFARE_SetValue(byte blockAddr, long value);
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Support functions // Support functions
@@ -360,9 +359,9 @@ public:
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 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);
bool MIFARE_OpenUidBackdoor(bool logErrors); bool MIFARE_OpenUidBackdoor(bool logErrors);
bool MIFARE_SetUid(byte* newUid, byte uidSize, bool logErrors); bool MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors);
bool MIFARE_UnbrickUidSector(bool logErrors); bool MIFARE_UnbrickUidSector(bool logErrors);
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Convenience functions - does not add extra functionality // Convenience functions - does not add extra functionality

View File

@@ -82,13 +82,14 @@ Protocols
2. The reader and the tags communicate using a 13.56 MHz electromagnetic field. 2. The reader and the tags communicate using a 13.56 MHz electromagnetic field.
* The protocol is defined in ISO/IEC 14443-3:2011 Part 3. * The protocol is defined in ISO/IEC 14443-3:2011 Part 3 Type A.
* Details are found in chapter 6 *"Type A Initialization and anticollision"*. * Details are found in chapter 6 *"Type A Initialization and anticollision"*.
* See http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf for a free version * See http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf for a free version
of the final draft (which might be outdated in some areas). of the final draft (which might be outdated in some areas).
* The reader do not support ISO/IEC 14443-3 Type B.
License License
------- -------

BIN
doc/rfidmifare.pdf Normal file

Binary file not shown.

View File

@@ -19,7 +19,10 @@ MIFARE_Key KEYWORD1
####################################### #######################################
# KEYWORD2 Methods and functions # KEYWORD2 Methods and functions
####################################### #######################################
# Functions for setting up the Arduino
setSPIConfig KEYWORD2 setSPIConfig KEYWORD2
# Basic interface functions for communicating with the MFRC522
PCD_WriteRegister KEYWORD2 PCD_WriteRegister KEYWORD2
PCD_WriteRegister KEYWORD2 PCD_WriteRegister KEYWORD2
PCD_ReadRegister KEYWORD2 PCD_ReadRegister KEYWORD2
@@ -28,12 +31,17 @@ setBitMask KEYWORD2
PCD_SetRegisterBitMask KEYWORD2 PCD_SetRegisterBitMask KEYWORD2
PCD_ClearRegisterBitMask KEYWORD2 PCD_ClearRegisterBitMask KEYWORD2
PCD_CalculateCRC KEYWORD2 PCD_CalculateCRC KEYWORD2
# Functions for manipulating the MFRC522
PCD_Init KEYWORD2 PCD_Init KEYWORD2
PCD_Reset KEYWORD2 PCD_Reset KEYWORD2
PCD_AntennaOn KEYWORD2 PCD_AntennaOn KEYWORD2
PCD_AntennaOff KEYWORD2 PCD_AntennaOff KEYWORD2
PCD_GetAntennaGain KEYWORD2 PCD_GetAntennaGain KEYWORD2
PCD_SetAntennaGain KEYWORD2 PCD_SetAntennaGain KEYWORD2
PCD_PerformSelfTest KEYWORD2
# Functions for communicating with PICCs
PCD_TransceiveData KEYWORD2 PCD_TransceiveData KEYWORD2
PCD_CommunicateWithPICC KEYWORD2 PCD_CommunicateWithPICC KEYWORD2
PICC_RequestA KEYWORD2 PICC_RequestA KEYWORD2
@@ -41,6 +49,8 @@ PICC_WakeupA KEYWORD2
PICC_REQA_or_WUPA KEYWORD2 PICC_REQA_or_WUPA KEYWORD2
PICC_Select KEYWORD2 PICC_Select KEYWORD2
PICC_HaltA KEYWORD2 PICC_HaltA KEYWORD2
# Functions for communicating with MIFARE PICCs
PCD_Authenticate KEYWORD2 PCD_Authenticate KEYWORD2
PCD_StopCrypto1 KEYWORD2 PCD_StopCrypto1 KEYWORD2
MIFARE_Read KEYWORD2 MIFARE_Read KEYWORD2
@@ -49,13 +59,22 @@ MIFARE_Increment KEYWORD2
MIFARE_Ultralight_Write KEYWORD2 MIFARE_Ultralight_Write KEYWORD2
MIFARE_GetValue KEYWORD2 MIFARE_GetValue KEYWORD2
MIFARE_SetValue KEYWORD2 MIFARE_SetValue KEYWORD2
# Support functions
PCD_MIFARE_Transceive KEYWORD2 PCD_MIFARE_Transceive KEYWORD2
GetStatusCodeName KEYWORD2
PICC_GetType KEYWORD2 PICC_GetType KEYWORD2
PICC_GetTypeName KEYWORD2
PICC_DumpToSerial KEYWORD2 PICC_DumpToSerial KEYWORD2
PICC_DumpMifareClassicToSerial KEYWORD2 PICC_DumpMifareClassicToSerial KEYWORD2
PICC_DumpMifareClassicSectorToSerial KEYWORD2 PICC_DumpMifareClassicSectorToSerial KEYWORD2
PICC_DumpMifareUltralightToSerial KEYWORD2 PICC_DumpMifareUltralightToSerial KEYWORD2
MIFARE_SetAccessBits KEYWORD2 MIFARE_SetAccessBits KEYWORD2
MIFARE_OpenUidBackdoor KEYWORD2
MIFARE_SetUid KEYWORD2
MIFARE_UnbrickUidSector KEYWORD2
# Convenience functions - does not add extra functionality
PICC_IsNewCardPresent KEYWORD2 PICC_IsNewCardPresent KEYWORD2
PICC_ReadCardSerial KEYWORD2 PICC_ReadCardSerial KEYWORD2