457 lines
14 KiB
C
457 lines
14 KiB
C
#include "../include/MIFARE.h"
|
||
#include "../include/READER.h"
|
||
#include "string.h"
|
||
#include "../include/READER_REG.h"
|
||
#include "../include/rfid_main.h"
|
||
#include "../rfid_hal.h"
|
||
|
||
#define ENABLE_XLOG 1
|
||
#ifdef xlog
|
||
#undef xlog
|
||
#endif
|
||
#if ENABLE_XLOG
|
||
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
|
||
#else
|
||
#define xlog(format, ...) ((void)0)
|
||
#endif
|
||
|
||
|
||
unsigned char SECTOR,BLOCK,BLOCK_NUM;
|
||
unsigned char BLOCK_DATA[16];
|
||
unsigned char KEY_A[16][6]=
|
||
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
|
||
|
||
unsigned char KEY_B[16][6]=
|
||
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
|
||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
|
||
|
||
/**
|
||
* @brief 清除Mifare卡加密认证标志。
|
||
* @details
|
||
* 在对Mifare卡进行认证(Authentication)后,芯片内部会设置一个加密标志位(BIT_CRYPTO1ON)。
|
||
* 此函数用于清除该标志,以便可以对新的扇区进行认证或执行非加密操作。
|
||
* @return 无。
|
||
*/
|
||
void Mifare_Clear_Crypto(void)
|
||
{
|
||
ModifyReg(REG_STATUS,BIT_CRYPTO1ON,RESET);
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @brief Mifare卡事件处理函数(示例)。
|
||
* @details
|
||
* 这是一个示例函数,演示了对Mifare Classic卡进行读写操作的完整流程:
|
||
* 1. 清除加密状态。
|
||
* 2. 对指定的扇区(例如扇区1)使用密钥A进行认证。
|
||
* 3. 如果认证成功,则遍历该扇区的数据块(块0到块2)。
|
||
* 4. 对每个块先执行写操作,写入16字节的0xFF。
|
||
* 5. 然后再执行读操作,将数据读回并打印。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
*/
|
||
unsigned char MIFARE_CARD_EVENT(void)
|
||
{
|
||
unsigned char result;
|
||
int i;
|
||
Mifare_Clear_Crypto();
|
||
SECTOR = 1;
|
||
//for(SECTOR = 0;SECTOR < 16; SECTOR++)
|
||
{
|
||
BLOCK_NUM = (SECTOR * 4) + BLOCK;
|
||
result = Mifare_Auth(KEY_A_M1,SECTOR,KEY_A[SECTOR],PICC_A.UID);
|
||
if(result != SUCCESS)
|
||
{
|
||
SetCW(DISABLE);
|
||
xlog("-> AUTH ERROR!\r\n");
|
||
return result;
|
||
}
|
||
|
||
xlog("-> AUTH SUCCESS!\r\n");
|
||
|
||
for(BLOCK = 0;BLOCK < 3;BLOCK++)
|
||
{
|
||
BLOCK_NUM = (SECTOR * 4) + BLOCK;
|
||
if(BLOCK_NUM == 0)
|
||
BLOCK_NUM = 1;
|
||
xlog("-> SECTOR = %02X\r\n",SECTOR);;
|
||
xlog("-> BLOCK = %02X\r\n",BLOCK);
|
||
xlog("-> BLOCK_NUM = %02X\r\n",BLOCK_NUM);
|
||
memcpy(BLOCK_DATA,"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",16);
|
||
result = Mifare_Blockwrite(BLOCK_NUM,BLOCK_DATA);
|
||
if(result != SUCCESS)
|
||
{
|
||
SetCW(DISABLE);
|
||
xlog("-> WRITE BLOCK ERROR!\r\n");
|
||
return result;
|
||
}
|
||
xlog("-> WRITE BLOCK SUCCESS!\r\n");
|
||
|
||
result = Mifare_Blockread(BLOCK_NUM,BLOCK_DATA);
|
||
if(result != SUCCESS)
|
||
{
|
||
SetCW(DISABLE);
|
||
xlog("-> READ BLOCK ERROR!\r\n");
|
||
return result;
|
||
}
|
||
|
||
xlog("-> READ BLOCK = ");
|
||
for(i=0; i<16; i++) xlog("%02X", BLOCK_DATA[i]);
|
||
xlog("\r\n");
|
||
}
|
||
}
|
||
SetCW(DISABLE);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* @brief 将6字节的Mifare密钥加载到芯片的密钥缓冲区。
|
||
* @param mifare_key [in] 指向6字节密钥数组的指针。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
* @details
|
||
* 在执行认证命令(Mifare_Auth)之前,必须先调用此函数将要使用的密钥加载到芯片内部。
|
||
*/
|
||
unsigned char Mifare_LoadKey(unsigned char *mifare_key)
|
||
{
|
||
unsigned char reg_data;
|
||
SetCommand(CMD_IDLE);
|
||
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
|
||
SetReg(REG_FIFODATA,mifare_key[0]);
|
||
SetReg(REG_FIFODATA,mifare_key[1]);
|
||
SetReg(REG_FIFODATA,mifare_key[2]);
|
||
SetReg(REG_FIFODATA,mifare_key[3]);
|
||
SetReg(REG_FIFODATA,mifare_key[4]);
|
||
SetReg(REG_FIFODATA,mifare_key[5]);
|
||
SetCommand(CMD_LOADKEY);
|
||
rfid_delay_ms(1);
|
||
GetReg(REG_COMMAND,®_data);
|
||
if((reg_data & CMD_MASK) == CMD_IDLE)
|
||
return SUCCESS;
|
||
else
|
||
return FAIL;
|
||
}
|
||
|
||
/**
|
||
* @brief 对Mifare Classic卡片的指定扇区进行认证。
|
||
* @param key_mode [in] 认证模式,`KEY_A_M1` (0) 表示使用密钥A,`KEY_B_M1` (1) 表示使用密钥B。
|
||
* @param sector [in] 要认证的扇区号 (0-15)。
|
||
* @param mifare_key [in] 指向6字节认证密钥的指针。
|
||
* @param card_uid [in] 指向4字节卡片UID的指针。
|
||
* @return 操作状态,SUCCESS表示认证成功,FAIL表示失败。
|
||
* @details
|
||
* 这是访问Mifare卡数据块之前的必要步骤。认证成功后,芯片会设置加密标志位。
|
||
*/
|
||
unsigned char Mifare_Auth(unsigned char key_mode,unsigned char sector,unsigned char *mifare_key,unsigned char *card_uid)
|
||
{
|
||
unsigned char result,reg_data;
|
||
result = Mifare_LoadKey(mifare_key);
|
||
if (result != SUCCESS)
|
||
return result;
|
||
SetCommand(CMD_IDLE);
|
||
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
|
||
if(key_mode == KEY_A_M1)
|
||
{
|
||
SetReg(REG_FIFODATA,0x60);// 0x60: Key A认证指令
|
||
ModifyReg(REG_RXTXCON,BIT_SHMODE,DISABLE);
|
||
}
|
||
if(key_mode == KEY_B_M1)
|
||
{
|
||
SetReg(REG_FIFODATA,0x61);// 0x61: Key B认证指令
|
||
ModifyReg(REG_RXTXCON,BIT_SHMODE,DISABLE);
|
||
}
|
||
|
||
SetReg(REG_FIFODATA,sector * 4);// 认证扇区的块0地址
|
||
SetReg(REG_FIFODATA,card_uid[0]);
|
||
SetReg(REG_FIFODATA,card_uid[1]);
|
||
SetReg(REG_FIFODATA,card_uid[2]);
|
||
SetReg(REG_FIFODATA,card_uid[3]);
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
|
||
SetCommand(CMD_AUTHENT);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_COMMAND,®_data);
|
||
if((reg_data & CMD_MASK) == CMD_IDLE)
|
||
{
|
||
GetReg(REG_STATUS,®_data);
|
||
if(reg_data & BIT_CRYPTO1ON)// 检查加密标志位以确认认证成功
|
||
return SUCCESS;
|
||
}
|
||
return FAIL;
|
||
}
|
||
|
||
/**
|
||
* @brief 将4字节数据格式化为Mifare值块格式并写入指定块。
|
||
* @param block [in] 目标块号。
|
||
* @param data_buff [in] 指向4字节源数据的指针。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
* @details
|
||
* Mifare值块有特定的数据格式,包含值、值的反码和地址字节。此函数会自动处理格式转换。
|
||
*/
|
||
unsigned char Mifare_Blockset(unsigned char block,unsigned char *data_buff)
|
||
{
|
||
unsigned char block_data[16],result;
|
||
// 格式化为值块
|
||
block_data[0] = data_buff[3];
|
||
block_data[1] = data_buff[2];
|
||
block_data[2] = data_buff[1];
|
||
block_data[3] = data_buff[0];
|
||
block_data[4] = ~data_buff[3];
|
||
block_data[5] = ~data_buff[2];
|
||
block_data[6] = ~data_buff[1];
|
||
block_data[7] = ~data_buff[0];
|
||
block_data[8] = data_buff[3];
|
||
block_data[9] = data_buff[2];
|
||
block_data[10] = data_buff[1];
|
||
block_data[11] = data_buff[0];
|
||
block_data[12] = block;
|
||
block_data[13] = ~block;
|
||
block_data[14] = block;
|
||
block_data[15] = ~block;
|
||
result = Mifare_Blockwrite(block,block_data);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* @brief 从Mifare卡读取一个16字节的数据块。
|
||
* @param block [in] 要读取的块号 (0x00 - 0x3F)。
|
||
* @param data_buff [out] 指向16字节缓冲区的指针,用于存储读取的数据。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
*/
|
||
unsigned char Mifare_Blockread(unsigned char block,unsigned char *data_buff)
|
||
{
|
||
unsigned char reg_data,i;
|
||
SetCommand(CMD_IDLE);
|
||
SetReg(REG_TXDATANUM,0x08);
|
||
SetReg(REG_FIFODATA,0x30);// 0x30: 读块指令
|
||
SetReg(REG_FIFODATA,block);// 块地址
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(2);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 16) // 成功时应返回16字节数据
|
||
return FAIL;
|
||
GetReg(REG_ERROR,®_data);
|
||
if(reg_data & 0x07)
|
||
return FAIL;
|
||
for(i=0;i<16;i++)
|
||
{
|
||
GetReg (REG_FIFODATA,&data_buff[i]);
|
||
}
|
||
return SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief 向Mifare卡写入一个16字节的数据块。
|
||
* @param block [in] 要写入的块号 (0x00 - 0x3F)。
|
||
* @param data_buff [in] 指向16字节数据的指针。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
*/
|
||
unsigned char Mifare_Blockwrite(unsigned char block,unsigned char *data_buff)
|
||
{
|
||
unsigned char reg_data,i;
|
||
SetCommand(CMD_IDLE);
|
||
SetReg(REG_TXDATANUM,0x08);
|
||
SetReg(REG_FIFODATA,0xA0);// 0xA0: 写块指令
|
||
SetReg(REG_FIFODATA,block);// 块地址
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1) // 接收到ACK (0x0A)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
for(i=0;i<16;i++)
|
||
{
|
||
SetReg(REG_FIFODATA,data_buff[i]);
|
||
}
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1) // 接收到ACK (0x0A)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
|
||
return SUCCESS;
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief 对Mifare卡的指定值块执行增值操作。
|
||
* @param block [in] 值块的块号。
|
||
* @param data_buff [in] 指向4字节增值数据的指针。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
*/
|
||
unsigned char Mifare_Blockinc(unsigned char block,unsigned char *data_buff)
|
||
{
|
||
unsigned char reg_data,i;
|
||
SetCommand(CMD_IDLE);
|
||
SetReg(REG_TXDATANUM,0x08);
|
||
SetReg(REG_FIFODATA,0xC1);// 0xC1: 增值指令
|
||
SetReg(REG_FIFODATA,block);// 块地址
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
for(i=0;i<4;i++)
|
||
{
|
||
SetReg(REG_FIFODATA,data_buff[i]);
|
||
}
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
|
||
return SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief 对Mifare卡的指定值块执行减值操作。
|
||
* @param block [in] 值块的块号。
|
||
* @param data_buff [in] 指向4字节减值数据的指针。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
*/
|
||
unsigned char Mifare_Blockdec(unsigned char block,unsigned char *data_buff)
|
||
{
|
||
unsigned char reg_data,i;
|
||
SetCommand(CMD_IDLE);
|
||
SetReg(REG_TXDATANUM,0x08);
|
||
SetReg(REG_FIFODATA,0xC0);// 0xC0: 减值指令
|
||
SetReg(REG_FIFODATA,block);// 块地址
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
for(i=0;i<4;i++)
|
||
{
|
||
SetReg(REG_FIFODATA,data_buff[i]);
|
||
}
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
|
||
return SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief 执行Mifare卡的传输(Transfer)命令。
|
||
* @param block [in] 块号。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
* @details
|
||
* 在对值块进行增/减值操作后,需要调用此函数将结果从内部寄存器写入到块中。
|
||
*/
|
||
unsigned char Mifare_Transfer(unsigned char block)
|
||
{
|
||
unsigned char reg_data;
|
||
SetCommand(CMD_IDLE);
|
||
SetReg(REG_TXDATANUM,0x08);
|
||
SetReg(REG_FIFODATA,0xB0);// 0xB0: Transfer指令
|
||
SetReg(REG_FIFODATA,block);// 块地址
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
|
||
return SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief 执行Mifare卡的恢复(Restore)命令。
|
||
* @param block [in] 块号。
|
||
* @return 操作状态,SUCCESS表示成功,FAIL表示失败。
|
||
* @details
|
||
* 此命令用于将一个块的内容从内部寄存器中恢复。
|
||
*/
|
||
unsigned char Mifare_Restore(unsigned char block)
|
||
{
|
||
unsigned char reg_data,i;
|
||
SetCommand(CMD_IDLE);
|
||
SetReg(REG_TXDATANUM,0x08);
|
||
SetReg(REG_FIFODATA,0xC2);// 0xC2: Restore指令
|
||
SetReg(REG_FIFODATA,block);// 块地址
|
||
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
|
||
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
for(i=0;i<4;i++)
|
||
{
|
||
SetReg(REG_FIFODATA,0);
|
||
}
|
||
SetCommand(CMD_TRANSCEIVE);
|
||
rfid_delay_ms(5);
|
||
GetReg(REG_FIFOLENGTH,®_data);
|
||
if (reg_data != 1)
|
||
return FAIL;
|
||
GetReg (REG_FIFODATA,®_data);
|
||
if(reg_data != 0x0A)
|
||
return FAIL;
|
||
return SUCCESS;
|
||
}
|