From 1da44037c69957372f15c5b099b08fb2546e7f33 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 4 Dec 2018 18:00:37 +0100 Subject: [PATCH 01/14] Checked read and lock out of bound errors against real tag and implemented in software. Updated authors --- Firmware/Chameleon-Mini/Application/ISO15693-A.c | 2 ++ .../Chameleon-Mini/Application/TITagitstandard.c | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index 5135135..f8a36da 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -62,6 +62,8 @@ bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize) * - true: Frame is valid and a response is needed * - false: Request is not addressed to us * Frame is not valid because it's too short or CRC is wrong + * + * Authors: ceres-c & MrMoDDoM */ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid) { diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 8441907..f5618f5 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -4,10 +4,7 @@ * Created on: 01-03-2017 * Author: Phillip Nash * Modified by rickventura for texas 15693 tag-it STANDARD - * Modified by ceres-c to finish things up - * TODO: - * - Check actual tag's response (error?) when trying to WRITE out of bound sectors - * - Check actual tag's response (error?) when trying to LOCK out of bound sectors + * Modified by ceres-c & MrMoDDoM to finish things up */ #include "ISO15693-A.h" @@ -118,7 +115,8 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) break; /* malformed: not enough or too much data */ if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) - /* TODO: Check actual tag's response (error?) */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; break; /* malformed: trying to write in a non-existing block */ Dataptr = PageAddress + 0x01; @@ -144,7 +142,9 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) break; /* malformed: not enough or too much data */ if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) - /* TODO: Check actual tag's response (error?) */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = 2; break; /* malformed: trying to lock a non-existing block */ if ((FactoryLockBits_Mask & (1 << PageAddress)) || (UserLockBits_Mask & (1 << PageAddress))) { From b28d8cb337748df7cf11a121c07b229bef4b8744 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Mon, 10 Dec 2018 19:43:43 +0100 Subject: [PATCH 02/14] EM4233 first draft --- .../Chameleon-Mini/Application/Application.h | 2 +- Firmware/Chameleon-Mini/Application/EM4233.c | 241 ++++++++++++++++++ Firmware/Chameleon-Mini/Application/EM4233.h | 60 +++++ .../Chameleon-Mini/Application/ISO15693-A.h | 9 +- .../Application/TITagitstandard.c | 7 +- Firmware/Chameleon-Mini/Configuration.c | 23 +- Firmware/Chameleon-Mini/Configuration.h | 3 + Firmware/Chameleon-Mini/DUMP_TEST | Bin 0 -> 304 bytes Firmware/Chameleon-Mini/Makefile | 3 +- 9 files changed, 341 insertions(+), 7 deletions(-) create mode 100644 Firmware/Chameleon-Mini/Application/EM4233.c create mode 100644 Firmware/Chameleon-Mini/Application/EM4233.h create mode 100644 Firmware/Chameleon-Mini/DUMP_TEST diff --git a/Firmware/Chameleon-Mini/Application/Application.h b/Firmware/Chameleon-Mini/Application/Application.h index 6fca8b6..af0dd2a 100644 --- a/Firmware/Chameleon-Mini/Application/Application.h +++ b/Firmware/Chameleon-Mini/Application/Application.h @@ -20,7 +20,7 @@ #include "Sl2s2002.h" #include "TITagitstandard.h" #include "Sniff14443A.h" - +#include "EM4233.h" /* Function wrappers */ INLINE void ApplicationInit(void) { diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c new file mode 100644 index 0000000..a2fb430 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -0,0 +1,241 @@ +/* + * EM4233.c + * + * Created on: 12-05-2018 + * Author: ceres-c & MrMoDDoM + */ + +#include "ISO15693-A.h" +#include "EM4233.h" + +static enum { + STATE_READY, + STATE_SELECTED, + STATE_QUIET +} State; + +CurrentFrame FrameInfo; + +uint64_t EM4233_FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ +uint64_t EM4233_UserLockBits_Mask = 0; /* Holds lock state of blocks */ + +//uint8_t EM4233_Lock_Status[64] = { 1 }; + + +void EM4233AppInit(void) +{ + State = STATE_READY; + + FrameInfo.Flags = NULL; + FrameInfo.Command = NULL; + FrameInfo.Parameters = NULL; + FrameInfo.ParamLen = 0; + FrameInfo.Addressed = false; + + //MemoryReadBlock(EM4233_Lock_Status, EM4233_MEM_LSM_ADDRESS, 64); + //MemoryReadBlock(&EM4233_FactoryLockBits_Mask, EM4233_MEM_FLM_ADDRESS, 8); +} + +void EM4233AppReset(void) +{ + State = STATE_READY; + + FrameInfo.Flags = NULL; + FrameInfo.Command = NULL; + FrameInfo.Parameters = NULL; + FrameInfo.ParamLen = 0; + FrameInfo.Addressed = false; + + //MemoryReadBlock(&EM4233_UserLockBits_Mask, EM4233_MEM_ULM_ADDRESS, 8); + //MemoryReadBlock(&EM4233_FactoryLockBits_Mask, EM4233_MEM_FLM_ADDRESS, 8); +} + + +void EM4233AppTask(void) +{ + +} + +void EM4233AppTick(void) +{ + +} + +uint16_t EM4233_Lock_Block(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t PageAddress = *FrameInfo.Parameters; + + if (FrameInfo.ParamLen != 1) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + if (PageAddress > EM4233_NUMBER_OF_BLCKS) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = 2; + return ResponseByteCount; /* malformed: trying to lock a non-existing block */ + } + + if ((EM4233_FactoryLockBits_Mask & (uint64_t)(1 << PageAddress)) || (EM4233_UserLockBits_Mask & (uint64_t)(1 << PageAddress))) { /* if already locked */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_ALRD_LKD; + ResponseByteCount = 2; + } else { + EM4233_UserLockBits_Mask |= (uint64_t)(1 << PageAddress); /* write the lock status in mask */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + } + + return ResponseByteCount; +} + +uint16_t EM4233_Write_Single(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t* Dataptr; + uint8_t PageAddress = *FrameInfo.Parameters; + + if (FrameInfo.ParamLen != 5) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + if (PageAddress > EM4233_NUMBER_OF_BLCKS) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = 2; /* malformed: trying to write in a non-existing block */ + return ResponseByteCount; + } + + Dataptr = PageAddress + 0x01; + + if (EM4233_FactoryLockBits_Mask & (uint64_t)(1 << PageAddress)) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = 2; + } else if (EM4233_UserLockBits_Mask & (uint64_t)(1 << PageAddress)) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_CHG_LKD; + ResponseByteCount = 2; + } else { + MemoryWriteBlock(Dataptr, PageAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + } + + return ResponseByteCount; +} + +uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t *FramePtr; /* holds the address where block's data will be put */ + uint8_t PageAddress = *FrameInfo.Parameters; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 1) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + if (PageAddress >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a sector out of bound */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; /* real TiTag standard reply with this error */ + ResponseByteCount = 2; + return ResponseByteCount; + } + + if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + PageAddress), 1); + if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { /* tests if the n-th bit of the factory bitmask if set to 1 */ + FrameBuf[1] = 0x02; /* return bit 1 set as 1 (factory locked) */ + } else if (LockStatus & ISO15693_MASK_USER_LOCK) { /* tests if the n-th bit of the user bitmask if set to 1 */ + FrameBuf[1] = 0x01; /* return bit 0 set as 1 (user locked) */ + } else + FrameBuf[1] = 0x00; /* return lock status 00 (unlocked) */ + FramePtr = FrameBuf + 2; /* block's data from byte 2 */ + ResponseByteCount = 6; + } else { /* request with option flag not set */ + FramePtr = FrameBuf + 1; /* block's data from byte 1 */ + ResponseByteCount = 5; + } + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + MemoryReadBlock(FramePtr, PageAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); + + return ResponseByteCount; +} + +uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t Uid[ActiveConfiguration.UidSize]; + EM4233GetUid(Uid); + + if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid)) + return ISO15693_APP_NO_RESPONSE; + + switch(State) { + case STATE_READY: + if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_INVENTORY_DSFID; + ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid); + ResponseByteCount = 10; + + } else if (*FrameInfo.Command == ISO15693_CMD_STAY_QUIET && FrameInfo.Addressed) { + State = STATE_QUIET; + + } else if (*FrameInfo.Command == ISO15693_CMD_READ_SINGLE) { + ResponseByteCount = EM4233_Read_Single(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_WRITE_SINGLE) { + ResponseByteCount = EM4233_Write_Single(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) { + ResponseByteCount = EM4233_Lock_Block(FrameBuf, FrameBytes); + + } else { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP; + ResponseByteCount = 2; + } + break; + + case STATE_SELECTED: + /* TO-DO */ + break; + + case STATE_QUIET: + if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + State = STATE_READY; + + FrameInfo.Flags = NULL; + FrameInfo.Command = NULL; + FrameInfo.Parameters = NULL; + FrameInfo.ParamLen = 0; + FrameInfo.Addressed = false; + } + + break; + + default: + break; + } + + if (ResponseByteCount > 0) { + /* There is data to be sent. Append CRC */ + ISO15693AppendCRC(FrameBuf, ResponseByteCount); + ResponseByteCount += ISO15693_CRC16_SIZE; + } + + return ResponseByteCount; +} + +void EM4233GetUid(ConfigurationUidType Uid) +{ + MemoryReadBlock(&Uid[0], EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize); +} + +void EM4233SetUid(ConfigurationUidType Uid) +{ + MemoryWriteBlock(Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize); +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h new file mode 100644 index 0000000..9e75160 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -0,0 +1,60 @@ +/* + * EM4233.h + * + * Created on: 04.12.2018 + * Author: ceres-c & MrMoDDoM + */ + +#ifndef EM4233_H_ +#define EM4233_H_ + +#include "Application.h" + +#define EM4233_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE +#define EM4233_STD_MEM_SIZE 256 // Bytes +#define EM4233_BYTES_PER_BLCK 4 +#define EM4233_BLCKS_PER_PAGE 4 +#define EM4233_NUMBER_OF_BLCKS ( EM4233_STD_MEM_SIZE / EM4233_BYTES_PER_BLCK ) +#define EM4233_NUMBER_OF_PAGES ( EM4233_STD_MEM_SIZE / (EM4233_BYTES_PER_BLCK * EM4233_BLCKS_PER_PAGE) ) + +#define EM4233_USR_MEM_SIZE 64 // Bytes, guessed, not described anywere +#define EM4233_MEM_UID_ADDRESS 0x0100 // From 0x0100 to 0x0107 - UID +#define EM4233_MEM_LSM_ADDRESS 0x0108 // From 0x0108 to 0x014F - Lock status masks +#define EM4233_MEM_PSW_ADDRESS 0x0150 // From 0x0118 to 0x011F - Password +#define EM4233_MEM_KEY_ADDRESS 0x0120 // From 0x0120 to 0x0127 - Encryption Key + +#define EM4233_MASK_READ_PROT ( 1 << 2 ) // For lock status byte +#define EM4233_MASK_WRITE_PROT ( 1 << 3 ) + +#define EM4233_TOT_MEM_SIZE ( EM4233_STD_MEM_SIZE + EM4233_USR_MEM_SIZE ) + +/* Custom command code */ +#define EM4233_CMD_SET_EAS 0xA2 +#define EM4233_CMD_RST_EAS 0xA3 +#define EM4233_CMD_LCK_EAS 0xA4 +#define EM4233_CMD_ACT_EAS 0xA5 +#define EM4233_CMD_PRT_EAS 0xA6 +#define EM4233_CMD_WRT_EAS_ID 0xA7 +#define EM4233_CMD_WRT_EAS_CFG 0xA8 +#define EM4233_CMD_WRT_PSW 0xB4 +#define EM4233_CMD_WRT_MEM_PAG 0xB6 +#define EM4233_CMD_GET_BLKS_PRT_STS 0xB8 +#define EM4233_CMD_DESTROY 0xB9 +#define EM4233_CMD_ENABLE_PRCY 0xBA +#define EM4233_CMD_DISBLE_PRCY 0xBB +#define EM4233_CMD_FST_READ_BLKS 0xC3 + +/* Proprietary command code */ +#define EM4233_CMD_LOGIN 0xE4 + + +void EM4233AppInit(void); +void EM4233AppReset(void); +void EM4233AppTask(void); +void EM4233AppTick(void); +uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes); +void EM4233GetUid(ConfigurationUidType Uid); +void EM4233SetUid(ConfigurationUidType Uid); +void EM4233FlipUid(ConfigurationUidType Uid); + +#endif /* EM4233_H_ */ diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index 936dbe4..72e0d9f 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -68,10 +68,17 @@ #define ISO15693_GENERIC_UID_SIZE 0x08 #define ISO15693_GENERIC_MEM_SIZE 8192 -#define ISO15693_CRC16_SIZE 2 /* Bytes */ +#define ISO15693_CRC16_SIZE 0x2 /* Bytes */ #define ISO15693_CRC16_POLYNORMAL 0x8408 #define ISO15693_CRC16_PRESET 0xFFFF +/* + * The byte used for the lock status has its bits addressed as follow: + * + */ +#define ISO15693_MASK_FACTORY_LOCK ( 1 << 0 ) +#define ISO15693_MASK_USER_LOCK ( 1 << 1 ) + typedef struct { uint8_t* Flags; uint8_t* Command; diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index f5618f5..80ae1a2 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -114,10 +114,12 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) if (FrameInfo.ParamLen != 5) break; /* malformed: not enough or too much data */ - if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) + if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = 2; break; /* malformed: trying to write in a non-existing block */ + } Dataptr = PageAddress + 0x01; @@ -141,11 +143,12 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) if (FrameInfo.ParamLen != 1) break; /* malformed: not enough or too much data */ - if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) + if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; ResponseByteCount = 2; break; /* malformed: trying to lock a non-existing block */ + } if ((FactoryLockBits_Mask & (1 << PageAddress)) || (UserLockBits_Mask & (1 << PageAddress))) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 2731cfc..35b0de5 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -46,10 +46,12 @@ static const MapEntryType PROGMEM ConfigurationMap[] = { #ifdef CONFIG_SL2S2002_SUPPORT { .Id = CONFIG_SL2S2002, .Text = "SL2S2002" }, #endif - #ifdef CONFIG_TITAGITSTANDARD_SUPPORT { .Id = CONFIG_TITAGITSTANDARD, .Text = "TITAGITSTANDARD" }, #endif +#ifdef CONFIG_EM4233_SUPPORT + { .Id = CONFIG_EM4233, .Text = "EM4233" }, +#endif }; /* Include all Codecs and Applications */ @@ -297,7 +299,6 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .TagFamily = TAG_FAMILY_ISO15693 }, #endif - #ifdef CONFIG_TITAGITSTANDARD_SUPPORT [CONFIG_TITAGITSTANDARD] = { .CodecInitFunc = ISO15693CodecInit, @@ -316,6 +317,24 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .TagFamily = TAG_FAMILY_ISO15693 }, #endif +#ifdef CONFIG_EM4233_SUPPORT + [CONFIG_EM4233] = { + .CodecInitFunc = ISO15693CodecInit, + .CodecDeInitFunc = ISO15693CodecDeInit, + .CodecTaskFunc = ISO15693CodecTask, + .ApplicationInitFunc = EM4233AppInit, + .ApplicationResetFunc = EM4233AppReset, + .ApplicationTaskFunc = EM4233AppTask, + .ApplicationTickFunc = EM4233AppTick, + .ApplicationProcessFunc = EM4233AppProcess, + .ApplicationGetUidFunc = EM4233GetUid, + .ApplicationSetUidFunc = EM4233SetUid, + .UidSize = EM4233_STD_UID_SIZE, + .MemorySize = EM4233_STD_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO15693 + }, +#endif }; ConfigurationType ActiveConfiguration; diff --git a/Firmware/Chameleon-Mini/Configuration.h b/Firmware/Chameleon-Mini/Configuration.h index 7f8b91a..9d53936 100644 --- a/Firmware/Chameleon-Mini/Configuration.h +++ b/Firmware/Chameleon-Mini/Configuration.h @@ -54,6 +54,9 @@ typedef enum { #endif #ifdef CONFIG_TITAGITSTANDARD_SUPPORT CONFIG_TITAGITSTANDARD, +#endif +#ifdef CONFIG_EM4233_SUPPORT + CONFIG_EM4233, #endif /* This HAS to be the last element */ CONFIG_COUNT diff --git a/Firmware/Chameleon-Mini/DUMP_TEST b/Firmware/Chameleon-Mini/DUMP_TEST new file mode 100644 index 0000000000000000000000000000000000000000..afaba814cb8c50804cf382e1694caeee59185b29 GIT binary patch literal 304 zcmZ3526m%?Gicy08hD2W{-Xgj<5!^>zZ=c?Gib)&MKk^#n(_Yy(SQ;fFh&CmXyAcZ W7rT&2SOvrS=b? Date: Fri, 14 Dec 2018 17:02:15 +0100 Subject: [PATCH 03/14] Fixed some bugs and implemented almost all optionnal ISO standard commands --- Firmware/Chameleon-Mini/Application/EM4233.c | 371 +++++++++++++++--- Firmware/Chameleon-Mini/Application/EM4233.h | 17 +- .../Chameleon-Mini/Application/ISO15693-A.c | 9 +- .../Chameleon-Mini/Application/ISO15693-A.h | 7 +- .../Application/TITagitstandard.c | 2 + 5 files changed, 349 insertions(+), 57 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index a2fb430..f9251f1 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -19,9 +19,6 @@ CurrentFrame FrameInfo; uint64_t EM4233_FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ uint64_t EM4233_UserLockBits_Mask = 0; /* Holds lock state of blocks */ -//uint8_t EM4233_Lock_Status[64] = { 1 }; - - void EM4233AppInit(void) { State = STATE_READY; @@ -31,9 +28,7 @@ void EM4233AppInit(void) FrameInfo.Parameters = NULL; FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; - - //MemoryReadBlock(EM4233_Lock_Status, EM4233_MEM_LSM_ADDRESS, 64); - //MemoryReadBlock(&EM4233_FactoryLockBits_Mask, EM4233_MEM_FLM_ADDRESS, 8); + FrameInfo.Selected = false; } void EM4233AppReset(void) @@ -45,12 +40,9 @@ void EM4233AppReset(void) FrameInfo.Parameters = NULL; FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; - - //MemoryReadBlock(&EM4233_UserLockBits_Mask, EM4233_MEM_ULM_ADDRESS, 8); - //MemoryReadBlock(&EM4233_FactoryLockBits_Mask, EM4233_MEM_FLM_ADDRESS, 8); + FrameInfo.Selected = false; } - void EM4233AppTask(void) { @@ -70,20 +62,20 @@ uint16_t EM4233_Lock_Block(uint8_t* FrameBuf, uint16_t FrameBytes) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ if (PageAddress > EM4233_NUMBER_OF_BLCKS) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; - ResponseByteCount = 2; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; /* malformed: trying to lock a non-existing block */ } if ((EM4233_FactoryLockBits_Mask & (uint64_t)(1 << PageAddress)) || (EM4233_UserLockBits_Mask & (uint64_t)(1 << PageAddress))) { /* if already locked */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_ALRD_LKD; - ResponseByteCount = 2; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_ALRD_LKD; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ } else { EM4233_UserLockBits_Mask |= (uint64_t)(1 << PageAddress); /* write the lock status in mask */ FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - ResponseByteCount = 1; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ } return ResponseByteCount; @@ -94,31 +86,33 @@ uint16_t EM4233_Write_Single(uint8_t* FrameBuf, uint16_t FrameBytes) uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; uint8_t* Dataptr; uint8_t PageAddress = *FrameInfo.Parameters; + uint8_t LockStatus = 0; if (FrameInfo.ParamLen != 5) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ if (PageAddress > EM4233_NUMBER_OF_BLCKS) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; - ResponseByteCount = 2; /* malformed: trying to write in a non-existing block */ - return ResponseByteCount; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ + return ResponseByteCount; /* malformed: trying to write in a non-existing block */ } + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + PageAddress), 1); Dataptr = PageAddress + 0x01; - if (EM4233_FactoryLockBits_Mask & (uint64_t)(1 << PageAddress)) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; - ResponseByteCount = 2; - } else if (EM4233_UserLockBits_Mask & (uint64_t)(1 << PageAddress)) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_CHG_LKD; - ResponseByteCount = 2; + if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway - probably: no factory lock exists? */ + } else if (LockStatus & ISO15693_MASK_USER_LOCK) { + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_CHG_LKD; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ } else { MemoryWriteBlock(Dataptr, PageAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - ResponseByteCount = 1; + ResponseByteCount += 1; } return ResponseByteCount; @@ -127,7 +121,7 @@ uint16_t EM4233_Write_Single(uint8_t* FrameBuf, uint16_t FrameBytes) uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) { uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; - uint8_t *FramePtr; /* holds the address where block's data will be put */ + uint8_t FramePtr; /* holds the address where block's data will be put */ uint8_t PageAddress = *FrameInfo.Parameters; uint8_t LockStatus = 0; @@ -135,30 +129,293 @@ uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ if (PageAddress >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a sector out of bound */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; /* real TiTag standard reply with this error */ - ResponseByteCount = 2; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } + FramePtr = 1; + if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + PageAddress), 1); if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { /* tests if the n-th bit of the factory bitmask if set to 1 */ - FrameBuf[1] = 0x02; /* return bit 1 set as 1 (factory locked) */ + FrameBuf[FramePtr] = 0x02; /* return bit 1 set as 1 (factory locked) */ } else if (LockStatus & ISO15693_MASK_USER_LOCK) { /* tests if the n-th bit of the user bitmask if set to 1 */ - FrameBuf[1] = 0x01; /* return bit 0 set as 1 (user locked) */ + FrameBuf[FramePtr] = 0x01; /* return bit 0 set as 1 (user locked) */ } else - FrameBuf[1] = 0x00; /* return lock status 00 (unlocked) */ - FramePtr = FrameBuf + 2; /* block's data from byte 2 */ - ResponseByteCount = 6; - } else { /* request with option flag not set */ - FramePtr = FrameBuf + 1; /* block's data from byte 1 */ - ResponseByteCount = 5; + FrameBuf[FramePtr] = 0x00; /* return lock status 00 (unlocked) */ + FramePtr += 1; /* block's data from byte 2 */ + ResponseByteCount += 1; + } + + MemoryReadBlock(&FrameBuf[FramePtr], PageAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); + ResponseByteCount += 4; + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + + return ResponseByteCount; +} + +uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t FramePtr; /* holds the address where block's data will be put */ + uint8_t BlockAddress = FrameInfo.Parameters[0]; + uint8_t BlocksNumber = 0; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 2) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + BlocksNumber = FrameInfo.Parameters[1]; + + if (BlockAddress >= EM4233_NUMBER_OF_BLCKS || (BlockAddress + BlocksNumber) >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a sector out of bound */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; /* real TiTag standard reply with this error */ + ResponseByteCount += 2; + return ResponseByteCount; + } + + FramePtr = 1; /* Start of response data */ + + for (uint8_t blk = 0; blk <= BlocksNumber; blk++) { + if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + (BlockAddress + blk)), 1); + + if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { /* tests if the n-th bit of the factory bitmask if set to 1 */ + FrameBuf[FramePtr] = 0x02; /* return bit 1 set as 1 (factory locked) */ + } else if (LockStatus & ISO15693_MASK_USER_LOCK) { /* tests if the n-th bit of the user bitmask if set to 1 */ + FrameBuf[FramePtr] = 0x01; /* return bit 0 set as 1 (user locked) */ + } else + FrameBuf[FramePtr] = 0x00; /* return lock status 00 (unlocked) */ + + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + + } + + MemoryReadBlock(&FrameBuf[FramePtr], (BlockAddress + blk ) * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); + FramePtr += 4; /* Move forward the buffer data pointer */ + ResponseByteCount += 4; /* Increment the response count */ + } + + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + return ResponseByteCount; +} + +uint16_t EM4233_Write_AFI(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t AFI = FrameInfo.Parameters[0]; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 1) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + MemoryReadBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); + + if (LockStatus & EM4233_MASK_AFI_STATUS ) { /* The afi is locked */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount += 2; + return ResponseByteCount; + } + + MemoryWriteBlock(&AFI, EM4233_MEM_AFI_ADDRESS, 1); /* Actually write new AFI */ + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + return ResponseByteCount; +} + +uint16_t EM4233_Lock_AFI(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 0) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + MemoryReadBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); + + if (LockStatus & EM4233_MASK_AFI_STATUS ) { /* The afi is already locked */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount += 2; + return ResponseByteCount; + } + + LockStatus |= EM4233_MASK_AFI_STATUS; + + MemoryWriteBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); /* Actually write new AFI */ + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + return ResponseByteCount; +} + +uint16_t EM4233_Write_DSFID(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t DSFID = FrameInfo.Parameters[0]; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 1) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + MemoryReadBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); + + if (LockStatus & EM4233_MASK_DSFID_STATUS ) { /* The afi is locked */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount += 2; + return ResponseByteCount; + } + + MemoryWriteBlock(&DSFID, EM4233_MEM_DSFID_ADDRESS, 1); /* Actually write new AFI */ + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + return ResponseByteCount; +} + +uint16_t EM4233_Lock_DSFID(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 0) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + MemoryReadBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); + + if (LockStatus & EM4233_MASK_DSFID_STATUS ) { /* The afi is already locked */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount += 2; + return ResponseByteCount; + } + + LockStatus |= EM4233_MASK_DSFID_STATUS; + + MemoryWriteBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); /* Actually write new AFI */ + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + return ResponseByteCount; +} + +uint8_t EM4233_Get_SysInfo(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t FramePtr; /* holds the address where block's data will be put */ + + if (FrameInfo.ParamLen != 0) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + FramePtr = 1; + + /* I've no idea how this request could generate errors ._. + if ( ) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount += 2; + return ResponseByteCount; + } + */ + + /* System info flags */ + FrameBuf[FramePtr] = EM4233_SYSINFO_BYTE; /* check pdf for this */ + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + + /* Then append UID */ + uint8_t Uid[ActiveConfiguration.UidSize]; + EM4233GetUid(Uid); + ISO15693CopyUid(&FrameBuf[FramePtr], Uid); + FramePtr += ISO15693_GENERIC_UID_SIZE; /* Move forward the buffer data pointer */ + ResponseByteCount += ISO15693_GENERIC_UID_SIZE; /* Increment the response count */ + + /* Append DSFID */ + if ( EM4233_SYSINFO_BYTE & ( 1 << 0 )) { + MemoryReadBlock(&FrameBuf[FramePtr], EM4233_MEM_DSFID_ADDRESS, 1); + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + } + + /* Append AFI */ + if ( EM4233_SYSINFO_BYTE & ( 1 << 1 )) { + MemoryReadBlock(&FrameBuf[FramePtr], EM4233_MEM_AFI_ADDRESS, 1); + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + } + + /* Append VICC memory size */ + if ( EM4233_SYSINFO_BYTE & ( 1 << 2 )) { + FrameBuf[FramePtr] = EM4233_NUMBER_OF_BLCKS - 0x01; + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + + FrameBuf[FramePtr] = EM4233_BYTES_PER_BLCK - 0x01; + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + } + + /* Append IC reference */ + if ( EM4233_SYSINFO_BYTE & ( 1 << 3 )) { + FrameBuf[FramePtr] = EM4233_IC_REFERENCE; + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ } FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - MemoryReadBlock(FramePtr, PageAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); + ResponseByteCount += 1; + return ResponseByteCount; +} +uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t FramePtr; /* holds the address where block's data will be put */ + uint8_t BlockAddress = FrameInfo.Parameters[0]; + uint8_t BlocksNumber = 0; + uint8_t LockStatus = 0; + + if (FrameInfo.ParamLen != 2) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + BlocksNumber = FrameInfo.Parameters[1]; + + if (BlockAddress >= EM4233_NUMBER_OF_BLCKS || (BlockAddress + BlocksNumber) >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a sector out of bound */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; /* real TiTag standard reply with this error */ + ResponseByteCount += 2; + return ResponseByteCount; + } + + FramePtr = 1; /* Start of response data */ + + for (uint8_t blk = 0; blk <= BlocksNumber; blk++) { + + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + (BlockAddress + blk)), 1); + + if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { /* tests if the n-th bit of the factory bitmask if set to 1 */ + FrameBuf[FramePtr] = 0x02; /* return bit 1 set as 1 (factory locked) */ + } else if (LockStatus & ISO15693_MASK_USER_LOCK) { /* tests if the n-th bit of the user bitmask if set to 1 */ + FrameBuf[FramePtr] = 0x01; /* return bit 0 set as 1 (user locked) */ + } else + FrameBuf[FramePtr] = 0x00; /* return lock status 00 (unlocked) */ + + FramePtr += 1; /* Move forward the buffer data pointer */ + ResponseByteCount += 1; /* Increment the response count */ + } + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; return ResponseByteCount; } @@ -175,7 +432,7 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) case STATE_READY: if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_INVENTORY_DSFID; + MemoryReadBlock(&FrameBuf[ISO15693_RES_ADDR_PARAM], EM4233_MEM_DSFID_ADDRESS, 1); ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid); ResponseByteCount = 10; @@ -191,6 +448,27 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) } else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) { ResponseByteCount = EM4233_Lock_Block(FrameBuf, FrameBytes); + } else if (*FrameInfo.Command == ISO15693_CMD_READ_MULTIPLE) { + ResponseByteCount = EM4233_Read_Multiple(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_WRITE_AFI) { + ResponseByteCount = EM4233_Write_AFI(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_LOCK_AFI) { + ResponseByteCount = EM4233_Lock_AFI(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_WRITE_DSFID) { + ResponseByteCount = EM4233_Write_DSFID(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_LOCK_DSFID) { + ResponseByteCount = EM4233_Lock_DSFID(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_GET_SYS_INFO) { + ResponseByteCount = EM4233_Get_SysInfo(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_GET_BLOCK_SEC) { + ResponseByteCount = EM4233_Get_Multi_Block_Sec_Stat(FrameBuf, FrameBytes); + } else { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP; @@ -198,10 +476,6 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) } break; - case STATE_SELECTED: - /* TO-DO */ - break; - case STATE_QUIET: if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; @@ -213,6 +487,7 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) FrameInfo.Parameters = NULL; FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; + FrameInfo.Selected = false; } break; diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h index 9e75160..7179673 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.h +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -12,19 +12,30 @@ #define EM4233_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE #define EM4233_STD_MEM_SIZE 256 // Bytes -#define EM4233_BYTES_PER_BLCK 4 -#define EM4233_BLCKS_PER_PAGE 4 +#define EM4233_BYTES_PER_BLCK 0x4 +#define EM4233_BLCKS_PER_PAGE 0x4 #define EM4233_NUMBER_OF_BLCKS ( EM4233_STD_MEM_SIZE / EM4233_BYTES_PER_BLCK ) #define EM4233_NUMBER_OF_PAGES ( EM4233_STD_MEM_SIZE / (EM4233_BYTES_PER_BLCK * EM4233_BLCKS_PER_PAGE) ) +#define EM4233_IC_REFERENCE 0x02 + #define EM4233_USR_MEM_SIZE 64 // Bytes, guessed, not described anywere #define EM4233_MEM_UID_ADDRESS 0x0100 // From 0x0100 to 0x0107 - UID -#define EM4233_MEM_LSM_ADDRESS 0x0108 // From 0x0108 to 0x014F - Lock status masks +#define EM4233_MEM_AFI_ADDRESS 0x0108 // AFI byte address +#define EM4233_MEM_DSFID_ADDRESS 0x0109 // DSFID byte adress +#define EM4233_MEM_INF_ADDRESS 0x010C // Some status bits + +#define EM4233_MEM_LSM_ADDRESS 0x0110 // From 0x0108 to 0x0157 - Lock status masks #define EM4233_MEM_PSW_ADDRESS 0x0150 // From 0x0118 to 0x011F - Password #define EM4233_MEM_KEY_ADDRESS 0x0120 // From 0x0120 to 0x0127 - Encryption Key +#define EM4233_SYSINFO_BYTE 0x0F // DSFID - AFI - VICC mem size - IC ref are present + +/* Bit masks */ #define EM4233_MASK_READ_PROT ( 1 << 2 ) // For lock status byte #define EM4233_MASK_WRITE_PROT ( 1 << 3 ) +#define EM4233_MASK_AFI_STATUS ( 1 << 0 ) +#define EM4233_MASK_DSFID_STATUS ( 1 << 1 ) #define EM4233_TOT_MEM_SIZE ( EM4233_STD_MEM_SIZE + EM4233_USR_MEM_SIZE ) diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index f8a36da..373a739 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -75,17 +75,20 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct -> Flags = &FrameBuf[ISO15693_ADDR_FLAGS]; FrameStruct -> Command = &FrameBuf[ISO15693_REQ_ADDR_CMD]; - if(!(FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_INVENTORY)) /* if inventory flag is not set */ + if(!(FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_INVENTORY)) { /* if inventory flag is not set */ FrameStruct -> Addressed = (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_ADDRESS); /* check for addressed flag */ - else /* otherwise always false */ + FrameStruct -> Selected = (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_SELECT); /* check for selected flag */ + } else { /* otherwise always false */ FrameStruct -> Addressed = false; + FrameStruct -> Selected = false; + } if (FrameStruct -> Addressed) /* UID sits between CMD and PARAM */ FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM + ISO15693_GENERIC_UID_SIZE]; else FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM]; - + FrameStruct -> ParamLen = FrameBuf + (FrameBytes - ISO15693_CRC16_SIZE) - (FrameStruct -> Parameters); if (FrameStruct -> Addressed && !ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], MyUid)) { diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index 72e0d9f..ac8fc31 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -63,7 +63,7 @@ #define ISO15693_RES_INVENTORY_DSFID 0x00 -#define ISO15693_MIN_FRAME_SIZE 0x05 +#define ISO15693_MIN_FRAME_SIZE 0x04 #define ISO15693_GENERIC_UID_SIZE 0x08 #define ISO15693_GENERIC_MEM_SIZE 8192 @@ -76,8 +76,8 @@ * The byte used for the lock status has its bits addressed as follow: * */ -#define ISO15693_MASK_FACTORY_LOCK ( 1 << 0 ) -#define ISO15693_MASK_USER_LOCK ( 1 << 1 ) +#define ISO15693_MASK_USER_LOCK ( 1 << 0 ) +#define ISO15693_MASK_FACTORY_LOCK ( 1 << 1 ) typedef struct { uint8_t* Flags; @@ -85,6 +85,7 @@ typedef struct { uint8_t* Parameters; uint8_t ParamLen; bool Addressed; + bool Selected; } CurrentFrame; void ISO15693AppendCRC(uint8_t* FrameBuf, uint16_t FrameBufSize); diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 80ae1a2..3208bf6 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -32,6 +32,7 @@ void TITagitstandardAppInit(void) FrameInfo.Parameters = NULL; FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; + FrameInfo.Selected = false; } void TITagitstandardAppReset(void) @@ -43,6 +44,7 @@ void TITagitstandardAppReset(void) FrameInfo.Parameters = NULL; FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; + FrameInfo.Selected = false; } From 0dfbe01b28bcd60103d9de196bebe023d8484b49 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Fri, 14 Dec 2018 21:41:36 +0100 Subject: [PATCH 04/14] Added EM4233 example dump and bug fixes --- Dumps/EM4233_example.dmp | Bin 0 -> 352 bytes Firmware/Chameleon-Mini/Application/EM4233.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 Dumps/EM4233_example.dmp diff --git a/Dumps/EM4233_example.dmp b/Dumps/EM4233_example.dmp new file mode 100644 index 0000000000000000000000000000000000000000..7e87a0699926a0fc6571893f6a936792318e5649 GIT binary patch literal 352 zcmZ3526m%?Gicy08hD2W{-Xgj<5!^>zZ=c?Gib)&MKk^#n(_Yy(SQ;fFh&CmXyAdE S3fM>nCWr(hg#c_A5&-~iuDl2U literal 0 HcmV?d00001 diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h index 7179673..48357da 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.h +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -27,7 +27,7 @@ #define EM4233_MEM_LSM_ADDRESS 0x0110 // From 0x0108 to 0x0157 - Lock status masks #define EM4233_MEM_PSW_ADDRESS 0x0150 // From 0x0118 to 0x011F - Password -#define EM4233_MEM_KEY_ADDRESS 0x0120 // From 0x0120 to 0x0127 - Encryption Key +#define EM4233_MEM_KEY_ADDRESS 0x0154 // From 0x0120 to 0x0127 - Encryption Key #define EM4233_SYSINFO_BYTE 0x0F // DSFID - AFI - VICC mem size - IC ref are present From aa237f0767480fdc00e3f783ade978b502e713f3 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 18 Dec 2018 00:13:57 +0100 Subject: [PATCH 05/14] Implemented Select command and fixed PrepareFrame to be compliant with Custom and Proprietary commands --- Firmware/Chameleon-Mini/Application/EM4233.c | 60 +++++++++++++++---- .../Chameleon-Mini/Application/ISO15693-A.c | 12 +++- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index f9251f1..75e6684 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -123,7 +123,7 @@ uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; uint8_t FramePtr; /* holds the address where block's data will be put */ uint8_t PageAddress = *FrameInfo.Parameters; - uint8_t LockStatus = 0; + uint8_t LockStatus = 0; if (FrameInfo.ParamLen != 1) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ @@ -164,7 +164,7 @@ uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) uint8_t FramePtr; /* holds the address where block's data will be put */ uint8_t BlockAddress = FrameInfo.Parameters[0]; uint8_t BlocksNumber = 0; - uint8_t LockStatus = 0; + uint8_t LockStatus = 0; if (FrameInfo.ParamLen != 2) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ @@ -419,6 +419,36 @@ uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t* FrameBuf, uint16_t FrameBytes) return ResponseByteCount; } +uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) +{ + /* I've no idea how this request could generate errors ._. + if ( ) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount += 2; + return ResponseByteCount; + } + */ + + bool UidEquals = ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid); + + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + if (!FrameInfo.Addressed || FrameInfo.Selected) { + /* tag should remain silent if Select is performed without address flag or with select flag */ + return ISO15693_APP_NO_RESPONSE; + } else if (State == STATE_SELECTED && !UidEquals) { + /* tag should remain silent if Select is performed while the tag is selected but against another tag */ + State == STATE_READY; + return ISO15693_APP_NO_RESPONSE; + } else if (State != STATE_SELECTED && !UidEquals) { + /* tag should remain silent if Select is performed against another UID */ + return ISO15693_APP_NO_RESPONSE; + } else if (State != STATE_SELECTED && UidEquals) { + State == STATE_SELECTED; + return ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ + } +} + uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) { uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; @@ -428,8 +458,14 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid)) return ISO15693_APP_NO_RESPONSE; - switch(State) { - case STATE_READY: + FrameBuf[ISO15693_ADDR_FLAGS] = FrameInfo.ParamLen; + ResponseByteCount = 1; + ISO15693AppendCRC(FrameBuf, ResponseByteCount); + ResponseByteCount += ISO15693_CRC16_SIZE; + return ResponseByteCount; + + + if (State == STATE_READY || State == STATE_SELECTED) { if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; MemoryReadBlock(&FrameBuf[ISO15693_RES_ADDR_PARAM], EM4233_MEM_DSFID_ADDRESS, 1); @@ -468,15 +504,20 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) } else if (*FrameInfo.Command == ISO15693_CMD_GET_BLOCK_SEC) { ResponseByteCount = EM4233_Get_Multi_Block_Sec_Stat(FrameBuf, FrameBytes); + + } else if (*FrameInfo.Command == ISO15693_CMD_SELECT) { + ResponseByteCount = EM4233_Select(FrameBuf, FrameBytes, Uid); + + } else if (*FrameInfo.Command == EM4233_CMD_LOGIN) { + // ResponseByteCount = EM4233_Select(FrameBuf, FrameBytes, Uid); } else { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP; ResponseByteCount = 2; } - break; - - case STATE_QUIET: + } + else if (State == STATE_QUIET) { if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount = 1; @@ -489,11 +530,6 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) FrameInfo.Addressed = false; FrameInfo.Selected = false; } - - break; - - default: - break; } if (ResponseByteCount > 0) { diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index 373a739..a87ab33 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -88,10 +88,18 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM + ISO15693_GENERIC_UID_SIZE]; else FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM]; - + + if (*(FrameStruct -> Command) >= 0xA0) { /* if command is Custom or Proprietary */ + /* then between CMD and UID is placed another byte which is IC Mfg Code, but we don't need it */ + FrameStruct -> Parameters += 0x01; + if (FrameBuf[ISO15693_REQ_ADDR_PARAM] != MyUid[1]) + /* if IC Mfg Code is different from our Mfg code (2nd byte of UID), then don't respond */ + return false; + } + FrameStruct -> ParamLen = FrameBuf + (FrameBytes - ISO15693_CRC16_SIZE) - (FrameStruct -> Parameters); - if (FrameStruct -> Addressed && !ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], MyUid)) { + if (FrameStruct -> Addressed && !ISO15693CompareUid(FrameStruct -> Parameters, MyUid)) { /* addressed request but we're not the addressee */ return false; } else { From 98141b676957ce5f23045f259114582772548e97 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Tue, 18 Dec 2018 00:42:19 +0100 Subject: [PATCH 06/14] Added fake login command --- Firmware/Chameleon-Mini/Application/EM4233.c | 42 ++++++++++++++++---- Firmware/Chameleon-Mini/Application/EM4233.h | 4 +- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index 75e6684..ea617c2 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -14,6 +14,8 @@ static enum { STATE_QUIET } State; +bool loggedIn; + CurrentFrame FrameInfo; uint64_t EM4233_FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ @@ -29,6 +31,8 @@ void EM4233AppInit(void) FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; FrameInfo.Selected = false; + loggedIn = false; + } void EM4233AppReset(void) @@ -41,6 +45,7 @@ void EM4233AppReset(void) FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; FrameInfo.Selected = false; + loggedIn = false; } void EM4233AppTask(void) @@ -449,6 +454,34 @@ uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) } } +uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t Password[4] = { 0 }; + + if (FrameInfo.ParamLen != 4) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + MemoryReadBlock(&Password, EM4233_MEM_PSW_ADDRESS, 4); + + if( false ){ // YES-MAN! +// if (!memcmp(Password, FrameInfo.Parameters, 4)) { /* Incorrect password */ + + loggedIn = false; + + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; + return ResponseByteCount; + } + + loggedIn = true; + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + ResponseByteCount += 1; + return ResponseByteCount; +} + uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) { uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; @@ -458,13 +491,6 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid)) return ISO15693_APP_NO_RESPONSE; - FrameBuf[ISO15693_ADDR_FLAGS] = FrameInfo.ParamLen; - ResponseByteCount = 1; - ISO15693AppendCRC(FrameBuf, ResponseByteCount); - ResponseByteCount += ISO15693_CRC16_SIZE; - return ResponseByteCount; - - if (State == STATE_READY || State == STATE_SELECTED) { if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; @@ -509,7 +535,7 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) ResponseByteCount = EM4233_Select(FrameBuf, FrameBytes, Uid); } else if (*FrameInfo.Command == EM4233_CMD_LOGIN) { - // ResponseByteCount = EM4233_Select(FrameBuf, FrameBytes, Uid); + ResponseByteCount = EM4233_Login(FrameBuf, FrameBytes, Uid); } else { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h index 48357da..6660e09 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.h +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -25,8 +25,8 @@ #define EM4233_MEM_DSFID_ADDRESS 0x0109 // DSFID byte adress #define EM4233_MEM_INF_ADDRESS 0x010C // Some status bits -#define EM4233_MEM_LSM_ADDRESS 0x0110 // From 0x0108 to 0x0157 - Lock status masks -#define EM4233_MEM_PSW_ADDRESS 0x0150 // From 0x0118 to 0x011F - Password +#define EM4233_MEM_LSM_ADDRESS 0x0110 // From 0x0108 to 0x0149 - Lock status masks +#define EM4233_MEM_PSW_ADDRESS 0x0150 // From 0x0150 to 0x0153 - Password #define EM4233_MEM_KEY_ADDRESS 0x0154 // From 0x0120 to 0x0127 - Encryption Key #define EM4233_SYSINFO_BYTE 0x0F // DSFID - AFI - VICC mem size - IC ref are present From 31d2320e8e18c8aaa1ba8bb38fc4fd1b69ec59b3 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Tue, 18 Dec 2018 01:06:25 +0100 Subject: [PATCH 07/14] Test to sniff EM4233 login password --- Firmware/Chameleon-Mini/Application/EM4233.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index ea617c2..475c277 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -307,7 +307,7 @@ uint16_t EM4233_Lock_DSFID(uint8_t* FrameBuf, uint16_t FrameBytes) LockStatus |= EM4233_MASK_DSFID_STATUS; - MemoryWriteBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); /* Actually write new AFI */ + MemoryWriteBlock(*FrameInfo.Parameters, EM4233_MEM_INF_ADDRESS, 4); /* Actually write the new PASSWORD */ FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ ResponseByteCount += 1; @@ -477,6 +477,9 @@ uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) loggedIn = true; + MemoryWriteBlock(Password, EM4233_MEM_PSW_ADDRESS, 1); /* Actually write new AFI */ + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ ResponseByteCount += 1; return ResponseByteCount; From d7f2b7525b507100f0772b225eddce44ca933b9a Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Tue, 18 Dec 2018 01:20:32 +0100 Subject: [PATCH 08/14] Modified EM4233_STD_MEM_SIZE to reflect real tag size --- Firmware/Chameleon-Mini/Application/EM4233.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h index 6660e09..88b79b3 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.h +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -11,7 +11,7 @@ #include "Application.h" #define EM4233_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE -#define EM4233_STD_MEM_SIZE 256 // Bytes +#define EM4233_STD_MEM_SIZE 208 // Bytes #define EM4233_BYTES_PER_BLCK 0x4 #define EM4233_BLCKS_PER_PAGE 0x4 #define EM4233_NUMBER_OF_BLCKS ( EM4233_STD_MEM_SIZE / EM4233_BYTES_PER_BLCK ) From be729b757326bd49eb66306f80b35a56718673ad Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Tue, 18 Dec 2018 16:42:10 +0100 Subject: [PATCH 09/14] Fixed a bug in prepareFrame on uid pointer into buffer --- Dumps/EM4233_example.dmp | Bin 352 -> 352 bytes Firmware/Chameleon-Mini/Application/EM4233.c | 14 +++++++------- .../Chameleon-Mini/Application/ISO15693-A.c | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Dumps/EM4233_example.dmp b/Dumps/EM4233_example.dmp index 7e87a0699926a0fc6571893f6a936792318e5649..e9f4caaa5851d6022b8c6f217498f1dc7ec28296 100644 GIT binary patch literal 352 zcmZ3526m%?Gicy08hD2W{-Xgj<5!^>zZ=c?Gib)&MKk^#n(_Yy(SQ;fFh&CmXyAdE W3fM>nCNv2$x%bxYdk;1cN&o;?Qo95I literal 352 zcmZ3526m%?Gicy08hD2W{-Xgj<5!^>zZ=c?Gib)&MKk^#n(_Yy(SQ;fFh&CmXyAdE S3fM>nCWr(hg#c_A5&-~iuDl2U diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index 475c277..b9cfeb6 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -443,15 +443,17 @@ uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) return ISO15693_APP_NO_RESPONSE; } else if (State == STATE_SELECTED && !UidEquals) { /* tag should remain silent if Select is performed while the tag is selected but against another tag */ - State == STATE_READY; + State = STATE_READY; return ISO15693_APP_NO_RESPONSE; } else if (State != STATE_SELECTED && !UidEquals) { /* tag should remain silent if Select is performed against another UID */ return ISO15693_APP_NO_RESPONSE; } else if (State != STATE_SELECTED && UidEquals) { - State == STATE_SELECTED; + State = STATE_SELECTED; return ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ } + + return ISO15693_APP_NO_RESPONSE; } uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) @@ -477,8 +479,7 @@ uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) loggedIn = true; - MemoryWriteBlock(Password, EM4233_MEM_PSW_ADDRESS, 1); /* Actually write new AFI */ - + MemoryWriteBlock(Password, EM4233_MEM_PSW_ADDRESS, 4); /* Actually write new AFI */ FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ ResponseByteCount += 1; @@ -501,7 +502,7 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid); ResponseByteCount = 10; - } else if (*FrameInfo.Command == ISO15693_CMD_STAY_QUIET && FrameInfo.Addressed) { + } else if ( (*FrameInfo.Command == ISO15693_CMD_STAY_QUIET ) && FrameInfo.Addressed) { State = STATE_QUIET; } else if (*FrameInfo.Command == ISO15693_CMD_READ_SINGLE) { @@ -545,8 +546,7 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP; ResponseByteCount = 2; } - } - else if (State == STATE_QUIET) { + } else if (State == STATE_QUIET) { if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount = 1; diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index a87ab33..38aa01b 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -89,7 +89,7 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* else FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM]; - if (*(FrameStruct -> Command) >= 0xA0) { /* if command is Custom or Proprietary */ + if ( (*FrameStruct -> Command) >= 0xA0) { /* if command is Custom or Proprietary */ /* then between CMD and UID is placed another byte which is IC Mfg Code, but we don't need it */ FrameStruct -> Parameters += 0x01; if (FrameBuf[ISO15693_REQ_ADDR_PARAM] != MyUid[1]) @@ -99,7 +99,9 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct -> ParamLen = FrameBuf + (FrameBytes - ISO15693_CRC16_SIZE) - (FrameStruct -> Parameters); - if (FrameStruct -> Addressed && !ISO15693CompareUid(FrameStruct -> Parameters, MyUid)) { + uint8_t *uid = (FrameStruct -> Parameters) - ISO15693_GENERIC_UID_SIZE; + + if (FrameStruct -> Addressed && !ISO15693CompareUid( uid, MyUid)) { /* addressed request but we're not the addressee */ return false; } else { From 1b38d14b2beb7970259e2821163f3f84a21424f3 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Wed, 19 Dec 2018 16:17:13 +0100 Subject: [PATCH 10/14] Refactored ReadMultipleBlocks command to partially cope with timing issues --- Firmware/Chameleon-Mini/Application/EM4233.c | 66 +++++++++++--------- Firmware/Chameleon-Mini/Application/EM4233.h | 4 +- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index b9cfeb6..18a26ac 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -168,47 +168,58 @@ uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; uint8_t FramePtr; /* holds the address where block's data will be put */ uint8_t BlockAddress = FrameInfo.Parameters[0]; - uint8_t BlocksNumber = 0; - uint8_t LockStatus = 0; + uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01; /* according to ISO standard, we have to read 8 blocks if we get 0x07 in request */ if (FrameInfo.ParamLen != 2) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ - BlocksNumber = FrameInfo.Parameters[1]; - - if (BlockAddress >= EM4233_NUMBER_OF_BLCKS || (BlockAddress + BlocksNumber) >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a sector out of bound */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; /* real TiTag standard reply with this error */ - ResponseByteCount += 2; + if (BlockAddress > EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a starting block out of bound */ + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; + } else if ((BlockAddress + BlocksNumber) >= EM4233_NUMBER_OF_BLCKS) { /* last block is out of bound */ + BlocksNumber = EM4233_NUMBER_OF_BLCKS - BlockAddress; /* we read up to latest block, as real tag does */ } - FramePtr = 1; /* Start of response data */ + FramePtr = 1; /* start of response data */ - for (uint8_t blk = 0; blk <= BlocksNumber; blk++) { - if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ - MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + (BlockAddress + blk)), 1); + if ( (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) == 0 ) { /* blocks' lock status is not requested */ + /* read data straight into frame */ + MemoryReadBlock(&FrameBuf[FramePtr], BlockAddress * EM4233_BYTES_PER_BLCK, BlocksNumber * EM4233_BYTES_PER_BLCK); + ResponseByteCount += BlocksNumber * EM4233_BYTES_PER_BLCK; - if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { /* tests if the n-th bit of the factory bitmask if set to 1 */ - FrameBuf[FramePtr] = 0x02; /* return bit 1 set as 1 (factory locked) */ - } else if (LockStatus & ISO15693_MASK_USER_LOCK) { /* tests if the n-th bit of the user bitmask if set to 1 */ + } else { /* we have to slice blocks' data with lock statuses */ + uint8_t DataBuffer[ BlocksNumber * EM4233_BYTES_PER_BLCK ]; /* a temporary vector with blocks' content */ + uint8_t LockStatusBuffer[ BlocksNumber ]; /* a vector with blocks' lock status */ + + /* read all at once to reduce timing issues */ + MemoryReadBlock(&DataBuffer, BlockAddress * EM4233_BYTES_PER_BLCK, BlocksNumber * EM4233_BYTES_PER_BLCK); + MemoryReadBlock(&LockStatusBuffer, EM4233_MEM_LSM_ADDRESS + BlockAddress, BlocksNumber); + + for (uint8_t block = 0; block < BlocksNumber; block++) { /* we cycle through the blocks */ + + /* add lock status */ + if (LockStatusBuffer[block] & ISO15693_MASK_USER_LOCK) { /* tests if bit 0 of the status byte if set to 1 */ FrameBuf[FramePtr] = 0x01; /* return bit 0 set as 1 (user locked) */ + } else if (LockStatusBuffer[block] & ISO15693_MASK_FACTORY_LOCK) { /* tests if bit 1 of the status byte if set to 1 */ + FrameBuf[FramePtr] = 0x02; /* return bit 1 set as 1 (factory locked) */ } else FrameBuf[FramePtr] = 0x00; /* return lock status 00 (unlocked) */ + ResponseByteCount += 1; + FramePtr += 1; - FramePtr += 1; /* Move forward the buffer data pointer */ - ResponseByteCount += 1; /* Increment the response count */ - - } - - MemoryReadBlock(&FrameBuf[FramePtr], (BlockAddress + blk ) * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); - FramePtr += 4; /* Move forward the buffer data pointer */ - ResponseByteCount += 4; /* Increment the response count */ + /* then copy block's data */ + for (uint8_t byte = 0; byte < EM4233_BYTES_PER_BLCK; byte++) { /* we cycle through the bytes in every block */ + FrameBuf[FramePtr] = DataBuffer[block * EM4233_BYTES_PER_BLCK + byte]; /* to copy them in the frame from our temporary buffer */ + FramePtr += 1; + } + ResponseByteCount += EM4233_BYTES_PER_BLCK; + } } - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + ResponseByteCount += 1; return ResponseByteCount; } @@ -435,9 +446,8 @@ uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) } */ - bool UidEquals = ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid); + bool UidEquals = ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid); - uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; if (!FrameInfo.Addressed || FrameInfo.Selected) { /* tag should remain silent if Select is performed without address flag or with select flag */ return ISO15693_APP_NO_RESPONSE; @@ -467,7 +477,7 @@ uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) MemoryReadBlock(&Password, EM4233_MEM_PSW_ADDRESS, 4); if( false ){ // YES-MAN! -// if (!memcmp(Password, FrameInfo.Parameters, 4)) { /* Incorrect password */ + // if (!memcmp(Password, FrameInfo.Parameters, 4)) { /* Incorrect password */ loggedIn = false; diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h index 88b79b3..e1d370b 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.h +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -12,8 +12,8 @@ #define EM4233_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE #define EM4233_STD_MEM_SIZE 208 // Bytes -#define EM4233_BYTES_PER_BLCK 0x4 -#define EM4233_BLCKS_PER_PAGE 0x4 +#define EM4233_BYTES_PER_BLCK 0x04 +#define EM4233_BLCKS_PER_PAGE 0x04 #define EM4233_NUMBER_OF_BLCKS ( EM4233_STD_MEM_SIZE / EM4233_BYTES_PER_BLCK ) #define EM4233_NUMBER_OF_PAGES ( EM4233_STD_MEM_SIZE / (EM4233_BYTES_PER_BLCK * EM4233_BLCKS_PER_PAGE) ) From cf27a07a8d2be68e9e6bdf08a19224b5cbe135bc Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Wed, 19 Dec 2018 17:23:19 +0100 Subject: [PATCH 11/14] Indentation fixes --- Firmware/Chameleon-Mini/Application/EM4233.c | 2 +- .../Chameleon-Mini/Application/ISO15693-A.c | 2 +- Firmware/Chameleon-Mini/Codec/ISO15693.c | 26 +-- Firmware/Chameleon-Mini/Configuration.c | 170 +++++++++--------- 4 files changed, 100 insertions(+), 100 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index 18a26ac..54a20f4 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -198,7 +198,7 @@ uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) MemoryReadBlock(&LockStatusBuffer, EM4233_MEM_LSM_ADDRESS + BlockAddress, BlocksNumber); for (uint8_t block = 0; block < BlocksNumber; block++) { /* we cycle through the blocks */ - + /* add lock status */ if (LockStatusBuffer[block] & ISO15693_MASK_USER_LOCK) { /* tests if bit 0 of the status byte if set to 1 */ FrameBuf[FramePtr] = 0x01; /* return bit 0 set as 1 (user locked) */ diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index 38aa01b..b271db8 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -88,7 +88,7 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM + ISO15693_GENERIC_UID_SIZE]; else FrameStruct -> Parameters = &FrameBuf[ISO15693_REQ_ADDR_PARAM]; - + if ( (*FrameStruct -> Command) >= 0xA0) { /* if command is Custom or Proprietary */ /* then between CMD and UID is placed another byte which is IC Mfg Code, but we don't need it */ FrameStruct -> Parameters += 0x01; diff --git a/Firmware/Chameleon-Mini/Codec/ISO15693.c b/Firmware/Chameleon-Mini/Codec/ISO15693.c index 8c84219..bab785d 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO15693.c +++ b/Firmware/Chameleon-Mini/Codec/ISO15693.c @@ -143,7 +143,7 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) CODEC_TIMER_SAMPLING.INTCTRLB = 0; } break; - + case DEMOD_1_OUT_OF_4_STATE: if (SampleRegister == EOC_CODE) { @@ -184,7 +184,7 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) } } break; - + case DEMOD_1_OUT_OF_256_STATE: if (SampleRegister == EOC_CODE) { @@ -252,7 +252,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) } else { return; } - + LOADMOD_START_SINGLE_LABEL: CodecStartSubcarrier(); ShiftRegister = SOF_PATTERN; @@ -276,7 +276,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) StateRegister = LOADMOD_SOF_SINGLE; } return; - + LOADMOD_BIT0_SINGLE_LABEL: //Manchester encoding if (ShiftRegister & 0x01) { /* Deactivate carrier */ @@ -288,7 +288,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) StateRegister = LOADMOD_BIT1_SINGLE; return; - + LOADMOD_BIT1_SINGLE_LABEL: //Manchester encoding if (ShiftRegister & 0x01) { CodecSetLoadmodState(true); @@ -312,7 +312,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) } } return; - + LOADMOD_EOF_SINGLE_LABEL: //End of Manchester encoding /* Output EOF */ if (ShiftRegister & 0x80) { @@ -333,7 +333,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) return; // ------------------------------------------------------------- - + LOADMOD_START_DUAL_LABEL: CodecStartSubcarrier(); ShiftRegister = SOF_PATTERN; @@ -514,11 +514,11 @@ void ISO15693CodecTask(void) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; - + uint16_t DemodByteCount = ByteCount; uint16_t AppReceivedByteCount = 0; bool bDualSubcarrier = false; - + if (DemodByteCount > 0) { if (CodecBuffer[0] & ISO15693_REQ_SUBCARRIER_DUAL) @@ -531,13 +531,13 @@ void ISO15693CodecTask(void) } else { ApplicationReset(); } - + //This is only reached when we've received a valid frame if (AppReceivedByteCount > 0) { LogEntry(LOG_INFO_CODEC_TX_DATA, CodecBuffer, AppReceivedByteCount); CodecBufferPtr = CodecBuffer; ByteCount = AppReceivedByteCount; - + CodecStartSubcarrier(); /* Start loadmodulating */ @@ -548,7 +548,7 @@ void ISO15693CodecTask(void) StateRegister = LOADMOD_START_SINGLE; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OOK, SUBCARRIER_1); } - + } else { /* No data to be processed. Disable T1 waiting and * start listening again */ @@ -557,7 +557,7 @@ void ISO15693CodecTask(void) StartISO15693Demod(); } } - + if (Flags.LoadmodFinished) { Flags.LoadmodFinished = 0; /* Load modulation has been finished. Stop it and start to listen diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 35b0de5..df5a1ff 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -38,19 +38,19 @@ static const MapEntryType PROGMEM ConfigurationMap[] = { { .Id = CONFIG_ISO14443A_READER, .Text = "ISO14443A_READER" }, #endif #ifdef CONFIG_VICINITY_SUPPORT - { .Id = CONFIG_VICINITY, .Text = "VICINITY" }, + { .Id = CONFIG_VICINITY, .Text = "VICINITY" }, #endif #ifdef CONFIG_ISO15693_SNIFF_SUPPORT - { .Id = CONFIG_ISO15693_SNIFF, .Text = "ISO15693_SNIFF" }, + { .Id = CONFIG_ISO15693_SNIFF, .Text = "ISO15693_SNIFF" }, #endif #ifdef CONFIG_SL2S2002_SUPPORT - { .Id = CONFIG_SL2S2002, .Text = "SL2S2002" }, + { .Id = CONFIG_SL2S2002, .Text = "SL2S2002" }, #endif #ifdef CONFIG_TITAGITSTANDARD_SUPPORT - { .Id = CONFIG_TITAGITSTANDARD, .Text = "TITAGITSTANDARD" }, + { .Id = CONFIG_TITAGITSTANDARD, .Text = "TITAGITSTANDARD" }, #endif #ifdef CONFIG_EM4233_SUPPORT - { .Id = CONFIG_EM4233, .Text = "EM4233" }, + { .Id = CONFIG_EM4233, .Text = "EM4233" }, #endif }; @@ -85,7 +85,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = 0, .MemorySize = 0, .ReadOnly = true, - .TagFamily = TAG_FAMILY_NONE + .TagFamily = TAG_FAMILY_NONE }, #ifdef CONFIG_MF_ULTRALIGHT_SUPPORT [CONFIG_MF_ULTRALIGHT] = { @@ -102,7 +102,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHT_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, [CONFIG_MF_ULTRALIGHT_EV1_80B] = { .CodecInitFunc = ISO14443ACodecInit, @@ -118,7 +118,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHT_EV11_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, [CONFIG_MF_ULTRALIGHT_EV1_164B] = { .CodecInitFunc = ISO14443ACodecInit, @@ -134,7 +134,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHT_EV12_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, #endif #ifdef CONFIG_MF_CLASSIC_1K_SUPPORT @@ -152,7 +152,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, #endif #ifdef CONFIG_MF_CLASSIC_1K_7B_SUPPORT @@ -170,7 +170,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = ISO14443A_UID_SIZE_DOUBLE, .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, #endif #ifdef CONFIG_MF_CLASSIC_4K_SUPPORT @@ -188,7 +188,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, #endif #ifdef CONFIG_MF_CLASSIC_4K_7B_SUPPORT @@ -206,7 +206,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = ISO14443A_UID_SIZE_DOUBLE, .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO14443A + .TagFamily = TAG_FAMILY_ISO14443A }, #endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT @@ -224,7 +224,7 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = 0, .MemorySize = 0, .ReadOnly = true, - .TagFamily = TAG_FAMILY_NONE + .TagFamily = TAG_FAMILY_NONE }, #endif #ifdef CONFIG_ISO14443A_READER_SUPPORT @@ -242,97 +242,97 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .UidSize = 0, .MemorySize = 0, .ReadOnly = false, - .TagFamily = TAG_FAMILY_NONE + .TagFamily = TAG_FAMILY_NONE }, #endif #ifdef CONFIG_VICINITY_SUPPORT [CONFIG_VICINITY] = { - .CodecInitFunc = ISO15693CodecInit, - .CodecDeInitFunc = ISO15693CodecDeInit, - .CodecTaskFunc = ISO15693CodecTask, - .ApplicationInitFunc = VicinityAppInit, - .ApplicationResetFunc = VicinityAppReset, - .ApplicationTaskFunc = VicinityAppTask, - .ApplicationTickFunc = VicinityAppTick, - .ApplicationProcessFunc = VicinityAppProcess, - .ApplicationGetUidFunc = VicinityGetUid, - .ApplicationSetUidFunc = VicinitySetUid, - .UidSize = ISO15693_GENERIC_UID_SIZE, - .MemorySize = ISO15693_GENERIC_MEM_SIZE, - .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO15693 + .CodecInitFunc = ISO15693CodecInit, + .CodecDeInitFunc = ISO15693CodecDeInit, + .CodecTaskFunc = ISO15693CodecTask, + .ApplicationInitFunc = VicinityAppInit, + .ApplicationResetFunc = VicinityAppReset, + .ApplicationTaskFunc = VicinityAppTask, + .ApplicationTickFunc = VicinityAppTick, + .ApplicationProcessFunc = VicinityAppProcess, + .ApplicationGetUidFunc = VicinityGetUid, + .ApplicationSetUidFunc = VicinitySetUid, + .UidSize = ISO15693_GENERIC_UID_SIZE, + .MemorySize = ISO15693_GENERIC_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO15693 }, #endif #ifdef CONFIG_ISO15693_SNIFF_SUPPORT [CONFIG_ISO15693_SNIFF] = { - .CodecInitFunc = ISO15693CodecInit, - .CodecDeInitFunc = ISO15693CodecDeInit, - .CodecTaskFunc = ISO15693CodecTask, - .ApplicationInitFunc = ApplicationInitDummy, - .ApplicationResetFunc = ApplicationResetDummy, - .ApplicationTaskFunc = ApplicationTaskDummy, - .ApplicationTickFunc = ApplicationTickDummy, - .ApplicationProcessFunc = ApplicationProcessDummy, - .ApplicationGetUidFunc = ApplicationGetUidDummy, - .ApplicationSetUidFunc = ApplicationSetUidDummy, - .UidSize = 0, - .MemorySize = 0, - .ReadOnly = true, - .TagFamily = TAG_FAMILY_NONE + .CodecInitFunc = ISO15693CodecInit, + .CodecDeInitFunc = ISO15693CodecDeInit, + .CodecTaskFunc = ISO15693CodecTask, + .ApplicationInitFunc = ApplicationInitDummy, + .ApplicationResetFunc = ApplicationResetDummy, + .ApplicationTaskFunc = ApplicationTaskDummy, + .ApplicationTickFunc = ApplicationTickDummy, + .ApplicationProcessFunc = ApplicationProcessDummy, + .ApplicationGetUidFunc = ApplicationGetUidDummy, + .ApplicationSetUidFunc = ApplicationSetUidDummy, + .UidSize = 0, + .MemorySize = 0, + .ReadOnly = true, + .TagFamily = TAG_FAMILY_NONE }, #endif #ifdef CONFIG_SL2S2002_SUPPORT [CONFIG_SL2S2002] = { - .CodecInitFunc = ISO15693CodecInit, - .CodecDeInitFunc = ISO15693CodecDeInit, - .CodecTaskFunc = ISO15693CodecTask, - .ApplicationInitFunc = Sl2s2002AppInit, - .ApplicationResetFunc = Sl2s2002AppReset, - .ApplicationTaskFunc = Sl2s2002AppTask, - .ApplicationTickFunc = Sl2s2002AppTick, - .ApplicationProcessFunc = Sl2s2002AppProcess, - .ApplicationGetUidFunc = Sl2s2002GetUid, - .ApplicationSetUidFunc = Sl2s2002SetUid, - .UidSize = ISO15693_GENERIC_UID_SIZE, - .MemorySize = ISO15693_GENERIC_MEM_SIZE, - .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO15693 + .CodecInitFunc = ISO15693CodecInit, + .CodecDeInitFunc = ISO15693CodecDeInit, + .CodecTaskFunc = ISO15693CodecTask, + .ApplicationInitFunc = Sl2s2002AppInit, + .ApplicationResetFunc = Sl2s2002AppReset, + .ApplicationTaskFunc = Sl2s2002AppTask, + .ApplicationTickFunc = Sl2s2002AppTick, + .ApplicationProcessFunc = Sl2s2002AppProcess, + .ApplicationGetUidFunc = Sl2s2002GetUid, + .ApplicationSetUidFunc = Sl2s2002SetUid, + .UidSize = ISO15693_GENERIC_UID_SIZE, + .MemorySize = ISO15693_GENERIC_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO15693 }, #endif #ifdef CONFIG_TITAGITSTANDARD_SUPPORT [CONFIG_TITAGITSTANDARD] = { - .CodecInitFunc = ISO15693CodecInit, - .CodecDeInitFunc = ISO15693CodecDeInit, - .CodecTaskFunc = ISO15693CodecTask, - .ApplicationInitFunc = TITagitstandardAppInit, - .ApplicationResetFunc = TITagitstandardAppReset, - .ApplicationTaskFunc = TITagitstandardAppTask, - .ApplicationTickFunc = TITagitstandardAppTick, - .ApplicationProcessFunc = TITagitstandardAppProcess, - .ApplicationGetUidFunc = TITagitstandardGetUid, - .ApplicationSetUidFunc = TITagitstandardSetUid, - .UidSize = TITAGIT_STD_UID_SIZE, - .MemorySize = TITAGIT_STD_MEM_SIZE, - .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO15693 + .CodecInitFunc = ISO15693CodecInit, + .CodecDeInitFunc = ISO15693CodecDeInit, + .CodecTaskFunc = ISO15693CodecTask, + .ApplicationInitFunc = TITagitstandardAppInit, + .ApplicationResetFunc = TITagitstandardAppReset, + .ApplicationTaskFunc = TITagitstandardAppTask, + .ApplicationTickFunc = TITagitstandardAppTick, + .ApplicationProcessFunc = TITagitstandardAppProcess, + .ApplicationGetUidFunc = TITagitstandardGetUid, + .ApplicationSetUidFunc = TITagitstandardSetUid, + .UidSize = TITAGIT_STD_UID_SIZE, + .MemorySize = TITAGIT_STD_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO15693 }, #endif #ifdef CONFIG_EM4233_SUPPORT [CONFIG_EM4233] = { - .CodecInitFunc = ISO15693CodecInit, - .CodecDeInitFunc = ISO15693CodecDeInit, - .CodecTaskFunc = ISO15693CodecTask, - .ApplicationInitFunc = EM4233AppInit, - .ApplicationResetFunc = EM4233AppReset, - .ApplicationTaskFunc = EM4233AppTask, - .ApplicationTickFunc = EM4233AppTick, - .ApplicationProcessFunc = EM4233AppProcess, - .ApplicationGetUidFunc = EM4233GetUid, - .ApplicationSetUidFunc = EM4233SetUid, - .UidSize = EM4233_STD_UID_SIZE, - .MemorySize = EM4233_STD_MEM_SIZE, - .ReadOnly = false, - .TagFamily = TAG_FAMILY_ISO15693 + .CodecInitFunc = ISO15693CodecInit, + .CodecDeInitFunc = ISO15693CodecDeInit, + .CodecTaskFunc = ISO15693CodecTask, + .ApplicationInitFunc = EM4233AppInit, + .ApplicationResetFunc = EM4233AppReset, + .ApplicationTaskFunc = EM4233AppTask, + .ApplicationTickFunc = EM4233AppTick, + .ApplicationProcessFunc = EM4233AppProcess, + .ApplicationGetUidFunc = EM4233GetUid, + .ApplicationSetUidFunc = EM4233SetUid, + .UidSize = EM4233_STD_UID_SIZE, + .MemorySize = EM4233_STD_MEM_SIZE, + .ReadOnly = false, + .TagFamily = TAG_FAMILY_ISO15693 }, #endif }; From 9ba4f75b66711d0b32bc5acefe71893876a167e4 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 25 Dec 2018 13:46:30 +0100 Subject: [PATCH 12/14] Current codec status, not working after APP_NO_RESPONSE --- .../Chameleon-Mini/Application/Vicinity.h | 3 -- Firmware/Chameleon-Mini/Codec/ISO15693.c | 44 ++++++++++--------- Firmware/Chameleon-Mini/Codec/ISO15693.h | 5 --- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Vicinity.h b/Firmware/Chameleon-Mini/Application/Vicinity.h index 797ff01..7f19a91 100644 --- a/Firmware/Chameleon-Mini/Application/Vicinity.h +++ b/Firmware/Chameleon-Mini/Application/Vicinity.h @@ -11,9 +11,6 @@ #include "Application.h" #include "ISO15693-A.h" -#define ISO15693_GENERIC_UID_SIZE 8 //ISO15693_UID_SIZE -#define ISO15693_GENERIC_MEM_SIZE 8192 //ISO15693_MAX_MEM_SIZE - void VicinityAppInit(void); void VicinityAppReset(void); void VicinityAppTask(void); diff --git a/Firmware/Chameleon-Mini/Codec/ISO15693.c b/Firmware/Chameleon-Mini/Codec/ISO15693.c index bab785d..8679dc2 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO15693.c +++ b/Firmware/Chameleon-Mini/Codec/ISO15693.c @@ -94,13 +94,13 @@ void isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT(void) INLINE void ISO15693_EOC(void) { - BitRate1 = 256 * 4; + BitRate1 = 256 * 4; // 256 * 4 - 1 if (CodecBuffer[0] & ISO15693_REQ_DATARATE_HIGH) BitRate1 = 256; if (CodecBuffer[0] & ISO15693_REQ_SUBCARRIER_DUAL) { - BitRate2 = 252 * 4; + BitRate2 = 252 * 4; // 252 * 4 - 3 if (CodecBuffer[0] & ISO15693_REQ_DATARATE_HIGH) BitRate2 = 252; } else { @@ -254,10 +254,10 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) } LOADMOD_START_SINGLE_LABEL: - CodecStartSubcarrier(); + /* Application produced data. With this interrupt we are aligned to the bit-grid. */ ShiftRegister = SOF_PATTERN; BitSent = 0; - // fallthrough + /* Fallthrough */ LOADMOD_SOF_SINGLE_LABEL: if (ShiftRegister & 0x80) { CodecSetLoadmodState(true); @@ -265,6 +265,8 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) CodecSetLoadmodState(false); } + CodecStartSubcarrier(); + ShiftRegister <<= 1; BitSent++; @@ -335,10 +337,10 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) // ------------------------------------------------------------- LOADMOD_START_DUAL_LABEL: - CodecStartSubcarrier(); ShiftRegister = SOF_PATTERN; BitSent = 0; CodecSetLoadmodState(true); + CodecStartSubcarrier(); // fallthrough LOADMOD_SOF_DUAL_LABEL: if (ShiftRegister & 0x80) { @@ -433,7 +435,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) #endif /* CONFIG_VICINITY_SUPPORT */ void StartISO15693Demod(void) { - + CodecBufferPtr = CodecBuffer; Flags.DemodFinished = 0; Flags.LoadmodFinished = 0; @@ -445,7 +447,8 @@ void StartISO15693Demod(void) { ModulationPauseCount = 0; ByteCount = 0; ShiftRegister = 0; - + + /* Activate Power for demodulator */ CodecSetDemodPower(true); /* Configure sampling-timer free running and sync to first modulation-pause. */ @@ -521,39 +524,38 @@ void ISO15693CodecTask(void) if (DemodByteCount > 0) { + LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, DemodByteCount); + LEDHook(LED_CODEC_RX, LED_PULSE); + if (CodecBuffer[0] & ISO15693_REQ_SUBCARRIER_DUAL) { bDualSubcarrier = true; } - LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, DemodByteCount); AppReceivedByteCount = ApplicationProcess(CodecBuffer, DemodByteCount); - - } else { - ApplicationReset(); } - //This is only reached when we've received a valid frame - if (AppReceivedByteCount > 0) { + /* This is only reached when we've received a valid frame */ + if (AppReceivedByteCount != ISO15693_APP_NO_RESPONSE) { LogEntry(LOG_INFO_CODEC_TX_DATA, CodecBuffer, AppReceivedByteCount); - CodecBufferPtr = CodecBuffer; - ByteCount = AppReceivedByteCount; + LEDHook(LED_CODEC_TX, LED_PULSE); - CodecStartSubcarrier(); + ByteCount = AppReceivedByteCount; + CodecBufferPtr = CodecBuffer; /* Start loadmodulating */ if (bDualSubcarrier) { - StateRegister = LOADMOD_START_DUAL; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OOK, SUBCARRIER_2); + StateRegister = LOADMOD_START_DUAL; } else { - StateRegister = LOADMOD_START_SINGLE; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OOK, SUBCARRIER_1); + StateRegister = LOADMOD_START_SINGLE; } } else { - /* No data to be processed. Disable T1 waiting and - * start listening again */ + /* No data to be processed. Disable T1 waiting and start listening again */ CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_OFF_gc; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + StartISO15693Demod(); } } diff --git a/Firmware/Chameleon-Mini/Codec/ISO15693.h b/Firmware/Chameleon-Mini/Codec/ISO15693.h index 93162d7..6c2e01b 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO15693.h +++ b/Firmware/Chameleon-Mini/Codec/ISO15693.h @@ -12,11 +12,6 @@ #define ISO15693_APP_NO_RESPONSE 0x0000 -/* VERY OUTDATED */ -#define TIMER_SAMPLING TCC0 -#define TIMER_T1_BITRATE TCD1 -#define TIMER_SUBCARRIER TCD0 - #define SUBCARRIER_1 32 #define SUBCARRIER_2 28 #define SUBCARRIER_OFF 0 From e92b3588e0b88f216b2d79c017f34b0fda7d024c Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Wed, 26 Dec 2018 00:53:17 +0100 Subject: [PATCH 13/14] Resetting LoadModState to avoid erratic behaviour --- Firmware/Chameleon-Mini/Codec/ISO15693.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/Chameleon-Mini/Codec/ISO15693.c b/Firmware/Chameleon-Mini/Codec/ISO15693.c index 8679dc2..6d1f706 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO15693.c +++ b/Firmware/Chameleon-Mini/Codec/ISO15693.c @@ -440,6 +440,7 @@ void StartISO15693Demod(void) { Flags.DemodFinished = 0; Flags.LoadmodFinished = 0; DemodState = DEMOD_SOC_STATE; + LoadModState = LOADMOD_WAIT; DataRegister = 0; SampleRegister = 0; BitSampleCount = 0; @@ -489,6 +490,7 @@ void ISO15693CodecDeInit(void) Flags.DemodFinished = 0; Flags.LoadmodFinished = 0; DemodState = DEMOD_SOC_STATE; + LoadModState = LOADMOD_WAIT; DataRegister = 0; SampleRegister = 0; BitSampleCount = 0; From 9a0ee807aac9a271b1510d225794d8e672b448c7 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Wed, 26 Dec 2018 18:06:10 +0100 Subject: [PATCH 14/14] Added comments and fixed a bug in codec's source ISO15693 codec was undocumented and without comments in relevant parts. I decided to spend 3 days diving into XMega interrupts and Chameleon's lowest level code. Now, I hope, it should be more readable for everyone, even newbies like my old self was before I started this deep dive. Also, I fixed the bug referenced here https://github.com/geo-rg/ChameleonMini/issues/4 which locked the chameleon when no response was to be sent to the reader --- Firmware/Chameleon-Mini/Codec/ISO15693.c | 154 ++++++++++++++++++----- 1 file changed, 121 insertions(+), 33 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/ISO15693.c b/Firmware/Chameleon-Mini/Codec/ISO15693.c index 6d1f706..e1aa507 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO15693.c +++ b/Firmware/Chameleon-Mini/Codec/ISO15693.c @@ -3,6 +3,7 @@ * * Created on: 25.01.2017 * Author: Phillip Nash + * Modified by: ceres-c */ #include "ISO15693.h" @@ -81,19 +82,33 @@ static volatile uint16_t ReadCommandFromReader = 0; #ifdef CONFIG_VICINITY_SUPPORT -// Started when a single pulse has been detected -// ISR(CODEC_DEMOD_IN_INT0_VECT) +/* 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: + * CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; + * and unregistered writing the INT0MASK to 0 + */ +// ISR(CODEC_DEMOD_IN_INT0_VECT) void isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT(void) { - // Start sample timer + /* Start sample timer CODEC_TIMER_SAMPLING (TCD0). + * Set Counter Channel C (CCC) with relevant bitmask (TC0_CCCIF_bm), + * the period for clock sampling is specified in StartISO15693Demod. + */ CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; + /* Sets register INTCTRLB to TC_CCCINTLVL_HI_gc = (0x03<<4) to enable compare/capture for high level interrupts on Channel C (CCC) */ CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_HI_gc; - /* Disable this interrupt */ + + /* Disable this interrupt as we've already sensed the relevant pulse and will use our internal clock from now on */ CODEC_DEMOD_IN_PORT.INT0MASK = 0; } +/* This function is called from isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT + * when we have 8 bits in SampleRegister and they represent an end of frame. + */ INLINE void ISO15693_EOC(void) { + /* Set bitrate required by the reader on SOF for our following response */ BitRate1 = 256 * 4; // 256 * 4 - 1 if (CodecBuffer[0] & ISO15693_REQ_DATARATE_HIGH) BitRate1 = 256; @@ -107,18 +122,35 @@ INLINE void ISO15693_EOC(void) BitRate2 = BitRate1; } - CODEC_TIMER_LOADMOD.CTRLD = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC0_CCBIF_bm; + /* Disable event action for CODEC_TIMER_LOADMOD (TCE0) as we're done receiving data */ + CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; + /* Set Counter Channel B (CCB) with relevant bitmask (TC0_CCBIF_bm), the period for clock sampling is specified below */ + CODEC_TIMER_LOADMOD.INTFLAGS = TC0_CCBIF_bm; // TODO This might not be needed since commenting it does not break anything + /* Sets register INTCTRLB to TC_CCBINTLVL_HI_gc = (0x03<<2) to enable compare/capture for high level interrupts on channel B */ CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc; + /* Set the period for CODEC_TIMER_LOADMOD (TCE0) to Bitrate - 1 because PERBUF is 0-based + * + * TODO Why are we using PERBUF instead of PER? + * With PERBUF the period register will occur on the next overflow. + */ CODEC_TIMER_LOADMOD.PERBUF = BitRate1 - 1; Flags.DemodFinished = 1; + /* Sets timer off for CODEC_TIMER_SAMPLING (TCD0) disabling clock source */ CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + /* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */ CODEC_TIMER_SAMPLING.INTCTRLB = 0; } +/* This function is registered to CODEC_TIMER_SAMPLING (TCD0)'s Counter Channel C (CCC). + * When the timer is enabled, this is called on counter's overflow + * + * It demodulates bits received from the reader and saves them in CodecBuffer. + * + * It disables its own interrupt when receives an EOF (calling ISO15693_EOC) or when it receives garbage + */ // ISR(CODEC_TIMER_SAMPLING_CCC_VECT) // Reading data sent from the reader -void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) +void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) { /* Shift demod data */ SampleRegister = (SampleRegister << 1) | (!(CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK) ? 0x01 : 0x00); @@ -137,9 +169,11 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) } else if (SampleRegister == SOC_1_OF_256_CODE) { DemodState = DEMOD_1_OUT_OF_256_STATE; SampleDataCount = 0; - } else { // No SOC. Restart and try again + } else { // No SOC. Restart and try again, we probably received garbage. Flags.DemodFinished = 1; + /* Sets timer off for CODEC_TIMER_SAMPLING (TCD0) disabling clock source */ CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + /* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */ CODEC_TIMER_SAMPLING.INTCTRLB = 0; } break; @@ -230,21 +264,28 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) } +/* This function is registered to CODEC_TIMER_LOADMOD (TCE0)'s Counter Channel B (CCB). + * When the timer is enabled, this is called on counter's overflow + * + * It modulates the carrier with consuming bytes in CodecBuffer until ByteCount is 0. + * + * It disables its own interrupt when all data has been sent + */ //ISR(CODEC_TIMER_LOADMOD_CCB_VECT) void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) { static void* JumpTable[] = { - [LOADMOD_START_SINGLE] = &&LOADMOD_START_SINGLE_LABEL, - [LOADMOD_SOF_SINGLE] = &&LOADMOD_SOF_SINGLE_LABEL, - [LOADMOD_BIT0_SINGLE] = &&LOADMOD_BIT0_SINGLE_LABEL, - [LOADMOD_BIT1_SINGLE] = &&LOADMOD_BIT1_SINGLE_LABEL, - [LOADMOD_EOF_SINGLE] = &&LOADMOD_EOF_SINGLE_LABEL, - [LOADMOD_START_DUAL] = &&LOADMOD_START_DUAL_LABEL, - [LOADMOD_SOF_DUAL] = &&LOADMOD_SOF_DUAL_LABEL, - [LOADMOD_BIT0_DUAL] = &&LOADMOD_BIT0_DUAL_LABEL, - [LOADMOD_BIT1_DUAL] = &&LOADMOD_BIT1_DUAL_LABEL, - [LOADMOD_EOF_DUAL] = &&LOADMOD_EOF_DUAL_LABEL, - [LOADMOD_FINISHED] = &&LOADMOD_FINISHED_LABEL + [LOADMOD_START_SINGLE] = &&LOADMOD_START_SINGLE_LABEL, + [LOADMOD_SOF_SINGLE] = &&LOADMOD_SOF_SINGLE_LABEL, + [LOADMOD_BIT0_SINGLE] = &&LOADMOD_BIT0_SINGLE_LABEL, + [LOADMOD_BIT1_SINGLE] = &&LOADMOD_BIT1_SINGLE_LABEL, + [LOADMOD_EOF_SINGLE] = &&LOADMOD_EOF_SINGLE_LABEL, + [LOADMOD_START_DUAL] = &&LOADMOD_START_DUAL_LABEL, + [LOADMOD_SOF_DUAL] = &&LOADMOD_SOF_DUAL_LABEL, + [LOADMOD_BIT0_DUAL] = &&LOADMOD_BIT0_DUAL_LABEL, + [LOADMOD_BIT1_DUAL] = &&LOADMOD_BIT1_DUAL_LABEL, + [LOADMOD_EOF_DUAL] = &&LOADMOD_EOF_DUAL_LABEL, + [LOADMOD_FINISHED] = &&LOADMOD_FINISHED_LABEL }; if ( (StateRegister >= LOADMOD_START_SINGLE) && (StateRegister <= LOADMOD_FINISHED) ) { @@ -255,7 +296,7 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) LOADMOD_START_SINGLE_LABEL: /* Application produced data. With this interrupt we are aligned to the bit-grid. */ - ShiftRegister = SOF_PATTERN; + ShiftRegister = SOF_PATTERN; BitSent = 0; /* Fallthrough */ LOADMOD_SOF_SINGLE_LABEL: @@ -425,22 +466,25 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) return; LOADMOD_FINISHED_LABEL: + /* Sets timer off for CODEC_TIMER_LOADMOD (TCE0) disabling clock source as we're done modulating */ CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + /* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */ CODEC_TIMER_LOADMOD.INTCTRLB = 0; - CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, SUBCARRIER_1); + CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); Flags.LoadmodFinished = 1; 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 */ CodecBufferPtr = CodecBuffer; Flags.DemodFinished = 0; Flags.LoadmodFinished = 0; DemodState = DEMOD_SOC_STATE; - LoadModState = LOADMOD_WAIT; + StateRegister = LOADMOD_WAIT; DataRegister = 0; SampleRegister = 0; BitSampleCount = 0; @@ -453,31 +497,66 @@ void StartISO15693Demod(void) { CodecSetDemodPower(true); /* Configure sampling-timer free running and sync to first modulation-pause. */ + /* Resets the counter to 0 */ CODEC_TIMER_SAMPLING.CNT = 0; - CODEC_TIMER_SAMPLING.PER = ISO15693_SAMPLE_PERIOD - 1; - CODEC_TIMER_SAMPLING.CCC = ISO15693_SAMPLE_PERIOD / 2 - 14 - 1; /* Half bit. ISR compensate*/ + /* Set the period for CODEC_TIMER_SAMPLING (TCD0) to ISO15693_SAMPLE_PERIOD - 1 because PER is 0-based */ + CODEC_TIMER_SAMPLING.PER = ISO15693_SAMPLE_PERIOD - 1; + /* Set Counter Channel C (CCC) register with half bit period - 1. (- 14 to compensate ISR timing overhead) */ + CODEC_TIMER_SAMPLING.CCC = ISO15693_SAMPLE_PERIOD / 2 - 14 - 1; + /* Set timer for CODEC_TIMER_SAMPLING (TCD0) to ISO15693_SAMPLE_CLK = TC_CLKSEL_DIV2_gc = System Clock / 2 + * + * TODO Why system clock / 2 and not iso period? + */ CODEC_TIMER_SAMPLING.CTRLA = ISO15693_SAMPLE_CLK; + /* Set event action for CODEC_TIMER_SAMPLING (TCD0) to restart and trigger CODEC_TIMER_MODSTART_EVSEL = TC_EVSEL_CH0_gc = Event Channel 0 */ CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; + /* Set Counter Channel C (CCC) with relevant bitmask (TC0_CCCIF_bm), the period for clock sampling is specified above */ CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; + /* Sets register INTCTRLB to TC_CCCINTLVL_OFF_gc = (0x00<<4) to disable compare/capture C interrupts + * + * TODO Why turn it off? + */ CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; + /* Set event action for CODEC_TIMER_LOADMOD (TCE0) to restart and trigger CODEC_TIMER_MODSTART_EVSEL = TC_EVSEL_CH0_gc = Event Channel 0 */ CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; - CODEC_TIMER_LOADMOD.PER = 4192 + 128 + 128 - 1; + /* Set the period for CODEC_TIMER_LOADMOD (TCE0) to... some magic numbers? + * Using PER instead of PERBUF breaks it when receiving ISO15693_APP_NO_RESPONSE from Application. + * + * TODO What are these numbers? + */ + CODEC_TIMER_LOADMOD.PERBUF = 4192 + 128 + 128 - 1; + /* Sets register INTCTRLA to 0 to disable timer error or overflow interrupts */ CODEC_TIMER_LOADMOD.INTCTRLA = 0; + /* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */ CODEC_TIMER_LOADMOD.INTCTRLB = 0; + /* Set timer for CODEC_TIMER_SAMPLING (TCD0) to TC_CLKSEL_EVCH6_gc = Event Channel 6 */ CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_EVCH6_gc; /* Start looking out for modulation pause via interrupt. */ - CODEC_DEMOD_IN_PORT.INTFLAGS = 0x03; + /* Sets register INTFLAGS to PORT_INT0LVL_HI_gc = (0x03<<0) to enable compare/capture for high level interrupts on CODEC_DEMOD_IN_PORT (PORTB) */ + CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT0LVL_HI_gc; + /* Sets INT0MASK to CODEC_DEMOD_IN_MASK0 = PIN1_bm to use it as source for port interrupt 0 */ CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; } void ISO15693CodecInit(void) { CodecInitCommon(); + + /* Register isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT function + * to CODEC_TIMER_SAMPLING (TCD0)'s Counter Channel C (CCC) + */ isr_func_TCD0_CCC_vect = &isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT; + /* Register isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT function + * to CODEC_DEMOD_IN_PORT (PORTB) interrupt 0 + */ isr_func_CODEC_DEMOD_IN_INT0_VECT = &isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT; + /* Register isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT function + * to CODEC_TIMER_LOADMOD (TCE0)'s Counter Channel B (CCB) + */ isr_func_CODEC_TIMER_LOADMOD_CCB_VECT = &isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT; + StartISO15693Demod(); } @@ -486,11 +565,12 @@ void ISO15693CodecDeInit(void) /* Gracefully shutdown codec */ CODEC_DEMOD_IN_PORT.INT0MASK = 0; + /* Reset global variables to default values */ CodecBufferPtr = CodecBuffer; Flags.DemodFinished = 0; Flags.LoadmodFinished = 0; DemodState = DEMOD_SOC_STATE; - LoadModState = LOADMOD_WAIT; + StateRegister = LOADMOD_WAIT; DataRegister = 0; SampleRegister = 0; BitSampleCount = 0; @@ -499,15 +579,22 @@ void ISO15693CodecDeInit(void) ByteCount = 0; ShiftRegister = 0; - //Disable sample timer + /* Disable sample timer */ + /* Sets timer off for CODEC_TIMER_SAMPLING (TCD0) disabling clock source */ CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + /* Disable event action for CODEC_TIMER_SAMPLING (TCD0) */ CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + /* Sets register INTCTRLB to TC_CCCINTLVL_OFF_gc = (0x00<<4) to disable compare/capture C interrupts */ CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; + /* Restore Counter Channel C (CCC) interrupt mask (TC0_CCCIF_bm) */ CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; - //Disable load modulation + /* Disable load modulation */ + /* Disable event action for CODEC_TIMER_LOADMOD (TCE0) */ CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; + /* Sets register INTCTRLB to TC_CCBINTLVL_OFF_gc = (0x00<<2) to disable compare/capture B interrupts */ CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_OFF_gc; + /* Restore Counter Channel B (CCB) interrupt mask (TC0_CCBIF_bm) */ CODEC_TIMER_LOADMOD.INTFLAGS = TC0_CCBIF_bm; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); @@ -554,8 +641,10 @@ void ISO15693CodecTask(void) } } else { - /* No data to be processed. Disable T1 waiting and start listening again */ + /* No data to process. Disable CODEC_TIMER_LOADMOD (TCE0) counter and start listening again */ + /* Sets timer off for CODEC_TIMER_LOADMOD (TCE0) disabling clock source as we're done modulating */ CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + /* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */ CODEC_TIMER_LOADMOD.INTCTRLB = 0; StartISO15693Demod(); @@ -564,8 +653,7 @@ void ISO15693CodecTask(void) if (Flags.LoadmodFinished) { Flags.LoadmodFinished = 0; - /* Load modulation has been finished. Stop it and start to listen - * for incoming data again. */ + /* Load modulation has been finished. Stop it and start to listen for incoming data again. */ StartISO15693Demod(); } }