diff --git a/Firmware/Chameleon-Mini/Application/Crypto1.c b/Firmware/Chameleon-Mini/Application/Crypto1.c index 4fc1a0d..21d7891 100644 --- a/Firmware/Chameleon-Mini/Application/Crypto1.c +++ b/Firmware/Chameleon-Mini/Application/Crypto1.c @@ -293,26 +293,26 @@ static const uint8_t TableC0[32] = { static const uint8_t TableC7[32] = { /* fc with Input {4,3,2,1,0} = (0,0,0,0,0) to (1,1,1,1,1) */ FC(0, 0, 0, 0, 0) << 7, FC(0, 0, 0, 0, 1) << 7, FC(0, 0, 0, 1, 0) << 7, FC(0, 0, 0, 1, 1) << 7, - FC(0, 0, 1, 0, 0) << 7, FC(0, 0, 1, 0, 1) << 7, FC(0, 0, 1, 1, 0) << 7, FC(0, 0, 1, 1, 1) << 7, - FC(0, 1, 0, 0, 0) << 7, FC(0, 1, 0, 0, 1) << 7, FC(0, 1, 0, 1, 0) << 7, FC(0, 1, 0, 1, 1) << 7, - FC(0, 1, 1, 0, 0) << 7, FC(0, 1, 1, 0, 1) << 7, FC(0, 1, 1, 1, 0) << 7, FC(0, 1, 1, 1, 1) << 7, - FC(1, 0, 0, 0, 0) << 7, FC(1, 0, 0, 0, 1) << 7, FC(1, 0, 0, 1, 0) << 7, FC(1, 0, 0, 1, 1) << 7, - FC(1, 0, 1, 0, 0) << 7, FC(1, 0, 1, 0, 1) << 7, FC(1, 0, 1, 1, 0) << 7, FC(1, 0, 1, 1, 1) << 7, - FC(1, 1, 0, 0, 0) << 7, FC(1, 1, 0, 0, 1) << 7, FC(1, 1, 0, 1, 0) << 7, FC(1, 1, 0, 1, 1) << 7, - FC(1, 1, 1, 0, 0) << 7, FC(1, 1, 1, 0, 1) << 7, FC(1, 1, 1, 1, 0) << 7, FC(1, 1, 1, 1, 1) << 7 + FC(0, 0, 1, 0, 0) << 7, FC(0, 0, 1, 0, 1) << 7, FC(0, 0, 1, 1, 0) << 7, FC(0, 0, 1, 1, 1) << 7, + FC(0, 1, 0, 0, 0) << 7, FC(0, 1, 0, 0, 1) << 7, FC(0, 1, 0, 1, 0) << 7, FC(0, 1, 0, 1, 1) << 7, + FC(0, 1, 1, 0, 0) << 7, FC(0, 1, 1, 0, 1) << 7, FC(0, 1, 1, 1, 0) << 7, FC(0, 1, 1, 1, 1) << 7, + FC(1, 0, 0, 0, 0) << 7, FC(1, 0, 0, 0, 1) << 7, FC(1, 0, 0, 1, 0) << 7, FC(1, 0, 0, 1, 1) << 7, + FC(1, 0, 1, 0, 0) << 7, FC(1, 0, 1, 0, 1) << 7, FC(1, 0, 1, 1, 0) << 7, FC(1, 0, 1, 1, 1) << 7, + FC(1, 1, 0, 0, 0) << 7, FC(1, 1, 0, 0, 1) << 7, FC(1, 1, 0, 1, 0) << 7, FC(1, 1, 0, 1, 1) << 7, + FC(1, 1, 1, 0, 0) << 7, FC(1, 1, 1, 0, 1) << 7, FC(1, 1, 1, 1, 0) << 7, FC(1, 1, 1, 1, 1) << 7 }; /* Special table for nibble processing (e.g. ack), feedback at bit 3 */ static const uint8_t TableC3[32] = { /* fc with Input {4,3,2,1,0} = (0,0,0,0,0) to (1,1,1,1,1) */ FC(0, 0, 0, 0, 0) << 3, FC(0, 0, 0, 0, 1) << 3, FC(0, 0, 0, 1, 0) << 3, FC(0, 0, 0, 1, 1) << 3, - FC(0, 0, 1, 0, 0) << 3, FC(0, 0, 1, 0, 1) << 3, FC(0, 0, 1, 1, 0) << 3, FC(0, 0, 1, 1, 1) << 3, - FC(0, 1, 0, 0, 0) << 3, FC(0, 1, 0, 0, 1) << 3, FC(0, 1, 0, 1, 0) << 3, FC(0, 1, 0, 1, 1) << 3, - FC(0, 1, 1, 0, 0) << 3, FC(0, 1, 1, 0, 1) << 3, FC(0, 1, 1, 1, 0) << 3, FC(0, 1, 1, 1, 1) << 3, - FC(1, 0, 0, 0, 0) << 3, FC(1, 0, 0, 0, 1) << 3, FC(1, 0, 0, 1, 0) << 3, FC(1, 0, 0, 1, 1) << 3, - FC(1, 0, 1, 0, 0) << 3, FC(1, 0, 1, 0, 1) << 3, FC(1, 0, 1, 1, 0) << 3, FC(1, 0, 1, 1, 1) << 3, - FC(1, 1, 0, 0, 0) << 3, FC(1, 1, 0, 0, 1) << 3, FC(1, 1, 0, 1, 0) << 3, FC(1, 1, 0, 1, 1) << 3, - FC(1, 1, 1, 0, 0) << 3, FC(1, 1, 1, 0, 1) << 3, FC(1, 1, 1, 1, 0) << 3, FC(1, 1, 1, 1, 1) << 3 + FC(0, 0, 1, 0, 0) << 3, FC(0, 0, 1, 0, 1) << 3, FC(0, 0, 1, 1, 0) << 3, FC(0, 0, 1, 1, 1) << 3, + FC(0, 1, 0, 0, 0) << 3, FC(0, 1, 0, 0, 1) << 3, FC(0, 1, 0, 1, 0) << 3, FC(0, 1, 0, 1, 1) << 3, + FC(0, 1, 1, 0, 0) << 3, FC(0, 1, 1, 0, 1) << 3, FC(0, 1, 1, 1, 0) << 3, FC(0, 1, 1, 1, 1) << 3, + FC(1, 0, 0, 0, 0) << 3, FC(1, 0, 0, 0, 1) << 3, FC(1, 0, 0, 1, 0) << 3, FC(1, 0, 0, 1, 1) << 3, + FC(1, 0, 1, 0, 0) << 3, FC(1, 0, 1, 0, 1) << 3, FC(1, 0, 1, 1, 0) << 3, FC(1, 0, 1, 1, 1) << 3, + FC(1, 1, 0, 0, 0) << 3, FC(1, 1, 0, 0, 1) << 3, FC(1, 1, 0, 1, 0) << 3, FC(1, 1, 0, 1, 1) << 3, + FC(1, 1, 1, 0, 0) << 3, FC(1, 1, 1, 0, 1) << 3, FC(1, 1, 1, 1, 0) << 3, FC(1, 1, 1, 1, 1) << 3 }; /* Filter Output Macros */ diff --git a/Firmware/Chameleon-Mini/Application/ISO14443-3A.h b/Firmware/Chameleon-Mini/Application/ISO14443-3A.h index 99cb56c..5ee3efb 100644 --- a/Firmware/Chameleon-Mini/Application/ISO14443-3A.h +++ b/Firmware/Chameleon-Mini/Application/ISO14443-3A.h @@ -133,7 +133,7 @@ bool ISO14443AWakeUp(void *Buffer, uint16_t *BitCount, uint16_t ATQAValue, bool return true; } else { - *BitCount = 0; +// *BitCount = 0; return false; } diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.c b/Firmware/Chameleon-Mini/Application/MifareClassic.c index 7271018..ec2cc33 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.c +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -3,8 +3,14 @@ * * Created on: 13.05.2013 * Author: skuser + * + * ChangeLog + * 2019-09-22 willok 加入了UID模式开关,加入了SAK模式开关 + * 2019-10-05 Willok 将侦测卡功能整合进来,以减少程序大小 + * */ +#include "System.h" #include "MifareClassic.h" #include "ISO14443-3A.h" @@ -75,9 +81,12 @@ #define CMD_SIG_READ_FRAME_SIZE 1 /* Bytes without CRCA */ #define CMD_TRANSFER 0xB0 #define CMD_TRANSFER_FRAME_SIZE 2 /* Bytes without CRCA */ + +// 白卡相关的指令 #define CMD_CHINESE_UNLOCK 0x40 #define CMD_CHINESE_WIPE 0x41 #define CMD_CHINESE_UNLOCK_RW 0x43 +#define CMD_CHINESE_UFUID_UNLOCK 0xE0 @@ -283,6 +292,7 @@ static uint8_t AccessAddress; static uint16_t CardATQAValue; static uint8_t CardSAKValue; static bool FromHalt = false; +static bool DetectionMode = false; #define BYTE_SWAP(x) (((uint8_t)(x)>>4)|((uint8_t)(x)<<4)) #define NO_ACCESS 0x07 @@ -382,11 +392,103 @@ void MifareClassicAppInitMini4B(void) { FromHalt = false; } +extern uint8_t bUidMode; // Magic card mode switch + +#define FRAM_DETECTION_START_ADDR 0x7000 +#define FRAM_DETECTION_DATA_ADDR 0x7002 +#define FRAM_DETECTION_DATA_SIZE 0x0FF8 + +static uint16_t DetectionLogPtr = FRAM_DETECTION_DATA_ADDR; +static uint8_t EEMEM LogDetectionValid = false; + +static void DetectionLogToFlash(uint8_t Entry, const void *Data, uint8_t Length) { + if (!DetectionMode) + return; + + uint8_t bLogHead[4]; + uint16_t SysTick = SystemGetSysTick(); + + uint16_t FRAM_Free = FRAM_DETECTION_DATA_SIZE - (DetectionLogPtr - FRAM_DETECTION_START_ADDR); + + // Prevent overflow, discard + if ((Length + 4) >= FRAM_Free) { + // Light up LED4-6-8 to notify + PORTA.DIRSET = PIN0_bm; + PORTE.DIRSET = PIN1_bm | PIN0_bm; + + PORTA.OUTCLR = PIN0_bm; + PORTE.OUTCLR = PIN1_bm; + PORTE.OUTCLR = PIN0_bm; + return; + } + + bLogHead[0] = Entry; + bLogHead[1] = Length; + bLogHead[2] = (uint8_t)(SysTick >> 8); + bLogHead[3] = (uint8_t)(SysTick >> 0); + MemoryWriteBlock(bLogHead, DetectionLogPtr, 4); + DetectionLogPtr += 4; + + MemoryWriteBlock(Data, DetectionLogPtr, Length); + DetectionLogPtr += Length; + + MemoryWriteBlock(&DetectionLogPtr, FRAM_DETECTION_START_ADDR, 2); +} + +void DetectionLogClear(void) { + DetectionLogPtr = FRAM_DETECTION_DATA_ADDR; + MemoryWriteBlock(&DetectionLogPtr, FRAM_DETECTION_START_ADDR, 2); +} + +void DetectionInit(void) { + uint8_t result; + ReadEEPBlock((uint16_t) &LogDetectionValid, &result, 1); + if (result == 0x5A) { + MemoryReadBlock(&DetectionLogPtr, FRAM_DETECTION_START_ADDR, 2); + } else { + DetectionLogClear(); + result = 0x5A; + WriteEEPBlock((uint16_t) &LogDetectionValid, &result, 1); + } +} + +// Download log +bool RfLogMemLoadBlock(void *Buffer, uint32_t BlockAddress, uint16_t ByteCount) { + // 位置超出尾部了,结束 + if (BlockAddress < (DetectionLogPtr - FRAM_DETECTION_START_ADDR)) { + MemoryReadBlock(Buffer, BlockAddress + FRAM_DETECTION_START_ADDR, ByteCount); + if (0 == BlockAddress) + ((uint8_t *)Buffer)[1] -= FRAM_DETECTION_START_ADDR >> 8; + + return true; + } else { + return false; + } +} + +// Download detection log +CommandStatusIdType CommandGetDetection(char *OutMessage) { + XModemSend(RfLogMemLoadBlock); + return COMMAND_INFO_XMODEM_WAIT_ID; +} + +// Clear detection log +CommandStatusIdType CommandSetDetection(char *OutMessage, const char *InParam) { + DetectionLogClear(); + return COMMAND_INFO_OK_ID; +} + void MifareClassicAppInit1K(void) { State = STATE_IDLE; CardATQAValue = MFCLASSIC_1K_ATQA_VALUE; CardSAKValue = MFCLASSIC_1K_SAK_VALUE; FromHalt = false; + DetectionMode = false; + + if (GlobalSettings.ActiveSettingPtr->bSakMode) { + MemoryReadBlock(&CardSAKValue, 5, 1); + MemoryReadBlock(&CardATQAValue, 6, 2); + } } void MifareClassicAppInit1K7B(void) { @@ -394,6 +496,7 @@ void MifareClassicAppInit1K7B(void) { CardATQAValue = MFCLASSIC_1K_7B_ATQA_VALUE; CardSAKValue = MFCLASSIC_1K_SAK_VALUE; FromHalt = false; + DetectionMode = false; } @@ -402,6 +505,12 @@ void MifareClassicAppInit4K(void) { CardATQAValue = MFCLASSIC_4K_ATQA_VALUE; CardSAKValue = MFCLASSIC_4K_SAK_VALUE; FromHalt = false; + DetectionMode = false; + + if (GlobalSettings.ActiveSettingPtr->bSakMode) { + MemoryReadBlock(&CardSAKValue, 5, 1); + MemoryReadBlock(&CardATQAValue, 6, 2); + } } void MifareClassicAppInit4K7B(void) { @@ -409,6 +518,56 @@ void MifareClassicAppInit4K7B(void) { CardATQAValue = MFCLASSIC_4K_7B_ATQA_VALUE; CardSAKValue = MFCLASSIC_4K_SAK_VALUE; FromHalt = false; + DetectionMode = false; +} + +// 1K mode is used by default +void MifareDetectionInit1K(void) { + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_1K_ATQA_VALUE; + CardSAKValue = MFCLASSIC_1K_SAK_VALUE; + FromHalt = false; + DetectionMode = true; + + DetectionLogToFlash(LOG_INFO_SYSTEM_BOOT, NULL, 0); + + if (GlobalSettings.ActiveSettingPtr->bSakMode) { + MemoryReadBlock(&CardSAKValue, 5, 1); + MemoryReadBlock(&CardATQAValue, 6, 2); + } +} + +void MifareDetectionInit1K7B(void) { + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_1K_7B_ATQA_VALUE; + CardSAKValue = MFCLASSIC_1K_SAK_VALUE; + FromHalt = false; + DetectionMode = true; + + DetectionLogToFlash(LOG_INFO_SYSTEM_BOOT, NULL, 0); +} + +void MifareDetectionInit4K(void) { + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_4K_ATQA_VALUE; + CardSAKValue = MFCLASSIC_4K_SAK_VALUE; + FromHalt = false; + + DetectionLogToFlash(LOG_INFO_SYSTEM_BOOT, NULL, 0); + + if (GlobalSettings.ActiveSettingPtr->bSakMode) { + MemoryReadBlock(&CardSAKValue, 5, 1); + MemoryReadBlock(&CardATQAValue, 6, 2); + } +} + +void MifareDetectionInit4K7B(void) { + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_4K_7B_ATQA_VALUE; + CardSAKValue = MFCLASSIC_4K_SAK_VALUE; + FromHalt = false; + + DetectionLogToFlash(LOG_INFO_SYSTEM_BOOT, NULL, 0); } void MifareClassicAppReset(void) { @@ -419,6 +578,12 @@ void MifareClassicAppTask(void) { } +#define MF_AUTH_OK 0x08 +#define MF_AUTH_NEST 0x04 +#define MF_AUTH_KEYB 0x01 + +uint8_t AuthDataLog[22]; + uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { /* Wakeup and Request may occure in all states */ if ((BitCount == 7) && @@ -441,16 +606,16 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { State = STATE_READY1; return BitCount; } -#ifdef SUPPORT_MF_CLASSIC_MAGIC_MODE +//#ifdef SUPPORT_MF_CLASSIC_MAGIC_MODE else if (Buffer[0] == CMD_CHINESE_UNLOCK) { State = STATE_CHINESE_IDLE; Buffer[0] = ACK_VALUE; return ACK_NAK_FRAME_SIZE; } -#endif +//#endif break; -#ifdef SUPPORT_MF_CLASSIC_MAGIC_MODE +//#ifdef SUPPORT_MF_CLASSIC_MAGIC_MODE case STATE_CHINESE_IDLE: /* Support special china commands that dont require authentication. */ if (Buffer[0] == CMD_CHINESE_UNLOCK_RW) { @@ -504,6 +669,9 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { Buffer[0] = NAK_INVALID_ARG; return ACK_NAK_FRAME_SIZE; } + } else { + Buffer[0] = NAK_NOT_AUTHED; + return ACK_NAK_FRAME_SIZE; } break; @@ -523,7 +691,7 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { State = STATE_CHINESE_IDLE; return ACK_NAK_FRAME_SIZE; -#endif +//#endif case STATE_READY1: if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue, FromHalt)) { @@ -596,106 +764,134 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { Buffer[0] = NAK_INVALID_ARG; return ACK_NAK_FRAME_SIZE; } - } else if ((Buffer[0] == CMD_AUTH_A) || (Buffer[0] == CMD_AUTH_B)) { - if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) { + } else if (BitCount == BITS_PER_BYTE * 4) { + if ((Buffer[0] == CMD_AUTH_A) || (Buffer[0] == CMD_AUTH_B)) { + if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) { - //uint16_t SectorAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; - uint16_t KeyOffset = (Buffer[0] == CMD_AUTH_A ? MEM_KEY_A_OFFSET : MEM_KEY_B_OFFSET); - uint16_t AccessOffset = MEM_KEY_A_OFFSET + MEM_KEY_SIZE; - uint16_t SectorStartAddress; - uint8_t Key[6]; - uint8_t Uid[4]; - uint8_t CardNonce[8]; + //uint16_t SectorAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; + uint16_t KeyOffset = (Buffer[0] == CMD_AUTH_A ? MEM_KEY_A_OFFSET : MEM_KEY_B_OFFSET); + uint16_t AccessOffset = MEM_KEY_A_OFFSET + MEM_KEY_SIZE; + uint16_t SectorStartAddress; + uint8_t Key[6]; + uint8_t Uid[4]; + uint8_t CardNonce[8]; + uint8_t Sector = Buffer[1]; - /* Fix for MFClassic 4k cards */ - if (Buffer[1] >= 128) { - SectorStartAddress = (Buffer[1] & MEM_BIGSECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; - KeyOffset += MEM_KEY_BIGSECTOR_OFFSET; - AccessOffset += MEM_KEY_BIGSECTOR_OFFSET; + /* Fix for MFClassic 4k cards */ + if (Buffer[1] >= 128) { + SectorStartAddress = (Buffer[1] & MEM_BIGSECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + KeyOffset += MEM_KEY_BIGSECTOR_OFFSET; + AccessOffset += MEM_KEY_BIGSECTOR_OFFSET; + } else { + SectorStartAddress = (Buffer[1] & MEM_SECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + } + + LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); + /* set KeyInUse for global use to keep info about authentication */ + KeyInUse = Buffer[0] & 1; + CurrentAddress = SectorStartAddress / MEM_BYTES_PER_BLOCK; + //if (!AccessConditions[MEM_ACC_GPB_SIZE-1] ||(CurrentAddress != AccessAddress)) { + /* Get access conditions from the sector trailor */ + MemoryReadBlock(AccessConditions, SectorStartAddress + AccessOffset, MEM_ACC_GPB_SIZE); + AccessAddress = CurrentAddress; + //} + + + /* Generate a random nonce and read UID and key from memory */ + RandomGetBuffer(CardNonce, sizeof(CardNonce)); + if (ActiveConfiguration.UidSize == 7) + MemoryReadBlock(Uid, MEM_UID_CL2_ADDRESS, MEM_UID_CL2_SIZE); + else + MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); + MemoryReadBlock(Key, SectorStartAddress + KeyOffset, MEM_KEY_SIZE); + + /* Precalculate the reader response from card-nonce */ + for (uint8_t i = 0; i < sizeof(ReaderResponse); i++) + ReaderResponse[i] = CardNonce[i]; + + Crypto1PRNG(ReaderResponse, 64); + + /* Precalculate our response from the reader response */ + for (uint8_t i = 0; i < sizeof(CardResponse); i++) + CardResponse[i] = ReaderResponse[i]; + + Crypto1PRNG(CardResponse, 32); + + /* Respond with the random card nonce and expect further authentication + * form the reader in the next frame. */ + State = STATE_AUTHING; + + /* use unencrypted card nonce */ + Buffer[0] = CardNonce[0]; + Buffer[1] = CardNonce[1]; + Buffer[2] = CardNonce[2]; + Buffer[3] = CardNonce[3]; + memcpy(&AuthDataLog[2], Uid, 4); + AuthDataLog[0] = 0x60 + KeyInUse; + AuthDataLog[1] = Sector; + memcpy(&AuthDataLog[6], CardNonce, 4); + + /* Setup crypto1 cipher. Discard in-place encrypted CardNonce. */ + Crypto1Setup(Key, Uid, CardNonce); + + return CMD_AUTH_RB_FRAME_SIZE * BITS_PER_BYTE; } else { - SectorStartAddress = (Buffer[1] & MEM_SECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + Buffer[0] = NAK_CRC_ERROR; + return ACK_NAK_FRAME_SIZE; + } + } else if ((Buffer[0] == CMD_READ) || (Buffer[0] == CMD_WRITE) || (Buffer[0] == CMD_DECREMENT) + || (Buffer[0] == CMD_INCREMENT) || (Buffer[0] == CMD_RESTORE) || (Buffer[0] == CMD_TRANSFER)) { + State = STATE_IDLE; + Buffer[0] = NAK_NOT_AUTHED; + + LogEntry(LOG_ERR_APP_NOT_AUTHED, NULL, 0); + + return ACK_NAK_FRAME_SIZE; + } else if (Buffer[0] == 0xE0) { + if (ISO14443ACheckCRCA(Buffer, CMD_READ_FRAME_SIZE)) { + Buffer[0] = 0x10; + Buffer[1] = 0x78; + Buffer[2] = 0x80; + Buffer[3] = 0xA0; + Buffer[4] = 0x00; + MemoryReadBlock(&Buffer[5], 0, MEM_BYTES_PER_BLOCK); + ISO14443AAppendCRCA(Buffer, Buffer[0]); + return (Buffer[0] + 2) * BITS_PER_BYTE; } - LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); - /* set KeyInUse for global use to keep info about authentication */ - KeyInUse = Buffer[0] & 1; - CurrentAddress = SectorStartAddress / MEM_BYTES_PER_BLOCK; - //if (!AccessConditions[MEM_ACC_GPB_SIZE-1] ||(CurrentAddress != AccessAddress)) { - /* Get access conditions from the sector trailor */ - MemoryReadBlock(AccessConditions, SectorStartAddress + AccessOffset, MEM_ACC_GPB_SIZE); - AccessAddress = CurrentAddress; - //} + State = STATE_IDLE; + return ISO14443A_APP_NO_RESPONSE; + } else if (Buffer[0] == 0xCA) { + if (ISO14443ACheckCRCA(Buffer, CMD_READ_FRAME_SIZE)) { + return 4 * BITS_PER_BYTE; + } - - /* Generate a random nonce and read UID and key from memory */ - RandomGetBuffer(CardNonce, sizeof(CardNonce)); - if (ActiveConfiguration.UidSize == 7) - MemoryReadBlock(Uid, MEM_UID_CL2_ADDRESS, MEM_UID_CL2_SIZE); - else - MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); - MemoryReadBlock(Key, SectorStartAddress + KeyOffset, MEM_KEY_SIZE); - - /* Precalculate the reader response from card-nonce */ - for (uint8_t i = 0; i < sizeof(ReaderResponse); i++) - ReaderResponse[i] = CardNonce[i]; - - Crypto1PRNG(ReaderResponse, 64); - - /* Precalculate our response from the reader response */ - for (uint8_t i = 0; i < sizeof(CardResponse); i++) - CardResponse[i] = ReaderResponse[i]; - - Crypto1PRNG(CardResponse, 32); - - /* Respond with the random card nonce and expect further authentication - * form the reader in the next frame. */ - State = STATE_AUTHING; - - /* use unencrypted card nonce */ - Buffer[0] = CardNonce[0]; - Buffer[1] = CardNonce[1]; - Buffer[2] = CardNonce[2]; - Buffer[3] = CardNonce[3]; - - /* Setup crypto1 cipher. Discard in-place encrypted CardNonce. */ - Crypto1Setup(Key, Uid, CardNonce); - - return CMD_AUTH_RB_FRAME_SIZE * BITS_PER_BYTE; - } else { - Buffer[0] = NAK_CRC_ERROR; - return ACK_NAK_FRAME_SIZE; - } - - /* EV1 READ_SIG command is */ - /* same as CMD_RESTORE but has no operand, rely on CRC here! */ - } else if ((Buffer[0] == CMD_SIG_READ) && - (Buffer[1] == 0xe0) && - (Buffer[2] == 0xb4)) { - uint8_t Key[6]; - /* check if Originality check signature data available */ - /* Signature data is stored in (hidden) blocks 68..71 (0x44..0x47) */ - /* Signature data is read with key B, check if present */ - MemoryReadBlock(Key, - MEM_EV1_SIGNATURE_TRAILOR + MEM_KEY_B_OFFSET, - MEM_KEY_SIZE); - /* Key B = 4b791bea7bcc is used to read the data, check if correct key */ - if ((Key[0] == 0x4b) && (Key[1] == 0x79) && (Key[2] == 0x1b) - && (Key[3] == 0xea) && (Key[4] == 0x7b) && (Key[5] == 0xcc)) { - /* no response! */ - /* Reader will send a HALT */ + State = STATE_IDLE; return ISO14443A_APP_NO_RESPONSE; } else { - Buffer[0] = NAK_CRC_ERROR; - return ACK_NAK_FRAME_SIZE; + /* Unknown command. Enter HALT state. */ + LogEntry(LOG_INFO_APP_CMD_UNKNOWN, Buffer, (BitCount + 7) / 8); + State = STATE_IDLE; + return ISO14443A_APP_NO_RESPONSE; } - } else if ((Buffer[0] == CMD_READ) || (Buffer[0] == CMD_WRITE) || (Buffer[0] == CMD_DECREMENT) - || (Buffer[0] == CMD_INCREMENT) || (Buffer[0] == CMD_RESTORE) || (Buffer[0] == CMD_TRANSFER)) { - State = STATE_IDLE; - Buffer[0] = NAK_NOT_AUTHED; + } else if (BitCount == 8 * 3) { + return BITS_PER_BYTE * 3; + } else if (BitCount >= 8 * 6) { + uint8_t Seq = Buffer[0]; + uint8_t Lc = Buffer[5]; + uint8_t Le = 0; - LogEntry(LOG_ERR_APP_NOT_AUTHED, NULL, 0); + if ((BitCount / 8) == (6 + Lc + 1 + 2)) + Le = Buffer[6 + Lc]; - return ACK_NAK_FRAME_SIZE; + for (uint8_t i = 0; i < Le; i++) { + Buffer[1 + i] = 0; + } + Buffer[0] = Seq; + Buffer[1 + Le] = 0x6A; + Buffer[1 + Le + 1] = 0x82; + ISO14443AAppendCRCA(Buffer, 1 + 2 + Le); + return BITS_PER_BYTE * (1 + 2 + Le + 2); } else { /* Unknown command. Enter HALT state. */ LogEntry(LOG_INFO_APP_CMD_UNKNOWN, Buffer, (BitCount + 7) / 8); @@ -705,6 +901,7 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { break; case STATE_AUTHING: + memcpy(&AuthDataLog[10], Buffer, 8); /* Reader delivers an encrypted nonce. We use it * to setup the crypto1 LFSR in nonlinear feedback mode. * Furthermore it delivers an encrypted answer. Decrypt and check it */ @@ -727,14 +924,24 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { Buffer[3] = CardResponse[3]; Crypto1ByteArrayWithParity(Buffer, 4); - LogEntry(LOG_INFO_APP_AUTHED, Buffer, sizeof(CardResponse)); + LogEntry(LOG_INFO_APP_AUTHED, Buffer, 4); State = STATE_AUTHED_IDLE; + AuthDataLog[0] |= MF_AUTH_OK; + memcpy(&AuthDataLog[18], Buffer, 4); + DetectionLogToFlash(LOG_INFO_APP_AUTHED, AuthDataLog, sizeof(AuthDataLog)); + return (CMD_AUTH_BA_FRAME_SIZE * BITS_PER_BYTE) | ISO14443A_APP_CUSTOM_PARITY; } else { LogEntry(LOG_ERR_APP_AUTH_FAIL, &ReaderResponse[0], 4); + AuthDataLog[18] = 0x00; + AuthDataLog[19] = 0x00; + AuthDataLog[20] = 0x00; + AuthDataLog[21] = 0x00; + DetectionLogToFlash(LOG_ERR_APP_AUTH_FAIL, AuthDataLog, sizeof(AuthDataLog)); + /* Just reset on authentication error. */ State = STATE_IDLE; } @@ -761,6 +968,7 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { /* Read command. Read data from memory and append CRCA. */ /* Sector trailor? Use access conditions! */ + DetectionLogToFlash(LOG_INFO_APP_CMD_READ, Buffer, 2); if ((Buffer[1] < 128 && (Buffer[1] & 3) == 3) || ((Buffer[1] & 15) == 15)) { uint8_t Acc; CurrentAddress = Buffer[1]; @@ -809,6 +1017,7 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { } } else if (Buffer[0] == CMD_WRITE) { if (ISO14443ACheckCRCA(Buffer, CMD_WRITE_FRAME_SIZE)) { + DetectionLogToFlash(LOG_INFO_APP_CMD_WRITE, Buffer, 2); /* Write command. Store the address and prepare for the upcoming data. * Respond with ACK. */ CurrentAddress = Buffer[1]; @@ -877,6 +1086,7 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { uint8_t Key[6]; uint8_t Uid[4]; uint8_t CardNonce[8]; + uint8_t Sector = Buffer[1]; /* Fix for MFClassic 4k cards */ if (Buffer[1] >= 128) { @@ -917,6 +1127,11 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount) { Crypto1PRNG(CardResponse, 32); + memcpy(&AuthDataLog[2], Uid, 4); + AuthDataLog[0] = (0x60 + KeyInUse) | MF_AUTH_NEST; + AuthDataLog[1] = Sector; + memcpy(&AuthDataLog[6], CardNonce, 4); + /* Setup crypto1 cipher. */ Crypto1SetupNested(Key, Uid, CardNonce, false); diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.h b/Firmware/Chameleon-Mini/Application/MifareClassic.h index 72d5b42..d509f2c 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.h +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.h @@ -16,6 +16,10 @@ #define MIFARE_CLASSIC_1K_MEM_SIZE 1024 #define MIFARE_CLASSIC_4K_MEM_SIZE 4096 +void DetectionInit(void); +void DetectionLogClear(void); +void MifareDetectionInit1K(void); +void MifareDetectionInit4K(void); void MifareClassicAppInitMini4B(void); void MifareClassicAppInit1K(void); void MifareClassicAppInit4K(void); diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.c b/Firmware/Chameleon-Mini/Application/Reader14443A.c index fd1bf83..6d6c236 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.c +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.c @@ -4,6 +4,7 @@ #include "../Codec/Reader14443-2A.h" #include "Crypto1.h" #include "../System.h" +#include "../uartcmd.h" #include "../Terminal/Terminal.h" @@ -138,8 +139,8 @@ uint16_t addParityBits(uint8_t *Buffer, uint16_t BitCount) { uint16_t removeParityBits(uint8_t *Buffer, uint16_t BitCount) { // Short frame, no parity bit is added - if (BitCount == 7) - return 7; + if (BitCount <= 7) + return BitCount; uint16_t i; for (i = 0; i < (BitCount / 9); i++) { @@ -147,7 +148,7 @@ uint16_t removeParityBits(uint8_t *Buffer, uint16_t BitCount) { if (i % 8) Buffer[i] |= (Buffer[i + i / 8 + 1] << (8 - (i % 8))); } - return BitCount / 9 * 8; + return (BitCount / 9) * 8; } bool checkParityBits(uint8_t *Buffer, uint16_t BitCount) { @@ -226,7 +227,7 @@ static uint16_t Reader14443A_Select(uint8_t *Buffer, uint16_t BitCount) { switch (ReaderState) { case STATE_IDLE: case STATE_HALT: - Reader_FWT = 4; + Reader_FWT = ISO14443A_RX_PENDING_TIMEOUT; /* Send a REQA */ Buffer[0] = ISO14443A_CMD_WUPA; // whenever REQA works, WUPA also works, so we choose WUPA always ReaderState = STATE_READY; @@ -802,17 +803,21 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) { if (CardCandidatesIdx == 1) { int cfgid = -1; switch (CardCandidates[0]) { +#ifdef CONFIG_MF_ULTRALIGHT_SUPPORT case CardType_NXP_MIFARE_Ultralight: { cfgid = CONFIG_MF_ULTRALIGHT; // TODO: enter MFU clone mdoe break; } +#endif case CardType_NXP_MIFARE_Classic_1k: case CardType_Infineon_MIFARE_Classic_1k: { if (CardCharacteristics.UIDSize == UIDSize_Single) { cfgid = CONFIG_MF_CLASSIC_1K; +#ifdef CONFIG_MF_CLASSIC_1K_7B_SUPPORT } else if (CardCharacteristics.UIDSize == UIDSize_Double) { cfgid = CONFIG_MF_CLASSIC_1K_7B; +#endif } break; } @@ -821,8 +826,10 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) { case CardType_Nokia_MIFARE_Classic_4k_emulated_6131: { if (CardCharacteristics.UIDSize == UIDSize_Single) { cfgid = CONFIG_MF_CLASSIC_4K; +#ifdef CONFIG_MF_CLASSIC_1K_7B_SUPPORT } else if (CardCharacteristics.UIDSize == UIDSize_Double) { cfgid = CONFIG_MF_CLASSIC_4K_7B; +#endif } break; } diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index 3c705e7..c85a177 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -23,8 +23,7 @@ static enum { } SniffState = STATE_IDLE; static uint16_t tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; -static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / - CODEC_THRESHOLD_CALIBRATE_STEPS] = {0}; +static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = {0}; void Sniff14443AAppInit(void) { SniffState = STATE_REQA; diff --git a/Firmware/Chameleon-Mini/Button.c b/Firmware/Chameleon-Mini/Button.c index 5ce9871..392cdc0 100644 --- a/Firmware/Chameleon-Mini/Button.c +++ b/Firmware/Chameleon-Mini/Button.c @@ -1,3 +1,14 @@ +/* + * Button.c + * + * Created on: 20.03.2013 + * Author: skuser + * + * ChangeLog + * 2019-09-22 willok Reverse switch function and log clearing function are added. + * + */ + #include "Button.h" #include "Random.h" #include "Common.h" @@ -25,10 +36,12 @@ static const MapEntryType PROGMEM ButtonActionMap[] = { { .Id = BUTTON_ACTION_UID_LEFT_DECREMENT, .Text = "UID_LEFT_DECREMENT" }, { .Id = BUTTON_ACTION_UID_RIGHT_DECREMENT, .Text = "UID_RIGHT_DECREMENT" }, { .Id = BUTTON_ACTION_CYCLE_SETTINGS, .Text = "CYCLE_SETTINGS" }, + { .Id = BUTTON_ACTION_CYCLE_SETTINGS_DEC, .Text = "CYCLE_SETTINGS_DEC" }, { .Id = BUTTON_ACTION_STORE_MEM, .Text = "STORE_MEM" }, { .Id = BUTTON_ACTION_RECALL_MEM, .Text = "RECALL_MEM" }, { .Id = BUTTON_ACTION_TOGGLE_FIELD, .Text = "TOGGLE_FIELD" }, { .Id = BUTTON_ACTION_STORE_LOG, .Text = "STORE_LOG" }, + { .Id = BUTTON_ACTION_CLEAR_LOG, .Text = "CLEAR_LOG" }, { .Id = BUTTON_ACTION_CLONE, .Text = "CLONE" }, }; @@ -146,7 +159,12 @@ static void ExecuteButtonAction(ButtonActionEnum ButtonAction) { } case BUTTON_ACTION_CYCLE_SETTINGS: { - SettingsCycle(); + SettingsCycle(true); + break; + } + + case BUTTON_ACTION_CYCLE_SETTINGS_DEC: { + SettingsCycle(false); break; } @@ -174,6 +192,12 @@ static void ExecuteButtonAction(ButtonActionEnum ButtonAction) { break; } + case BUTTON_ACTION_CLEAR_LOG: { + LogMemClear(); + DetectionLogClear(); + break; + } + case BUTTON_ACTION_CLONE: { CommandExecute("CLONE"); break; diff --git a/Firmware/Chameleon-Mini/Button.h b/Firmware/Chameleon-Mini/Button.h index c84f603..2a8fc87 100644 --- a/Firmware/Chameleon-Mini/Button.h +++ b/Firmware/Chameleon-Mini/Button.h @@ -28,10 +28,12 @@ typedef enum { BUTTON_ACTION_UID_LEFT_DECREMENT, BUTTON_ACTION_UID_RIGHT_DECREMENT, BUTTON_ACTION_CYCLE_SETTINGS, + BUTTON_ACTION_CYCLE_SETTINGS_DEC, BUTTON_ACTION_STORE_MEM, BUTTON_ACTION_RECALL_MEM, BUTTON_ACTION_TOGGLE_FIELD, BUTTON_ACTION_STORE_LOG, + BUTTON_ACTION_CLEAR_LOG, BUTTON_ACTION_CLONE, /* This has to be last element */ diff --git a/Firmware/Chameleon-Mini/Chameleon-Mini.c b/Firmware/Chameleon-Mini/Chameleon-Mini.c index 664a299..dd983b4 100644 --- a/Firmware/Chameleon-Mini/Chameleon-Mini.c +++ b/Firmware/Chameleon-Mini/Chameleon-Mini.c @@ -1,10 +1,13 @@ #include "Chameleon-Mini.h" +#include "Uart.h" +#include "uartcmd.h" int main(void) { SystemInit(); SettingsLoad(); LEDInit(); MemoryInit(); + DetectionInit(); CodecInitCommon(); ConfigurationInit(); TerminalInit(); @@ -13,6 +16,8 @@ int main(void) { AntennaLevelInit(); LogInit(); SystemInterruptInit(); + uart_init(); + uartcmd_init(); while (1) { if (SystemTick100ms()) { @@ -25,10 +30,13 @@ int main(void) { ApplicationTick(); CommandLineTick(); AntennaLevelTick(); + uartcmd_tick(); LEDHook(LED_POWERED, LED_ON); } + uart_task(); + uartcmd_task(); TerminalTask(); LogTask(); ApplicationTask(); diff --git a/Firmware/Chameleon-Mini/Chameleon-Mini.h b/Firmware/Chameleon-Mini/Chameleon-Mini.h index 8c66796..4844012 100644 --- a/Firmware/Chameleon-Mini/Chameleon-Mini.h +++ b/Firmware/Chameleon-Mini/Chameleon-Mini.h @@ -20,7 +20,7 @@ #include "AntennaLevel.h" #include "Settings.h" -#define CHAMELEON_MINI_VERSION_STRING BUILD_DATE +#define CHAMELEON_MINI_VERSION_STRING __DATE__ #endif //CHAMELEON_MINI_H diff --git a/Firmware/Chameleon-Mini/Codec/Codec.c b/Firmware/Chameleon-Mini/Codec/Codec.c index 30151e7..14d0bdf 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.c +++ b/Firmware/Chameleon-Mini/Codec/Codec.c @@ -11,6 +11,7 @@ uint16_t Reader_FWT = ISO14443A_RX_PENDING_TIMEOUT; +// 这个是从开启到准备好的时间间隔,之前不能发送数据 #define READER_FIELD_MINIMUM_WAITING_TIME 70 // ms static uint16_t ReaderFieldStartTimestamp = 0; diff --git a/Firmware/Chameleon-Mini/Codec/ISO15693.c b/Firmware/Chameleon-Mini/Codec/ISO15693.c index 601be47..152837e 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO15693.c +++ b/Firmware/Chameleon-Mini/Codec/ISO15693.c @@ -12,7 +12,7 @@ #include "LEDHook.h" #include "AntennaLevel.h" #include "Terminal/Terminal.h" -#include +//#include #include #include @@ -80,8 +80,6 @@ static volatile uint16_t BitRate2; static volatile uint16_t SampleDataCount; static volatile uint16_t ReadCommandFromReader = 0; -#ifdef CONFIG_VICINITY_SUPPORT - /* This function implements CODEC_DEMOD_IN_INT0_VECT interrupt vector. * It is called when a pulse is detected in CODEC_DEMOD_IN_PORT (PORTB). * The relevatn interrupt vector is registered to CODEC_DEMOD_IN_MASK0 (PIN1) via: @@ -461,8 +459,6 @@ LOADMOD_FINISHED_LABEL: return; } -#endif /* CONFIG_VICINITY_SUPPORT */ - /* This functions resets all global variables used in the codec and enables interrupts to wait for reader data */ void StartISO15693Demod(void) { /* Reset global variables to default values */ diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index cc4180e..d88de71 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -11,7 +11,7 @@ #include "../Application/Application.h" #include "LEDHook.h" #include "Terminal/Terminal.h" -#include +//#include #define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) #define ISO14443A_RX_MINIMUM_BITCOUNT 4 @@ -48,6 +48,8 @@ void Reader14443ACodecInit(void) { /* Initialize common peripherals and start listening * for incoming data. */ CodecInitCommon(); + + // 中断回调 isr_func_TCD0_CCC_vect = &isr_Reader14443_2A_TCD0_CCC_vect; CodecSetDemodPower(true); @@ -198,7 +200,9 @@ void isr_Reader14443_2A_TCD0_CCC_vect(void) { BitCountUp = 0; State = STATE_IDLE; +#ifndef CONFIG_UART_MODE PORTE.OUTTGL = PIN3_bm; +#endif } // Reader -> card send bits finished @@ -208,7 +212,9 @@ void Reader14443AMillerEOC(void) { CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm | TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc | TC_CCCINTLVL_HI_gc; CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; +#ifndef CONFIG_UART_MODE PORTE.OUTTGL = PIN3_bm; +#endif } // EOC of Card->Reader found diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index ac132fb..801a610 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -13,7 +13,7 @@ #include "../Application/Application.h" #include "LEDHook.h" #include "Terminal/Terminal.h" -#include +//#include /* Sampling is done using internal clock, synchronized to the field modulation. * For that we need to convert the bit rate for the internal clock. */ @@ -109,7 +109,9 @@ INLINE void ReaderSniffDeInit(void) { // Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT1_VECT) { +#ifndef CONFIG_UART_MODE PORTE.OUTSET = PIN2_bm; +#endif /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start @@ -147,8 +149,9 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { // Shutdown the Reader->Card Sniffing, // disable the sampling timer +#ifndef CONFIG_UART_MODE PORTE.OUTCLR = PIN2_bm; - +#endif CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; @@ -473,7 +476,9 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) { // EOC found void Sniff14443ACodecInit(void) { +#ifndef CONFIG_UART_MODE PORTE.DIRSET = PIN3_bm | PIN2_bm; +#endif // Common Codec Register settings CodecInitCommon(); isr_func_CODEC_TIMER_LOADMOD_CCB_VECT = &isr_SniffISO14443_2A_CODEC_TIMER_LOADMOD_CCB_VECT; @@ -496,7 +501,9 @@ void Sniff14443ACodecDeInit(void) { void Sniff14443ACodecTask(void) { +#ifndef CONFIG_UART_MODE PORTE.OUTSET = PIN3_bm; +#endif if (Flags.ReaderDataAvaliable) { Flags.ReaderDataAvaliable = false; @@ -526,7 +533,8 @@ void Sniff14443ACodecTask(void) { CardSniffDeinit(); ReaderSniffInit(); } +#ifndef CONFIG_UART_MODE PORTE.OUTCLR = PIN3_bm; - +#endif } diff --git a/Firmware/Chameleon-Mini/Common.h b/Firmware/Chameleon-Mini/Common.h index 0456329..658082e 100644 --- a/Firmware/Chameleon-Mini/Common.h +++ b/Firmware/Chameleon-Mini/Common.h @@ -11,7 +11,7 @@ #include #include #include -#include +//#include #include #include diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index aef4fb8..c26ff6e 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -3,6 +3,10 @@ * * Created on: 15.02.2013 * Author: skuser + * + * ChangeLog + * 2019-09-22 Willok Add Turn on the antenna load when simulation tags. It solves the problem of blind area in the short distance of reading head. + * */ #include "Configuration.h" @@ -35,6 +39,12 @@ static const MapEntryType PROGMEM ConfigurationMap[] = { #ifdef CONFIG_MF_CLASSIC_4K_7B_SUPPORT { .Id = CONFIG_MF_CLASSIC_4K_7B, .Text = "MF_CLASSIC_4K_7B" }, #endif +#ifdef CONFIG_MF_DETECTION_SUPPORT + { .Id = CONFIG_MF_DETECTION, .Text = "MF_DETECTION_1K" }, +#endif +#ifdef CONFIG_MF_DETECTION_4K_SUPPORT + { .Id = CONFIG_MF_DETECTION_4K, .Text = "MF_DETECTION_4K" }, +#endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT { .Id = CONFIG_ISO14443A_SNIFF, .Text = "ISO14443A_SNIFF" }, #endif @@ -247,6 +257,42 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .TagFamily = TAG_FAMILY_ISO14443A }, #endif +#ifdef CONFIG_MF_DETECTION_SUPPORT + [CONFIG_MF_DETECTION] = { + .CodecInitFunc = ISO14443ACodecInit, + .CodecDeInitFunc = ISO14443ACodecDeInit, + .CodecTaskFunc = ISO14443ACodecTask, + .ApplicationInitFunc = MifareDetectionInit1K, + .ApplicationResetFunc = MifareClassicAppReset, + .ApplicationTaskFunc = MifareClassicAppTask, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = MifareClassicAppProcess, + .ApplicationGetUidFunc = MifareClassicGetUid, + .ApplicationSetUidFunc = MifareClassicSetUid, + .UidSize = MIFARE_CLASSIC_UID_SIZE, + .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO14443A + }, +#endif +#ifdef CONFIG_MF_DETECTION_4K_SUPPORT + [CONFIG_MF_DETECTION_4K] = { + .CodecInitFunc = ISO14443ACodecInit, + .CodecDeInitFunc = ISO14443ACodecDeInit, + .CodecTaskFunc = ISO14443ACodecTask, + .ApplicationInitFunc = MifareDetectionInit4K, + .ApplicationResetFunc = MifareClassicAppReset, + .ApplicationTaskFunc = MifareClassicAppTask, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = MifareClassicAppProcess, + .ApplicationGetUidFunc = MifareClassicGetUid, + .ApplicationSetUidFunc = MifareClassicSetUid, + .UidSize = MIFARE_CLASSIC_UID_SIZE, + .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO14443A + }, +#endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT [CONFIG_ISO14443A_SNIFF] = { .CodecInitFunc = Sniff14443ACodecInit, @@ -380,6 +426,9 @@ ConfigurationType ActiveConfiguration; void ConfigurationInit(void) { memcpy_P(&ActiveConfiguration, &ConfigurationTable[CONFIG_NONE], sizeof(ConfigurationType)); + // Simulation mode antenna load, Default is close load. + PORTC.DIRSET = PIN7_bm; + PORTC.OUTCLR = PIN7_bm; ConfigurationSetById(GlobalSettings.ActiveSettingPtr->Configuration); } @@ -387,6 +436,7 @@ void ConfigurationInit(void) { void ConfigurationSetById(ConfigurationEnum Configuration) { CodecDeInit(); + // Cancel currently executed command when configuration changes CommandLinePendingTaskBreak(); // break possibly pending task GlobalSettings.ActiveSettingPtr->Configuration = Configuration; @@ -395,6 +445,12 @@ void ConfigurationSetById(ConfigurationEnum Configuration) { memcpy_P(&ActiveConfiguration, &ConfigurationTable[Configuration], sizeof(ConfigurationType)); + // Configure antenna load as appropriate + if (Configuration == CONFIG_ISO14443A_READER) + PORTC.OUTCLR = PIN7_bm; + else + PORTC.OUTSET = PIN7_bm; + CodecInit(); ApplicationInit(); } @@ -407,6 +463,10 @@ bool ConfigurationSetByName(const char *Configuration) { MapIdType Id; if (MapTextToId(ConfigurationMap, ARRAY_COUNT(ConfigurationMap), Configuration, &Id)) { + // The last configuration can only be configured as a reader + if (GlobalSettings.ActiveSettingIdx >= SETTINGS_COUNT && Id != CONFIG_ISO14443A_READER) { + return false; + } ConfigurationSetById(Id); LogEntry(LOG_INFO_CONFIG_SET, Configuration, StringLength(Configuration, CONFIGURATION_NAME_LENGTH_MAX - 1)); return true; diff --git a/Firmware/Chameleon-Mini/Configuration.h b/Firmware/Chameleon-Mini/Configuration.h index f348d44..fefa9fe 100644 --- a/Firmware/Chameleon-Mini/Configuration.h +++ b/Firmware/Chameleon-Mini/Configuration.h @@ -41,6 +41,12 @@ typedef enum { #ifdef CONFIG_MF_CLASSIC_4K_7B_SUPPORT CONFIG_MF_CLASSIC_4K_7B, #endif +#ifdef CONFIG_MF_DETECTION_SUPPORT + CONFIG_MF_DETECTION, +#endif +#ifdef CONFIG_MF_DETECTION_4K_SUPPORT + CONFIG_MF_DETECTION_4K, +#endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT CONFIG_ISO14443A_SNIFF, #endif diff --git a/Firmware/Chameleon-Mini/LED.c b/Firmware/Chameleon-Mini/LED.c index 0bddd2c..991dffb 100644 --- a/Firmware/Chameleon-Mini/LED.c +++ b/Firmware/Chameleon-Mini/LED.c @@ -1,3 +1,13 @@ +/* + * LED.c + * + * Created on: 13.05.2013 + * Author: skuser + * + * ChangeLog + * 2019-09-22 willok Add 8 LED for indicate 8 slot + * + */ #include "LED.h" #include "Settings.h" #include "Map.h" @@ -24,7 +34,97 @@ static const MapEntryType PROGMEM LEDFunctionMap[] = { { .Id = LED_LOG_MEM_FULL, .Text = "LOGMEM_FULL" }, }; -INLINE void Tick(uint8_t Mask, LEDActionEnum *Action) { +void LEDHook(LEDHookEnum Func, LEDActionEnum Action) { + extern LEDActionEnum LEDGreenAction; + extern LEDActionEnum LEDRedAction; + + if (GlobalSettings.ActiveSettingPtr->LEDGreenFunction == Func) { + LEDGreenAction = Action; + } + + if (GlobalSettings.ActiveSettingPtr->LEDRedFunction == Func) { + LEDRedAction = Action; + } +} + + + +// 0 = Default mode,1 = 8 LED mode +uint8_t LedMode = 1; + +uint8_t LedConfig[] = { + 1, 0, 2, 2, 2, // 1 + 0, 1, 2, 2, 2, + 0, 0, 1, 2, 2, + 0, 0, 0, 2, 2, + 0, 0, 2, 1, 2, + 0, 0, 2, 0, 2, + 0, 0, 2, 2, 1, + 0, 0, 2, 2, 0, + 0, 0, 0, 1, 2, // 9 +}; + +// LED init +void LEDInit(void) { + LED_PORT.DIRSET = LED_MASK; + + // For Extended led, high resistance + PORTA.DIRCLR = PIN0_bm; + PORTE.DIRCLR = PIN1_bm; + PORTE.DIRCLR = PIN0_bm; +} + +// 根据状态切换指示灯 +void Led8Map(uint8_t LedNo) { + // 超出范围 + if (LedNo > SETTINGS_COUNT) { + return; + } + + if (LedConfig[LedNo * 5]) + LED_PORT.OUTSET = PIN4_bm; + else + LED_PORT.OUTCLR = PIN4_bm; + + if (LedConfig[LedNo * 5 + 1]) + LED_PORT.OUTSET = PIN3_bm; + else + LED_PORT.OUTCLR = PIN3_bm; + + if (0 == LedConfig[LedNo * 5 + 2]) { + PORTA.OUTCLR = PIN0_bm; + PORTA.DIRSET = PIN0_bm; + } else if (1 == LedConfig[LedNo * 5 + 2]) { + PORTA.OUTSET = PIN0_bm; + PORTA.DIRSET = PIN0_bm; + } else { + PORTA.DIRCLR = PIN0_bm; + } + + if (0 == LedConfig[LedNo * 5 + 3]) { + PORTE.OUTCLR = PIN1_bm; + PORTE.DIRSET = PIN1_bm; + } else if (1 == LedConfig[LedNo * 5 + 3]) { + PORTE.OUTSET = PIN1_bm; + PORTE.DIRSET = PIN1_bm; + } else { + PORTE.DIRCLR = PIN1_bm; + } + + if (0 == LedConfig[LedNo * 5 + 4]) { + PORTE.OUTCLR = PIN0_bm; + PORTE.DIRSET = PIN0_bm; + } else if (1 == LedConfig[LedNo * 5 + 4]) { + PORTE.OUTSET = PIN0_bm; + PORTE.DIRSET = PIN0_bm; + } else { + PORTE.DIRCLR = PIN0_bm; + } +} + +// 循环执行,更新指示灯状态 +//INLINE void Tick(uint8_t Mask, LEDActionEnum* Action) +void Tick(uint8_t Mask, LEDActionEnum *Action) { static uint8_t LEDRedBlinkPrescaler = 0; static uint8_t LEDGreenBlinkPrescaler = 0; uint8_t *BlinkPrescaler = (Action == &LEDGreenAction) ? &LEDGreenBlinkPrescaler : &LEDRedBlinkPrescaler; @@ -58,7 +158,7 @@ INLINE void Tick(uint8_t Mask, LEDActionEnum *Action) { } break; - case LED_BLINK_1X ... LED_BLINK_8X: + case LED_BLINK_1X ... LED_BLINK_9X: if (++(*BlinkPrescaler) == BLINK_PRESCALER) { *BlinkPrescaler = 0; @@ -88,14 +188,21 @@ INLINE void Tick(uint8_t Mask, LEDActionEnum *Action) { } } -void LEDInit(void) { - LED_PORT.DIRSET = LED_MASK; -} - - +// 指示灯循环 void LEDTick(void) { - Tick(LED_RED, &LEDRedAction); - Tick(LED_GREEN, &LEDGreenAction); + // 默认模式 + if (0 == LedMode) { + Tick(LED_RED, &LEDRedAction); + Tick(LED_GREEN, &LEDGreenAction); + } else { + static uint8_t LastLed = 0xFF; + + // 配置更改,更新显示 + if (LastLed != GlobalSettings.ActiveSettingIdx) { + LastLed = GlobalSettings.ActiveSettingIdx; + Led8Map(LastLed); + } + } } void LEDGetFuncList(char *List, uint16_t BufferSize) { diff --git a/Firmware/Chameleon-Mini/LED.h b/Firmware/Chameleon-Mini/LED.h index b93d444..f192fde 100644 --- a/Firmware/Chameleon-Mini/LED.h +++ b/Firmware/Chameleon-Mini/LED.h @@ -12,8 +12,8 @@ #include "Common.h" #define LED_PORT PORTA -#define LED_GREEN PIN4_bm -#define LED_RED PIN3_bm +#define LED_GREEN PIN3_bm +#define LED_RED PIN4_bm #define LED_MASK (LED_GREEN | LED_RED) typedef enum LEDFunctionEnum { @@ -55,6 +55,7 @@ typedef enum LEDActionEnum { LED_BLINK_6X, LED_BLINK_7X, LED_BLINK_8X, + LED_BLINK_9X, } LEDActionEnum; diff --git a/Firmware/Chameleon-Mini/LEDHook.h b/Firmware/Chameleon-Mini/LEDHook.h index 9827ae0..b24eec5 100644 --- a/Firmware/Chameleon-Mini/LEDHook.h +++ b/Firmware/Chameleon-Mini/LEDHook.h @@ -10,6 +10,8 @@ #include "Settings.h" +void LEDHook(LEDHookEnum Func, LEDActionEnum Action); +/* INLINE void LEDHook(LEDHookEnum Func, LEDActionEnum Action) { extern LEDActionEnum LEDGreenAction; extern LEDActionEnum LEDRedAction; @@ -22,5 +24,5 @@ INLINE void LEDHook(LEDHookEnum Func, LEDActionEnum Action) { LEDRedAction = Action; } } - +*/ #endif /* LEDHOOK_H_ */ diff --git a/Firmware/Chameleon-Mini/Log.c b/Firmware/Chameleon-Mini/Log.c index 721cd74..a71ccf2 100644 --- a/Firmware/Chameleon-Mini/Log.c +++ b/Firmware/Chameleon-Mini/Log.c @@ -11,7 +11,7 @@ static uint16_t LogMemLeft; static uint16_t LogFRAMAddr = FRAM_LOG_START_ADDR; static uint8_t EEMEM LogFRAMAddrValid = false; static bool EnableLogSRAMtoFRAM = false; -LogFuncType CurrentLogFunc; +LogFuncType CurrentLogFunc = NULL; static const MapEntryType PROGMEM LogModeMap[] = { { .Id = LOG_MODE_OFF, .Text = "OFF" }, @@ -62,16 +62,16 @@ void LogInit(void) { LogSetModeById(GlobalSettings.ActiveSettingPtr->LogMode); LogMemPtr = LogMem; LogMemLeft = sizeof(LogMem); + memset(LogMemPtr, LOG_EMPTY, LOG_SIZE); uint8_t result; ReadEEPBlock((uint16_t) &LogFRAMAddrValid, &result, 1); - memset(LogMemPtr, LOG_EMPTY, LOG_SIZE); - if (result) { + if (result == 0x5A) { MemoryReadBlock(&LogFRAMAddr, FRAM_LOG_ADDR_ADDR, 2); } else { LogFRAMAddr = FRAM_LOG_START_ADDR; MemoryWriteBlock(&LogFRAMAddr, FRAM_LOG_ADDR_ADDR, 2); - result = true; + result = 0x5A; WriteEEPBlock((uint16_t) &LogFRAMAddrValid, &result, 1); } @@ -126,7 +126,8 @@ bool LogMemLoadBlock(void *Buffer, uint32_t BlockAddress, uint16_t ByteCount) { } } -INLINE void LogSRAMClear(void) { +//INLINE void LogSRAMClear(void) +void LogSRAMClear(void) { uint16_t i, until = LOG_SIZE - LogMemLeft; for (i = 0; i < until; i++) { diff --git a/Firmware/Chameleon-Mini/Log.h b/Firmware/Chameleon-Mini/Log.h index b6e49bb..8ffd7be 100644 --- a/Firmware/Chameleon-Mini/Log.h +++ b/Firmware/Chameleon-Mini/Log.h @@ -6,7 +6,7 @@ #define LOG_SIZE 2048 #define FRAM_LOG_ADDR_ADDR 0x4000 // start of the second half of FRAM #define FRAM_LOG_START_ADDR 0x4002 // directly after the address -#define FRAM_LOG_SIZE 0x3FFE // the whole second half (minus the 2 Bytes of Address) +#define FRAM_LOG_SIZE 0x2FFE // the whole second half (minus the 2 Bytes of Address) /** Enum for log entry type. \note Every entry type has a specific integer value, which can be found in the source code. */ typedef enum { @@ -78,6 +78,6 @@ void LogGetModeList(char *List, uint16_t BufferSize); void LogSRAMToFRAM(void); /* Wrapper function to call current logging function */ -INLINE void LogEntry(LogEntryEnum Entry, const void *Data, uint8_t Length) { CurrentLogFunc(Entry, Data, Length); } +INLINE void LogEntry(LogEntryEnum Entry, const void *Data, uint8_t Length) { if (CurrentLogFunc) CurrentLogFunc(Entry, Data, Length); } #endif /* LOG_H_ */ diff --git a/Firmware/Chameleon-Mini/Makefile b/Firmware/Chameleon-Mini/Makefile index 257115f..a7e1580 100644 --- a/Firmware/Chameleon-Mini/Makefile +++ b/Firmware/Chameleon-Mini/Makefile @@ -4,7 +4,11 @@ # because Atmel does not ship sh.exe anymore with the toolchain. SHELL = /bin/sh +SETTINGS += -DCONFIG_UART_MODE + #Supported configurations +SETTINGS += -DCONFIG_MF_DETECTION_SUPPORT +SETTINGS += -DCONFIG_MF_DETECTION_4K_SUPPORT SETTINGS += -DCONFIG_MF_CLASSIC_MINI_4B_SUPPORT SETTINGS += -DCONFIG_MF_CLASSIC_1K_SUPPORT SETTINGS += -DCONFIG_MF_CLASSIC_1K_7B_SUPPORT @@ -44,14 +48,17 @@ SETTINGS += -DDEFAULT_CONFIGURATION=CONFIG_NONE #SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_UID_RIGHT_DECREMENT SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_CYCLE_SETTINGS #SETTINGS += -DDEFAULT_RBUTTON_ACTION=BUTTON_ACTION_STORE_MEM -SETTINGS += -DDEFAULT_LBUTTON_ACTION=BUTTON_ACTION_RECALL_MEM +SETTINGS += -DDEFAULT_LBUTTON_ACTION=BUTTON_ACTION_CYCLE_SETTINGS_DEC +#SETTINGS += -DDEFAULT_LBUTTON_ACTION=BUTTON_ACTION_RECALL_MEM #Define if button action setting should be independent of active setting SETTINGS += -DBUTTON_SETTING_GLOBAL #Default LED functions -SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_SETTING_CHANGE -SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_POWERED +#SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_SETTING_CHANGE +#SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_POWERED +SETTINGS += -DDEFAULT_RED_LED_ACTION=LED_POWERED +SETTINGS += -DDEFAULT_GREEN_LED_ACTION=LED_SETTING_CHANGE #Define if LED function setting should be independent of active setting SETTINGS += -DLED_SETTING_GLOBAL @@ -68,7 +75,7 @@ SETTINGS += -DLOG_SETTING_GLOBAL SETTINGS += -DDEFAULT_SETTING=SETTINGS_FIRST #Default pending task timeout -SETTINGS += -DDEFAULT_PENDING_TASK_TIMEOUT=50 #* 100ms +SETTINGS += -DDEFAULT_PENDING_TASK_TIMEOUT=20 #* 100ms #Default reader threshold SETTINGS += -DDEFAULT_READER_THRESHOLD=400 @@ -85,7 +92,7 @@ SPM_HELPER_OBJCOPY = --set-section-flags=.spmhelper="alloc,load" #Build configuration ifeq ($(OS),Windows_NT) -BUILD_DATE = "\"$(shell date /t)\"" +BUILD_DATE = "\"$(shell date -I)\"" else BUILD_DATE = $(shell date +'\"%y%m%d\"') endif @@ -95,9 +102,9 @@ ARCH = XMEGA BOARD = NONE F_CPU = 27120000 F_USB = 48000000 -TARGET = Chameleon-Mini +TARGET = Chameleon-RevG OPTIMIZATION = s -SRC += $(TARGET).c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c +SRC += Chameleon-Mini.c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c Uart.c uartcmd.c SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Terminal/CommandLine.c SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c Application/CryptoTDEA.S @@ -120,8 +127,8 @@ AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) #AVRDUDE settings to program the precompiled firmware -AVRDUDE_WRITE_APP_LATEST = -U application:w:Latest/Chameleon-Mini.hex -AVRDUDE_WRITE_EEPROM_LATEST = -U eeprom:w:Latest/Chameleon-Mini.eep +AVRDUDE_WRITE_APP_LATEST = -U application:w:Latest/Chameleon-RevG.hex +AVRDUDE_WRITE_EEPROM_LATEST = -U eeprom:w:Latest/Chameleon-RevG.eep # Default target diff --git a/Firmware/Chameleon-Mini/Memory.c b/Firmware/Chameleon-Mini/Memory.c index c4cbd52..1a4e3ba 100644 --- a/Firmware/Chameleon-Mini/Memory.c +++ b/Firmware/Chameleon-Mini/Memory.c @@ -1,8 +1,12 @@ /* - * Flash.c + * Memory.c * * Created on: 20.03.2013 * Author: skuser + * + * ChangeLog + * 2019-09-22 Willok Modify only load and save card area, add area tracking, do not save if there is no change + * */ #include "Memory.h" @@ -36,6 +40,12 @@ void FlashEraseWriteApplicationPage(uint32_t Address); void FlashEraseFlashBuffer(void); void FlashWaitForSPM(void); +uint8_t bUidMode = 0; +uint8_t EEMEM bUidMode_EEP = 0; + +uint8_t bSramWriteFlag = 0; +uint8_t EEMEM bSramWriteFlag_EEP = 0; + static uint8_t ScrapBuffer[] = {0}; INLINE uint8_t SPITransferByte(uint8_t Data) { @@ -123,6 +133,9 @@ INLINE void SPIWriteBlock(const void *Buffer, uint16_t ByteCount) { #endif INLINE void FRAMRead(void *Buffer, uint16_t Address, uint16_t ByteCount) { + if (0 == ByteCount) + return; + FRAM_PORT.OUTCLR = FRAM_CS; SPITransferByte(0x03); /* Read command */ @@ -135,6 +148,14 @@ INLINE void FRAMRead(void *Buffer, uint16_t Address, uint16_t ByteCount) { } INLINE void FRAMWrite(const void *Buffer, uint16_t Address, uint16_t ByteCount) { + if (0 == ByteCount) + return; + + if (bSramWriteFlag == 0x00 && Address < FRAM_LOG_ADDR_ADDR) { + bSramWriteFlag++; + WriteEEPBlock((uint16_t) &bSramWriteFlag_EEP, &bSramWriteFlag, 1); + } + FRAM_PORT.OUTCLR = FRAM_CS; SPITransferByte(0x06); /* Write Enable */ FRAM_PORT.OUTSET = FRAM_CS; @@ -151,6 +172,10 @@ INLINE void FRAMWrite(const void *Buffer, uint16_t Address, uint16_t ByteCount) SPIWriteBlock(Buffer, ByteCount); FRAM_PORT.OUTSET = FRAM_CS; + + if (0 == Address && GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER) { + ConfigurationSetById(GlobalSettings.ActiveSettingPtr->Configuration); + } } INLINE void FlashRead(void *Buffer, uint32_t Address, uint16_t ByteCount) { @@ -232,6 +257,9 @@ INLINE void FlashErase(uint32_t Address, uint16_t ByteCount) { } INLINE void FlashToFRAM(uint32_t Address, uint16_t ByteCount) { + if (0 == ByteCount) + return; + /* We assume that ByteCount is a multiple of 2 */ uint32_t PhysicalAddress = Address + FLASH_DATA_ADDR; @@ -269,6 +297,14 @@ INLINE void FlashToFRAM(uint32_t Address, uint16_t ByteCount) { } INLINE void FRAMToFlash(uint32_t Address, uint16_t ByteCount) { + if (0 == ByteCount) + return; + + if (0 == bSramWriteFlag) + return; + bSramWriteFlag = 0; + WriteEEPBlock((uint16_t) &bSramWriteFlag_EEP, &bSramWriteFlag, 1); + /* We assume that FlashWrite is always called for write actions that are * aligned to APP_SECTION_PAGE_SIZE and a multiple of APP_SECTION_PAGE_SIZE. * Thus only full pages are written into the flash. */ @@ -319,6 +355,9 @@ INLINE void FRAMToFlash(uint32_t Address, uint16_t ByteCount) { } void MemoryInit(void) { + ReadEEPBlock((uint16_t) &bUidMode_EEP, &bUidMode, 1); + ReadEEPBlock((uint16_t) &bSramWriteFlag_EEP, &bSramWriteFlag, 1); + /* Configure FRAM_USART for SPI master mode 0 with maximum clock frequency */ FRAM_PORT.OUTSET = FRAM_CS; @@ -371,21 +410,27 @@ void MemoryWriteBlock(const void *Buffer, uint16_t Address, uint16_t ByteCount) } void MemoryClear(void) { - FlashErase((uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING); + if (GlobalSettings.ActiveSettingIdx < SETTINGS_COUNT) + FlashErase((uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING); MemoryRecall(); } void MemoryRecall(void) { /* Recall memory from permanent flash */ - FlashToFRAM((uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING); + if (GlobalSettings.ActiveSettingIdx < SETTINGS_COUNT) + FlashToFRAM((uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, ActiveConfiguration.MemorySize); + + if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER) + ActiveConfiguration.ApplicationInitFunc(); SystemTickClearFlag(); } void MemoryStore(void) { /* Store current memory into permanent flash */ - FRAMToFlash((uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING); + if (GlobalSettings.ActiveSettingIdx < SETTINGS_COUNT) + FRAMToFlash((uint32_t) GlobalSettings.ActiveSettingIdx * MEMORY_SIZE_PER_SETTING, ActiveConfiguration.MemorySize); LEDHook(LED_MEMORY_CHANGED, LED_OFF); LEDHook(LED_MEMORY_STORED, LED_PULSE); @@ -394,7 +439,7 @@ void MemoryStore(void) { } bool MemoryUploadBlock(void *Buffer, uint32_t BlockAddress, uint16_t ByteCount) { - if (BlockAddress >= MEMORY_SIZE_PER_SETTING) { + if ((BlockAddress >= MEMORY_SIZE_PER_SETTING) || (BlockAddress >= ActiveConfiguration.MemorySize)) { /* Prevent writing out of bounds by silently ignoring it */ return true; } else { diff --git a/Firmware/Chameleon-Mini/Settings.c b/Firmware/Chameleon-Mini/Settings.c index 19c02ff..7d51681 100644 --- a/Firmware/Chameleon-Mini/Settings.c +++ b/Firmware/Chameleon-Mini/Settings.c @@ -1,3 +1,14 @@ +/* + * Settings.c + * + * Created on: 20.03.2013 + * Author: skuser + * + * ChangeLog + * 2019-09-22 Willok A special configuration has been added, which has no storage space and can only be used as a reader mode + * + */ + #include "Settings.h" #include #include "Configuration.h" @@ -8,9 +19,6 @@ #include "System.h" -#define SETTING_TO_INDEX(S) (S - SETTINGS_FIRST) -#define INDEX_TO_SETTING(I) (I + SETTINGS_FIRST) - SettingsType GlobalSettings; SettingsType EEMEM StoredSettings = { .ActiveSettingIdx = SETTING_TO_INDEX(DEFAULT_SETTING), @@ -27,13 +35,50 @@ SettingsType EEMEM StoredSettings = { .LEDRedFunction = DEFAULT_RED_LED_ACTION, .LEDGreenFunction = DEFAULT_GREEN_LED_ACTION, .PendingTaskTimeout = DEFAULT_PENDING_TASK_TIMEOUT, - .ReaderThreshold = DEFAULT_READER_THRESHOLD + .ReaderThreshold = DEFAULT_READER_THRESHOLD, + .bSakMode = 0, + }, + // In the last configuration, there is no storage space. This is used as the card reader mode only + [SETTINGS_COUNT] = + { + .Configuration = CONFIG_ISO14443A_READER, + .ButtonActions = { + [BUTTON_L_PRESS_SHORT] = DEFAULT_LBUTTON_ACTION, [BUTTON_R_PRESS_SHORT] = DEFAULT_RBUTTON_ACTION, + [BUTTON_L_PRESS_LONG] = DEFAULT_LBUTTON_ACTION, [BUTTON_R_PRESS_LONG] = DEFAULT_RBUTTON_ACTION + }, + .LogMode = DEFAULT_LOG_MODE, + .LEDRedFunction = DEFAULT_RED_LED_ACTION, + .LEDGreenFunction = DEFAULT_GREEN_LED_ACTION, + .PendingTaskTimeout = DEFAULT_PENDING_TASK_TIMEOUT, + .ReaderThreshold = DEFAULT_READER_THRESHOLD, + .bSakMode = 0, } } }; void SettingsLoad(void) { ReadEEPBlock((uint16_t) &StoredSettings, &GlobalSettings, sizeof(SettingsType)); + + if (GlobalSettings.ActiveSettingIdx > SETTINGS_COUNT || GlobalSettings.ActiveSettingPtr != &GlobalSettings.Settings[GlobalSettings.ActiveSettingIdx]) { + GlobalSettings.ActiveSettingIdx = SETTINGS_COUNT; + GlobalSettings.ActiveSettingPtr = &GlobalSettings.Settings[SETTINGS_COUNT]; + + for (int i = 0; i <= SETTINGS_COUNT; i++) { + GlobalSettings.Settings[i].Configuration = CONFIG_NONE; + GlobalSettings.Settings[i].ButtonActions[BUTTON_L_PRESS_SHORT] = DEFAULT_LBUTTON_ACTION; + GlobalSettings.Settings[i].ButtonActions[BUTTON_R_PRESS_SHORT] = DEFAULT_RBUTTON_ACTION; + GlobalSettings.Settings[i].ButtonActions[BUTTON_L_PRESS_LONG] = DEFAULT_LBUTTON_ACTION; + GlobalSettings.Settings[i].ButtonActions[BUTTON_R_PRESS_LONG] = DEFAULT_RBUTTON_ACTION; + GlobalSettings.Settings[i].LogMode = DEFAULT_LOG_MODE; + GlobalSettings.Settings[i].LEDRedFunction = DEFAULT_RED_LED_ACTION; + GlobalSettings.Settings[i].LEDGreenFunction = DEFAULT_GREEN_LED_ACTION; + GlobalSettings.Settings[i].PendingTaskTimeout = DEFAULT_PENDING_TASK_TIMEOUT; + GlobalSettings.Settings[i].ReaderThreshold = DEFAULT_READER_THRESHOLD; + } + GlobalSettings.Settings[SETTINGS_COUNT].Configuration = CONFIG_ISO14443A_READER; + + SettingsSave(); + } } void SettingsSave(void) { @@ -42,15 +87,19 @@ void SettingsSave(void) { #endif } -void SettingsCycle(void) { - uint8_t i = SETTINGS_COUNT; +void SettingsCycle(uint8_t bAdd) { uint8_t SettingIdx = GlobalSettings.ActiveSettingIdx; - while (i-- > 0) { - /* Try to set one of the SETTINGS_COUNT following settings. - * But only set if it is not CONFIG_NONE. */ - SettingIdx = (SettingIdx + 1) % SETTINGS_COUNT; - + for (uint8_t i = SETTINGS_COUNT; i > 0; i--) { + if (SettingIdx >= SETTINGS_COUNT) { + SettingIdx = 0; + i++; + } else { + if (bAdd) + SettingIdx = (SettingIdx + 1) % SETTINGS_COUNT; + else + SettingIdx = (SettingIdx + SETTINGS_COUNT - 1) % SETTINGS_COUNT; + } if (GlobalSettings.Settings[SettingIdx].Configuration != CONFIG_NONE) { SettingsSetActiveById(INDEX_TO_SETTING(SettingIdx)); break; @@ -59,7 +108,10 @@ void SettingsCycle(void) { } bool SettingsSetActiveById(uint8_t Setting) { - if ((Setting >= SETTINGS_FIRST) && (Setting <= SETTINGS_LAST)) { + uint8_t cSetting = Setting + '0'; + LogEntry(LOG_INFO_SETTING_SET, &cSetting, 1); + + if ((Setting >= SETTINGS_FIRST) && (Setting <= (SETTINGS_LAST + 1))) { uint8_t SettingIdx = SETTING_TO_INDEX(Setting); /* Break potentially pending timeout task (manual timeout) */ @@ -107,7 +159,7 @@ bool SettingsSetActiveByName(const char *Setting) { uint8_t SettingNr = Setting[0] - '0'; if (Setting[1] == '\0') { - LogEntry(LOG_INFO_SETTING_SET, Setting, 1); +// LogEntry(LOG_INFO_SETTING_SET, Setting, 1); return SettingsSetActiveById(SettingNr); } else { return false; diff --git a/Firmware/Chameleon-Mini/Settings.h b/Firmware/Chameleon-Mini/Settings.h index 37647d6..f793643 100644 --- a/Firmware/Chameleon-Mini/Settings.h +++ b/Firmware/Chameleon-Mini/Settings.h @@ -19,6 +19,9 @@ #define SETTINGS_FIRST 1 #define SETTINGS_LAST (SETTINGS_FIRST + SETTINGS_COUNT - 1) +#define SETTING_TO_INDEX(S) (S - SETTINGS_FIRST) +#define INDEX_TO_SETTING(I) (I + SETTINGS_FIRST) + /** Defines one setting. * * \note Some properties may change globally if this is defined in the Makefile. @@ -31,12 +34,13 @@ typedef struct { LEDHookEnum LEDGreenFunction; /// Green LED function for this setting. uint16_t PendingTaskTimeout; /// Timeout for timeout commands for this setting, in multiples of 100 ms. uint16_t ReaderThreshold; /// Reader threshold + uint8_t bSakMode; /// MifareCard SAK_ATQA Setting } SettingsEntryType; typedef struct { uint8_t ActiveSettingIdx; SettingsEntryType *ActiveSettingPtr; - SettingsEntryType Settings[SETTINGS_COUNT]; + SettingsEntryType Settings[SETTINGS_COUNT + 1]; } SettingsType; extern SettingsType GlobalSettings, StoredSettings; @@ -65,7 +69,7 @@ INLINE void SettingUpdate(const void *addr, uint16_t size) { void SettingsLoad(void); void SettingsSave(void); -void SettingsCycle(void); +void SettingsCycle(uint8_t bAdd); bool SettingsSetActiveById(uint8_t Setting); uint8_t SettingsGetActiveById(void); void SettingsGetActiveByName(char *SettingOut, uint16_t BufferSize); diff --git a/Firmware/Chameleon-Mini/System.c b/Firmware/Chameleon-Mini/System.c index 33f7e8c..a2b33ca 100644 --- a/Firmware/Chameleon-Mini/System.c +++ b/Firmware/Chameleon-Mini/System.c @@ -80,6 +80,17 @@ void SystemEnterBootloader(void) { } +bool SystemTick100ms(void) { + if (RTC.INTFLAGS & RTC_COMPIF_bm) { + while (RTC.STATUS & RTC_SYNCBUSY_bm) ; + + RTC.INTFLAGS = RTC_COMPIF_bm; + return true; + } + + return false; +} + void SystemStartUSBClock(void) { //SystemSleepDisable(); #if 0 diff --git a/Firmware/Chameleon-Mini/System.h b/Firmware/Chameleon-Mini/System.h index 96b0794..2884dbf 100644 --- a/Firmware/Chameleon-Mini/System.h +++ b/Firmware/Chameleon-Mini/System.h @@ -19,8 +19,9 @@ #define SYSTEM_MILLISECONDS_TO_RTC_CYCLES(x) \ ( (uint16_t) ( (double) F_RTC * x / 1E3 + 0.5) ) +// Tick about 120ms #define SYSTEM_TICK_WIDTH 7 /* Bits */ -#define SYSTEM_TICK_PERIOD (1<<7) +#define SYSTEM_TICK_PERIOD 106 /* (1<<7) */ #define SYSTEM_TICK_MS (SYSTEM_TICK_PERIOD) #define SYSTEM_TICK_FREQ (1000 / SYSTEM_TICK_PERIOD) @@ -36,19 +37,7 @@ void SystemEnterBootloader(void); void SystemStartUSBClock(void); void SystemStopUSBClock(void); void SystemInterruptInit(void); -INLINE bool SystemTick100ms(void); - -INLINE bool SystemTick100ms(void) { - if (RTC.INTFLAGS & RTC_COMPIF_bm) { - while (RTC.STATUS & RTC_SYNCBUSY_bm) - ; - - RTC.INTFLAGS = RTC_COMPIF_bm; - return true; - } - - return false; -} +bool SystemTick100ms(void); INLINE void SystemTickClearFlag(void) { while (RTC.STATUS & RTC_SYNCBUSY_bm) diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index 3982332..a91c84a 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -316,6 +316,20 @@ const PROGMEM CommandEntryType CommandTable[] = { .SetFunc = NO_FUNCTION, .GetFunc = NO_FUNCTION }, + { + .Command = COMMAND_SETUIDMODE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetUidMode, + .GetFunc = CommandGetUidMode + }, + { + .Command = COMMAND_SETSAKMODE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetSakMode, + .GetFunc = CommandGetSakMode + }, { /* This has to be last element */ .Command = COMMAND_LIST_END, @@ -323,6 +337,28 @@ const PROGMEM CommandEntryType CommandTable[] = { .ExecParamFunc = NO_FUNCTION, .SetFunc = NO_FUNCTION, .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_SETLEDMODE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetLedMode, + .GetFunc = CommandGetLedMode + }, + { + .Command = COMMAND_DETECTION, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetDetection, + .GetFunc = CommandGetDetection, + }, + { + .Command = COMMAND_BAUDRATE, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, +// .SetFunc = CommandSetBaudrate, + .SetFunc = NO_FUNCTION, + .GetFunc = CommandGetBaudrate, } }; diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index 8583d07..6811498 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -15,6 +15,7 @@ #include "../AntennaLevel.h" #include "../Battery.h" #include "../Codec/Codec.h" +#include "uartcmd.h" extern Reader14443Command Reader14443CurrentCommand; extern Sniff14443Command Sniff14443CurrentCommand; @@ -23,8 +24,10 @@ extern const PROGMEM CommandEntryType CommandTable[]; CommandStatusIdType CommandGetVersion(char *OutParam) { snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR( - "ChameleonMini RevG %S using LUFA %S compiled with AVR-GCC %S. Based on the open-source NFC tool ChameleonMini. https://github.com/emsec/ChameleonMini commit %S" - ), PSTR(CHAMELEON_MINI_VERSION_STRING), PSTR(LUFA_VERSION_STRING), PSTR(__VERSION__), PSTR(COMMIT_ID) +// "ChameleonMini RevG %S using LUFA %S compiled with AVR-GCC %S. Based on the open-source NFC tool ChameleonMini. https://github.com/emsec/ChameleonMini commit %S" +// ), PSTR(CHAMELEON_MINI_VERSION_STRING), PSTR(LUFA_VERSION_STRING), PSTR(__VERSION__), PSTR(COMMIT_ID) + "ChameleonMini RevG compiled at %S %S(%S) using LUFA %S with AVR-GCC %S." + ), PSTR(BUILD_DATE), PSTR(__TIME__), PSTR(COMMIT_ID), PSTR(LUFA_VERSION_STRING), PSTR(__VERSION__) ); return COMMAND_INFO_OK_WITH_TEXT_ID; @@ -608,3 +611,150 @@ CommandStatusIdType CommandExecClone(char *OutMessage) { return TIMEOUT_COMMAND; } + +extern uint32_t dwBaudRate; +CommandStatusIdType CommandGetBaudrate(char *OutParam) { + snprintf(OutParam, TERMINAL_BUFFER_SIZE, "%lu", dwBaudRate); + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +uint8_t uart_baudrate(uint32_t NewBaudrate); + +CommandStatusIdType CommandSetBaudrate(char *OutMessage, const char *InParam) { + uint32_t tmp = 0; + + if (!sscanf_P(InParam, PSTR("%ld"), &tmp) || tmp < 115200 || tmp > 921600) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("Set %ld Error.\r\n"), tmp); + return COMMAND_ERR_INVALID_PARAM_ID; + } + + if (0 == uart_baudrate(tmp)) { + TerminalSendStringP(PSTR("Invalid Baudrate.\r\nUse Default baudrate 460800.\r\n")); + } + + return COMMAND_INFO_OK_ID; +} + +// Send test command +void SendTestCmd(uint8_t bData) { + uint8_t Buffer[sizeof(CMD_HEAD)]; + PCMD_HEAD CmdHead = (PCMD_HEAD)Buffer; + uint8_t *pDataPtr = (uint8_t *)(CmdHead + 1); + + // Filling structure + CmdHead->bSign = 0xA5; + CmdHead->bCmd = CMD_BLE_TEST; + CmdHead->bCmdLen = 1; + pDataPtr[0] = bData; + CmdHead->bChkSum = GetChkSum(CmdHead, NULL); + + uart_putb((uint8_t *)CmdHead, sizeof(CMD_HEAD) + CmdHead->bCmdLen); +} + +extern uint8_t LedMode; +extern uint8_t bKeepAlive; +extern uint8_t bUSBTerminal; +// Set led mode +CommandStatusIdType CommandSetLedMode(char *OutMessage, const char *InParam) { + if (COMMAND_IS_SUGGEST_STRING(InParam)) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("%c,%c"), COMMAND_CHAR_TRUE, COMMAND_CHAR_FALSE); + return COMMAND_INFO_OK_WITH_TEXT_ID; + } + + switch (InParam[0]) { + case '0': // Close + LedMode = 0; + break; + case '1': // Open + LedMode = 1; + break; + case 'R': // State reset + bKeepAlive = 1; + break; + case 'T': // Test + SendTestCmd(InParam[1]); + break; + default: + return COMMAND_ERR_INVALID_PARAM_ID; + } + + return COMMAND_INFO_OK_ID; +} + +CommandStatusIdType CommandGetLedMode(char *OutMessage) { + if (LedMode) + OutMessage[0] = COMMAND_CHAR_TRUE; + else + OutMessage[0] = COMMAND_CHAR_FALSE; + + OutMessage[1] = '\0'; + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +extern uint8_t bUidMode; +extern uint8_t EEMEM bUidMode_EEP; +// UIDMODE Set tag mode orginal or magic back door +CommandStatusIdType CommandSetUidMode(char *OutMessage, const char *InParam) { + if (COMMAND_IS_SUGGEST_STRING(InParam)) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("%c,%c"), COMMAND_CHAR_TRUE, COMMAND_CHAR_FALSE); + return COMMAND_INFO_OK_WITH_TEXT_ID; + } + switch (InParam[0]) { + case '0': // Close + case '1': // Open magic back door mode + bUidMode = InParam[0] - '0'; + WriteEEPBlock((uint16_t) &bUidMode_EEP, &bUidMode, 1); + break; + default: + return COMMAND_ERR_INVALID_PARAM_ID; + break; + } + + return COMMAND_INFO_OK_ID; +} + +CommandStatusIdType CommandGetUidMode(char *OutMessage) { + OutMessage[0] = bUidMode + '0'; + OutMessage[1] = '\0'; + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +// SAKMODE Set Tag fix sak or changeable SAK ATQA +CommandStatusIdType CommandSetSakMode(char *OutMessage, const char *InParam) { + if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_MF_CLASSIC_1K && + GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_MF_CLASSIC_4K && + GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_MF_DETECTION && + GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_MF_DETECTION_4K) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + if (COMMAND_IS_SUGGEST_STRING(InParam)) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("%c,%c"), COMMAND_CHAR_TRUE, COMMAND_CHAR_FALSE); + return COMMAND_INFO_OK_WITH_TEXT_ID; + } + if (InParam[0] == '1') { + GlobalSettings.ActiveSettingPtr->bSakMode = 1; + } else if (InParam[0] == '0') { + GlobalSettings.ActiveSettingPtr->bSakMode = 0; + } else { + return COMMAND_ERR_INVALID_PARAM_ID; + } + + // save global configuration to EEPROM + SettingsSave(); + + // 重新应用 + ConfigurationSetById(GlobalSettings.ActiveSettingPtr->Configuration); + + + return COMMAND_INFO_OK_ID; +} + +CommandStatusIdType CommandGetSakMode(char *OutMessage) { + if (GlobalSettings.ActiveSettingPtr->bSakMode) + OutMessage[0] = COMMAND_CHAR_TRUE; + else + OutMessage[0] = COMMAND_CHAR_FALSE; + + OutMessage[1] = '\0'; + return COMMAND_INFO_OK_WITH_TEXT_ID; +} diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.h b/Firmware/Chameleon-Mini/Terminal/Commands.h index 93e08e0..8d4b786 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.h +++ b/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -187,7 +187,27 @@ CommandStatusIdType CommandGetField(char *OutMessage); #define COMMAND_CLONE "CLONE" CommandStatusIdType CommandExecClone(char *OutMessage); +#define COMMAND_SETUIDMODE "UIDMODE" +CommandStatusIdType CommandGetUidMode(char *OutMessage); +CommandStatusIdType CommandSetUidMode(char *OutMessage, const char *InParam); + +#define COMMAND_SETSAKMODE "SAKMODE" +CommandStatusIdType CommandGetSakMode(char *OutMessage); +CommandStatusIdType CommandSetSakMode(char *OutMessage, const char *InParam); + #define COMMAND_LIST_END "" /* Defines the end of command list. This is no actual command */ +#define COMMAND_DETECTION "DETECTION" +CommandStatusIdType CommandGetDetection(char *OutParam); +CommandStatusIdType CommandSetDetection(char *OutMessage, const char *InParam); + +#define COMMAND_BAUDRATE "BAUDRATE" +CommandStatusIdType CommandGetBaudrate(char *OutParam); +CommandStatusIdType CommandSetBaudrate(char *OutMessage, const char *InParam); + +#define COMMAND_SETLEDMODE "LEDMODE" +CommandStatusIdType CommandGetLedMode(char *OutMessage); +CommandStatusIdType CommandSetLedMode(char *OutMessage, const char *InParam); + #endif /* COMMANDS_H_ */ diff --git a/Firmware/Chameleon-Mini/Terminal/Terminal.c b/Firmware/Chameleon-Mini/Terminal/Terminal.c index 0c927ea..add3b3b 100644 --- a/Firmware/Chameleon-Mini/Terminal/Terminal.c +++ b/Firmware/Chameleon-Mini/Terminal/Terminal.c @@ -1,11 +1,12 @@ #include "Terminal.h" +#include "../Uart.h" #include "../System.h" #include "../LEDHook.h" #include "../LUFADescriptors.h" -#define INIT_DELAY (2000 / SYSTEM_TICK_MS) +#define INIT_DELAY (1000 / SYSTEM_TICK_MS) USB_ClassInfo_CDC_Device_t TerminalHandle = { @@ -27,44 +28,45 @@ USB_ClassInfo_CDC_Device_t TerminalHandle = { } }; +uint8_t bUSBTerminal = 0; uint8_t TerminalBuffer[TERMINAL_BUFFER_SIZE]; TerminalStateEnum TerminalState = TERMINAL_UNINITIALIZED; static uint8_t TerminalInitDelay = INIT_DELAY; -void TerminalSendString(const char *s) { - CDC_Device_SendString(&TerminalHandle, s); -} - -void TerminalSendStringP(const char *s) { - char c; - - while ((c = pgm_read_byte(s++)) != '\0') { - TerminalSendChar(c); +void TerminalSendByte(uint8_t Byte) { + if (bUSBTerminal) { + CDC_Device_SendByte(&TerminalHandle, Byte); + } else { + uart_fifo_put(&Byte, 1); } } -/* -void TerminalSendHex(void* Buffer, uint16_t ByteCount) -{ - char* pTerminalBuffer = (char*) TerminalBuffer; - - BufferToHexString(pTerminalBuffer, sizeof(TerminalBuffer), Buffer, ByteCount); - - TerminalSendString(pTerminalBuffer); +void TerminalSendString(const char *s) { + TerminalSendBlock(s, strlen(s)); } -*/ +void TerminalSendStringP(const char *s) { + char Byte; + while ((Byte = pgm_read_byte(s++)) != '\0') { + TerminalSendByte(Byte); + } +} void TerminalSendBlock(const void *Buffer, uint16_t ByteCount) { - CDC_Device_SendData(&TerminalHandle, Buffer, ByteCount); + if (bUSBTerminal) { + CDC_Device_SendData(&TerminalHandle, Buffer, ByteCount); + } else { + uart_fifo_put((uint8_t *)Buffer, ByteCount); + } } -static void ProcessByte(void) { +void ProcessByte(void) { int16_t Byte = CDC_Device_ReceiveByte(&TerminalHandle); if (Byte >= 0) { + bUSBTerminal = 1; /* Byte received */ LEDHook(LED_TERMINAL_RXTX, LED_PULSE); @@ -76,7 +78,7 @@ static void ProcessByte(void) { } } -static void SenseVBus(void) { +static void SenseVBusTick(void) { switch (TerminalState) { case TERMINAL_UNINITIALIZED: if (TERMINAL_VBUS_PORT.IN & TERMINAL_VBUS_MASK) { @@ -99,6 +101,7 @@ static void SenseVBus(void) { /* Initialized and VBUS sense low */ TerminalInitDelay = INIT_DELAY; TerminalState = TERMINAL_UNITIALIZING; + bUSBTerminal = 0; } break; @@ -129,7 +132,7 @@ void TerminalTask(void) { } void TerminalTick(void) { - SenseVBus(); + SenseVBusTick(); if (TerminalState == TERMINAL_INITIALIZED) { XModemTick(); diff --git a/Firmware/Chameleon-Mini/Terminal/Terminal.h b/Firmware/Chameleon-Mini/Terminal/Terminal.h index 53413af..955c515 100644 --- a/Firmware/Chameleon-Mini/Terminal/Terminal.h +++ b/Firmware/Chameleon-Mini/Terminal/Terminal.h @@ -34,10 +34,11 @@ void TerminalTask(void); void TerminalTick(void); /*void TerminalSendHex(void* Buffer, uint16_t ByteCount);*/ -INLINE void TerminalSendByte(uint8_t Byte); +//INLINE void TerminalSendByte(uint8_t Byte); +void TerminalSendByte(uint8_t Byte); void TerminalSendBlock(const void *Buffer, uint16_t ByteCount); - -INLINE void TerminalSendChar(char c); +//INLINE void TerminalSendChar(char c); +#define TerminalSendChar(x) TerminalSendByte((uint8_t)x) void TerminalSendString(const char *s); void TerminalSendStringP(const char *s); @@ -46,7 +47,4 @@ void EVENT_USB_Device_Disconnect(void); void EVENT_USB_Device_ConfigurationChanged(void); void EVENT_USB_Device_ControlRequest(void); -INLINE void TerminalSendChar(char c) { CDC_Device_SendByte(&TerminalHandle, c); } -INLINE void TerminalSendByte(uint8_t Byte) { CDC_Device_SendByte(&TerminalHandle, Byte); } - #endif /* TERMINAL_H_ */