#include "../include/MIFARE.h" #include "../include/READER.h" #include "../include/READER_REG.h" #include "../include/rfid_main.h" #include "../rfid_hal.h" #define FUN_ENABLE_XLOG 1 #ifdef xlog #undef xlog #endif #if FUN_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(FUN_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(FUN_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(FUN_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(FUN_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,FUN_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,FUN_ENABLE); //Clear FIFO if(key_mode == KEY_A_M1) { SetReg(REG_FIFODATA,0x60);// 0x60: Key A认证指令 ModifyReg(REG_RXTXCON,BIT_SHMODE,FUN_DISABLE); } if(key_mode == KEY_B_M1) { SetReg(REG_FIFODATA,0x61);// 0x61: Key B认证指令 ModifyReg(REG_RXTXCON,BIT_SHMODE,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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,FUN_ENABLE); ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_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; }