From 119096971efedf476076bccc105a4219a4e7c669 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Mon, 12 Nov 2018 15:12:01 +0100 Subject: [PATCH 01/31] Fixed indentation. Sorry, it's driving me nuts --- .../Chameleon-Mini/Application/TITagitstandard.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index b68a243..73784fb 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -183,13 +183,11 @@ void TITagitstandardSetUid(ConfigurationUidType Uid) void TITagitstandardFlipUid(ConfigurationUidType Uid) { - - uint8_t tmp , *tail ; - tail = Uid + ActiveConfiguration.UidSize - 1; - while ( Uid < tail ){ - tmp = *Uid; - *Uid++ = *tail ; - *tail-- = tmp; - } - + uint8_t tmp, *tail; + tail = Uid + ActiveConfiguration.UidSize - 1; + while ( Uid < tail ) { + tmp = *Uid; + *Uid++ = *tail; + *tail-- = tmp; + } } \ No newline at end of file From b83b4f80e7de5ee4c910ba9c3681dc61315c9562 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Wed, 28 Nov 2018 18:40:51 +0100 Subject: [PATCH 02/31] Added tag family configuration --- Firmware/Chameleon-Mini/Button.c | 5 + Firmware/Chameleon-Mini/Configuration.c | 122 +++++++++++--------- Firmware/Chameleon-Mini/Configuration.h | 11 ++ Firmware/Chameleon-Mini/Terminal/Commands.c | 5 + 4 files changed, 89 insertions(+), 54 deletions(-) diff --git a/Firmware/Chameleon-Mini/Button.c b/Firmware/Chameleon-Mini/Button.c index 3791783..33f3eb5 100644 --- a/Firmware/Chameleon-Mini/Button.c +++ b/Firmware/Chameleon-Mini/Button.c @@ -4,6 +4,7 @@ #include "Settings.h" #include "Memory.h" #include "Map.h" +#include "Configuration.h" #include "Terminal/CommandLine.h" #include "Application/Application.h" @@ -42,6 +43,10 @@ static void ExecuteButtonAction(ButtonActionEnum ButtonAction) for (uint8_t i=0; i Date: Thu, 29 Nov 2018 18:00:36 +0100 Subject: [PATCH 03/31] Added bitmask to track locked blocks, Lock Block command, sanity checks on received data. --- .../Application/TITagitstandard.c | 73 ++++++++++++++++--- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 73784fb..f334b99 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -22,6 +22,9 @@ static enum { STATE_QUIET } State; +uint16_t UserLockBits_Mask = 0; /* Holds lock state of blocks */ +uint16_t FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ + //ISO15693UidType Uid = {0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0xE0}; //0xE0 = iso15693 //0x07 = TEXAS INSTRUMENTS @@ -30,6 +33,9 @@ static enum { void TITagitstandardAppInit(void) { State = STATE_READY; + FactoryLockBits_Mask |= (1 << 8); /* Locks block 8... */ + FactoryLockBits_Mask |= (1 << 9); /* ...and 9, which contains the UID */ + UserLockBits_Mask |= (1 << 3); /* TESTING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ } void TITagitstandardAppReset(void) @@ -92,19 +98,24 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) } if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - /* UID is stored in blocks 8 and 9 which are blocked */ - FrameBuf[1] = ( PageAddress == 8 || PageAddress == 9) ? 0x02 : 0x00; /* block security status: when request has the option flag set */ + if (FactoryLockBits_Mask & (1 << PageAddress)) { /* 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 (UserLockBits_Mask & (1 << PageAddress)) { /* 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; ResponseByteCount = 6; - } else { /* request with option flag not set*/ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* Flags */ + } else { /* request with option flag not set */ FramePtr = FrameBuf + 1; ResponseByteCount = 5; } - MemoryReadBlock(FramePtr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + MemoryReadBlock(FramePtr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); } else if (Command == ISO15693_CMD_WRITE_SINGLE) { @@ -112,6 +123,8 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) uint8_t PageAddress; if (ISO15693Addressed(FrameBuf)) { + if (FrameBytes < (0x01 + 0x01 + 0x08 + 0x01 + 0x04)) /* flag + cmd + uid + block number + data */ + break; /* malformed: not enough data */ if (ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) {/* write is addressed to us */ /* pick block 2 + 8 (UID Lenght) */ PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x08]; /*when receiving an addressed request pick block number from 10th byte in the request*/ @@ -121,17 +134,57 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) else /* we are not the addressee of the write command */ break; } else { /* request is not addressed */ + if (FrameBytes < (0x01 + 0x01 + 0x01 + 0x04)) /* flag + cmd + block number + data */ + break; /* malformed: not enough data */ PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM]; Dataptr = &FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x01]; } - MemoryWriteBlock(Dataptr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - ResponseByteCount = 1; + if (FactoryLockBits_Mask & (1 << PageAddress)) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_ADDR_FLAGS + 1] = ISO15693_RES_ERR_OPT_NOT_SUPP; + ResponseByteCount = 2; + } else if (UserLockBits_Mask & (1 << PageAddress)) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_ADDR_FLAGS + 1] = ISO15693_RES_ERR_BLK_CHG_LKD; + ResponseByteCount = 2; + } else { + MemoryWriteBlock(Dataptr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + } } + + else if (Command == ISO15693_CMD_LOCK_BLOCK) { + uint8_t PageAddress; + if (ISO15693Addressed(FrameBuf)) { + if (FrameBytes < (0x01 + 0x01 + 0x08 + 0x01)) /* flag + cmd + uid + block number + data */ + break; /* malformed: not enough data */ + if (ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) {/* write is addressed to us */ + /* pick block 2 + 8 (UID Lenght) */ + PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x08]; /*when receiving an addressed request pick block number from 10th byte in the request*/ + } + else /* we are not the addressee of the write command */ + break; + } else { /* request is not addressed */ + if (FrameBytes < (0x01 + 0x01 + 0x01)) /* flag + cmd + block number + data */ + break; /* malformed: not enough data */ + PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM]; + } + + if ((FactoryLockBits_Mask & (1 << PageAddress)) || (UserLockBits_Mask & (1 << PageAddress))) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_ADDR_FLAGS + 1] = ISO15693_RES_ERR_BLK_ALRD_LKD; + ResponseByteCount = 2; + } else { + UserLockBits_Mask |= (1 << PageAddress); /* */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + } + } break; case STATE_SELECTED: - /* TODO: Selected has to be impemented altogether */ + /* Selected state is not supported by Ti TagIt Standard */ break; case STATE_QUIET: From 3ce502158d1e9eb720dbad969d6df47385df5898 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Thu, 29 Nov 2018 18:17:34 +0100 Subject: [PATCH 04/31] Removed testing stuff and removed todo --- Firmware/Chameleon-Mini/Application/TITagitstandard.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index f334b99..27e734a 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -5,8 +5,6 @@ * Author: Phillip Nash * Modified by rickventura for texas 15693 tag-it STANDARD * Modified by ceres-c to finish things up - * TODO: - * - Selected mode has to be impemented altogether - ceres-c */ #include "TITagitstandard.h" @@ -35,7 +33,6 @@ void TITagitstandardAppInit(void) State = STATE_READY; FactoryLockBits_Mask |= (1 << 8); /* Locks block 8... */ FactoryLockBits_Mask |= (1 << 9); /* ...and 9, which contains the UID */ - UserLockBits_Mask |= (1 << 3); /* TESTING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ } void TITagitstandardAppReset(void) From 28f647818e644d955b14b2bd929a569145dcf1ed Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Thu, 29 Nov 2018 18:33:30 +0100 Subject: [PATCH 05/31] Removed unsupported command ISO15693_CMD_RESET_TO_READY --- Firmware/Chameleon-Mini/Application/TITagitstandard.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 27e734a..ddc787f 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -185,13 +185,18 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) break; case STATE_QUIET: + /* Ti TagIt Standard does not support reset to ready command */ + /* following code is lef for future reference for other tags */ + /* if (Command == ISO15693_CMD_RESET_TO_READY) { - if (ISO15693Addressed(FrameBuf)) { + if (ISO15693Addressed(FrameBuf) && ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount = 1; State = STATE_READY; } } + */ + ResponseByteCount = 0; /* better safe than sorry */ break; default: From d091e2291b9095eddc33f10569c4ca62abafaada Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Mon, 3 Dec 2018 23:07:50 +0100 Subject: [PATCH 06/31] PrepareFrame function first draft, there might be performance issues --- .../Chameleon-Mini/Application/ISO15693-A.c | 40 +++ .../Chameleon-Mini/Application/ISO15693-A.h | 16 +- .../Application/TITagitstandard.c | 315 +++++++++--------- 3 files changed, 202 insertions(+), 169 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index 0f7f3d3..7837111 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -50,3 +50,43 @@ bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize) return (DataPtr[FrameBufSize] == crcLb && DataPtr[FrameBufSize + 1] == crcHb); } + +/* + * ISO15693PrepareFrame + * + * This function validates frame lenght and sets pointers in 'frame' struct + * to relevant byte(s) of 'FrameBuf'. Also sets frame.addressed as true if + * the command is addressed + * + * Returns: + * - 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 + */ +bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid) +{ + if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE)) + /* malformed frame */ + return false; + + /* following declarations are not dependent on addressed/unaddressed state */ + FrameStruct -> Flags = &FrameBuf[ISO15693_ADDR_FLAGS]; + FrameStruct -> Command = &FrameBuf[ISO15693_REQ_ADDR_CMD]; + FrameStruct -> Addressed = ( !(FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_INVENTORY) & (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_ADDRESS) ); + /* "inventory" flag must be 0, otherwise "addressed" flag have a different meaning (see ISO15693-3) */ + + 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)) { + /* addressed request but we're not the addressee */ + return false; + } else { + return true; + } +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index 3f45a6f..936dbe4 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -63,16 +63,26 @@ #define ISO15693_RES_INVENTORY_DSFID 0x00 -#define ISO15693_MIN_FRAME_SIZE 5 +#define ISO15693_MIN_FRAME_SIZE 0x05 -#define ISO15693_CRC16_SIZE 2 /* Bytes */ +#define ISO15693_GENERIC_UID_SIZE 0x08 +#define ISO15693_GENERIC_MEM_SIZE 8192 + +#define ISO15693_CRC16_SIZE 2 /* Bytes */ #define ISO15693_CRC16_POLYNORMAL 0x8408 #define ISO15693_CRC16_PRESET 0xFFFF -typedef uint8_t ISO15693UidType[8]; +typedef struct { + uint8_t* Flags; + uint8_t* Command; + uint8_t* Parameters; + uint8_t ParamLen; + bool Addressed; +} CurrentFrame; void ISO15693AppendCRC(uint8_t* FrameBuf, uint16_t FrameBufSize); bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize); +bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid); INLINE bool ISO15693CompareUid(uint8_t* Uid1, uint8_t* Uid2) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index ddc787f..63fcb7f 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -5,6 +5,9 @@ * 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 */ #include "TITagitstandard.h" @@ -22,22 +25,31 @@ static enum { uint16_t UserLockBits_Mask = 0; /* Holds lock state of blocks */ uint16_t FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ - -//ISO15693UidType Uid = {0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0xE0}; -//0xE0 = iso15693 -//0x07 = TEXAS INSTRUMENTS -//0xC0 0xC1 = "Tagitstandard" 0xC4 or 0xC5 "TagitPro" 0x00 or 0x01 or 0x80 or 0x81 "Tagitplus" +CurrentFrame FrameInfo; void TITagitstandardAppInit(void) { State = STATE_READY; + FactoryLockBits_Mask |= (1 << 8); /* Locks block 8... */ FactoryLockBits_Mask |= (1 << 9); /* ...and 9, which contains the UID */ + + FrameInfo.Flags = NULL; + FrameInfo.Command = NULL; + FrameInfo.Parameters = NULL; + FrameInfo.ParamLen = 0; + FrameInfo.Addressed = false; } void TITagitstandardAppReset(void) { State = STATE_READY; + + FrameInfo.Flags = NULL; + FrameInfo.Command = NULL; + FrameInfo.Parameters = NULL; + FrameInfo.ParamLen = 0; + FrameInfo.Addressed = false; } @@ -53,171 +65,142 @@ void TITagitstandardAppTick(void) uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) { - if (FrameBytes >= ISO15693_MIN_FRAME_SIZE) { - if(ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE)) { - // At this point, we have a valid ISO15693 frame - uint8_t Command = FrameBuf[1]; - uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; - uint8_t Uid[ActiveConfiguration.UidSize]; - TITagitstandardGetUid(Uid); + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + uint8_t Uid[ActiveConfiguration.UidSize]; + TITagitstandardGetUid(Uid); - switch(State) { - case STATE_READY: - if (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 (Command == ISO15693_CMD_STAY_QUIET) { - if (ISO15693Addressed(FrameBuf) && ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) - State = STATE_QUIET; - - } else if (Command == ISO15693_CMD_READ_SINGLE) { - uint8_t *FramePtr; - uint8_t PageAddress; - - if (ISO15693Addressed(FrameBuf)) { - if (ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) /* read is addressed to us */ - - /* pick block 2 + 8 (UID Lenght) */ - PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x08]; - else /* we are not the addressee of the read command */ - break; - } else /* request is not addressed */ - PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM]; - - if (PageAddress >= TITAGIT_NUMBER_OF_SECTORS) { /* 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; - break; - } - - if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ - if (FactoryLockBits_Mask & (1 << PageAddress)) { /* 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 (UserLockBits_Mask & (1 << PageAddress)) { /* 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; - ResponseByteCount = 6; - } else { /* request with option flag not set */ - FramePtr = FrameBuf + 1; - ResponseByteCount = 5; - } - - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - - MemoryReadBlock(FramePtr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); - } - - else if (Command == ISO15693_CMD_WRITE_SINGLE) { - uint8_t* Dataptr; - uint8_t PageAddress; - - if (ISO15693Addressed(FrameBuf)) { - if (FrameBytes < (0x01 + 0x01 + 0x08 + 0x01 + 0x04)) /* flag + cmd + uid + block number + data */ - break; /* malformed: not enough data */ - if (ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) {/* write is addressed to us */ - /* pick block 2 + 8 (UID Lenght) */ - PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x08]; /*when receiving an addressed request pick block number from 10th byte in the request*/ - /* pick block 2 + 8 (UID Lenght) + 1 (data starts here) */ - Dataptr = &FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x08 + 0x01]; /* addr of sent data to write in memory */ - } - else /* we are not the addressee of the write command */ - break; - } else { /* request is not addressed */ - if (FrameBytes < (0x01 + 0x01 + 0x01 + 0x04)) /* flag + cmd + block number + data */ - break; /* malformed: not enough data */ - PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM]; - Dataptr = &FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x01]; - } - - if (FactoryLockBits_Mask & (1 << PageAddress)) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_ADDR_FLAGS + 1] = ISO15693_RES_ERR_OPT_NOT_SUPP; - ResponseByteCount = 2; - } else if (UserLockBits_Mask & (1 << PageAddress)) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_ADDR_FLAGS + 1] = ISO15693_RES_ERR_BLK_CHG_LKD; - ResponseByteCount = 2; - } else { - MemoryWriteBlock(Dataptr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - ResponseByteCount = 1; - } - } - - else if (Command == ISO15693_CMD_LOCK_BLOCK) { - uint8_t PageAddress; - if (ISO15693Addressed(FrameBuf)) { - if (FrameBytes < (0x01 + 0x01 + 0x08 + 0x01)) /* flag + cmd + uid + block number + data */ - break; /* malformed: not enough data */ - if (ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) {/* write is addressed to us */ - /* pick block 2 + 8 (UID Lenght) */ - PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM + 0x08]; /*when receiving an addressed request pick block number from 10th byte in the request*/ - } - else /* we are not the addressee of the write command */ - break; - } else { /* request is not addressed */ - if (FrameBytes < (0x01 + 0x01 + 0x01)) /* flag + cmd + block number + data */ - break; /* malformed: not enough data */ - PageAddress = FrameBuf[ISO15693_REQ_ADDR_PARAM]; - } - - if ((FactoryLockBits_Mask & (1 << PageAddress)) || (UserLockBits_Mask & (1 << PageAddress))) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_ADDR_FLAGS + 1] = ISO15693_RES_ERR_BLK_ALRD_LKD; - ResponseByteCount = 2; - } else { - UserLockBits_Mask |= (1 << PageAddress); /* */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - ResponseByteCount = 1; - } - } - break; - case STATE_SELECTED: - /* Selected state is not supported by Ti TagIt Standard */ - break; - - case STATE_QUIET: - /* Ti TagIt Standard does not support reset to ready command */ - /* following code is lef for future reference for other tags */ - /* - if (Command == ISO15693_CMD_RESET_TO_READY) { - if (ISO15693Addressed(FrameBuf) && ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid)) { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; - ResponseByteCount = 1; - State = STATE_READY; - } - } - */ - ResponseByteCount = 0; /* better safe than sorry */ - break; - - default: - break; - } - - if (ResponseByteCount > 0) { - /* There is data to be sent. Append CRC */ - ISO15693AppendCRC(FrameBuf, ResponseByteCount); - ResponseByteCount += ISO15693_CRC16_SIZE; - } - - return ResponseByteCount; - - } else { // Invalid CRC - return ISO15693_APP_NO_RESPONSE; - } - } else { // Min frame size not met + 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) { + uint8_t *FramePtr; /* holds the address where block's data will be put */ + uint8_t PageAddress = *FrameInfo.Parameters; + + if (FrameInfo.ParamLen != 1) + break; /* malformed: not enough or too much data */ + + if (PageAddress >= TITAGIT_NUMBER_OF_SECTORS) { /* 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; + break; + } + + if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ + if (FactoryLockBits_Mask & (1 << PageAddress)) { /* 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 (UserLockBits_Mask & (1 << PageAddress)) { /* 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 * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); + } else if (*FrameInfo.Command == ISO15693_CMD_WRITE_SINGLE) { + uint8_t* Dataptr; + uint8_t PageAddress = *FrameInfo.Parameters; + + if (FrameInfo.ParamLen != 5) + break; /* malformed: not enough or too much data */ + + if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) + /* TODO: Check actual tag's response (error?) */ + break; /* malformed: trying to write in a non-existing block */ + + Dataptr = PageAddress + 0x01; + + if (FactoryLockBits_Mask & (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 (UserLockBits_Mask & (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 * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + } + } else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) { + uint8_t PageAddress = *FrameInfo.Parameters; + + if (FrameInfo.ParamLen != 1) + break; /* malformed: not enough or too much data */ + + if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) + /* TODO: Check actual tag's response (error?) */ + 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; + FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_ALRD_LKD; + ResponseByteCount = 2; + } else { + UserLockBits_Mask |= (1 << PageAddress); /* */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount = 1; + } + } 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: + /* Selected state is not supported by Ti TagIt Standard */ + break; + + case STATE_QUIET: + /* Ti TagIt Standard does not support reset to ready command */ + /* following code is lef for future reference for other tags */ + /* + if (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; + } + */ + ResponseByteCount = 0; /* better safe than sorry */ + break; + + default: + break; } + if (ResponseByteCount > 0) { + /* There is data to be sent. Append CRC */ + ISO15693AppendCRC(FrameBuf, ResponseByteCount); + ResponseByteCount += ISO15693_CRC16_SIZE; + } + + return ResponseByteCount; } void TITagitstandardGetUid(ConfigurationUidType Uid) From c8496d2087daa1e902a742ffcb00b49d2285be82 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 4 Dec 2018 11:03:41 +0100 Subject: [PATCH 07/31] Fixed couple of indent mistakes --- .../Chameleon-Mini/Application/TITagitstandard.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 63fcb7f..8132fc7 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -100,11 +100,9 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ if (FactoryLockBits_Mask & (1 << PageAddress)) { /* 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 (UserLockBits_Mask & (1 << PageAddress)) { /* tests if the n-th bit of the user bitmask if set to 1 */ + } else if (UserLockBits_Mask & (1 << PageAddress)) { /* 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 + } else FrameBuf[1] = 0x00; /* return lock status 00 (unlocked) */ FramePtr = FrameBuf + 2; /* block's data from byte 2 */ ResponseByteCount = 6; @@ -114,15 +112,15 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) } FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - MemoryReadBlock(FramePtr, PageAddress * TITAGIT_BYTES_PER_PAGE, TITAGIT_BYTES_PER_PAGE); + } else if (*FrameInfo.Command == ISO15693_CMD_WRITE_SINGLE) { uint8_t* Dataptr; uint8_t PageAddress = *FrameInfo.Parameters; if (FrameInfo.ParamLen != 5) break; /* malformed: not enough or too much data */ - + if (PageAddress > TITAGIT_NUMBER_OF_SECTORS) /* TODO: Check actual tag's response (error?) */ break; /* malformed: trying to write in a non-existing block */ @@ -142,6 +140,7 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount = 1; } + } else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) { uint8_t PageAddress = *FrameInfo.Parameters; @@ -161,12 +160,14 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount = 1; } + } 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: /* Selected state is not supported by Ti TagIt Standard */ break; From 168b565f237ee98b8758fdd274ba3479e433d445 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Tue, 4 Dec 2018 17:33:46 +0100 Subject: [PATCH 08/31] Fixed nasty bug in ISO15693PrepareFrame, removed unnecessary includes and implemented failsafe to command not supported to fix problems with Android apps. Everything just works. --- Firmware/Chameleon-Mini/Application/ISO15693-A.c | 9 ++++++--- Firmware/Chameleon-Mini/Application/TITagitstandard.c | 8 ++------ Firmware/Chameleon-Mini/Application/TITagitstandard.h | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index 7837111..5135135 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -72,8 +72,11 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* /* following declarations are not dependent on addressed/unaddressed state */ FrameStruct -> Flags = &FrameBuf[ISO15693_ADDR_FLAGS]; FrameStruct -> Command = &FrameBuf[ISO15693_REQ_ADDR_CMD]; - FrameStruct -> Addressed = ( !(FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_INVENTORY) & (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_ADDRESS) ); - /* "inventory" flag must be 0, otherwise "addressed" flag have a different meaning (see ISO15693-3) */ + + 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 -> Addressed = false; if (FrameStruct -> Addressed) /* UID sits between CMD and PARAM */ @@ -89,4 +92,4 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* } else { return true; } -} \ No newline at end of file +} diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 8132fc7..8441907 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -10,12 +10,8 @@ * - Check actual tag's response (error?) when trying to LOCK out of bound sectors */ -#include "TITagitstandard.h" -#include "../Codec/ISO15693.h" -#include "../Memory.h" -#include "Crypto1.h" -#include "../Random.h" #include "ISO15693-A.h" +#include "TITagitstandard.h" static enum { STATE_READY, @@ -229,4 +225,4 @@ void TITagitstandardFlipUid(ConfigurationUidType Uid) *Uid++ = *tail; *tail-- = tmp; } -} \ No newline at end of file +} diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.h b/Firmware/Chameleon-Mini/Application/TITagitstandard.h index bd984c5..a433913 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.h +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.h @@ -10,7 +10,6 @@ #define TITAGITSTANDARD_H_ #include "Application.h" -#include "ISO15693-A.h" #define TITAGIT_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE //ISO15693_UID_SIZE #define TITAGIT_STD_MEM_SIZE 44 //TAG-IT STANDARD MAX MEM SIZE @@ -27,4 +26,4 @@ void TITagitstandardGetUid(ConfigurationUidType Uid); void TITagitstandardSetUid(ConfigurationUidType Uid); void TITagitstandardFlipUid(ConfigurationUidType Uid); -#endif /* VICINITY_H_ */ \ No newline at end of file +#endif /* TITAGITSTANDARD_H_ */ From edb1d93084f9e1f2e21a24536e9dff6c19ebfa05 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 4 Dec 2018 18:00:37 +0100 Subject: [PATCH 09/31] 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 1da44037c69957372f15c5b099b08fb2546e7f33 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 4 Dec 2018 18:00:37 +0100 Subject: [PATCH 10/31] 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 fda9f07894e2022f022bb31d51741965a5ec0446 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Mon, 10 Dec 2018 12:55:38 +0100 Subject: [PATCH 11/31] Fixed a bug in write and lock commands - Missing parenthesis --- Firmware/Chameleon-Mini/Application/TITagitstandard.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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; From b28d8cb337748df7cf11a121c07b229bef4b8744 Mon Sep 17 00:00:00 2001 From: MrMoDDoM Date: Mon, 10 Dec 2018 19:43:43 +0100 Subject: [PATCH 12/31] 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 13/31] 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 14/31] 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 7bc809cc165d873af1235ae808674eee904481f5 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Sun, 16 Dec 2018 20:03:02 +0100 Subject: [PATCH 15/31] Backporting bug fixes and additions from EM4233 branch --- Firmware/Chameleon-Mini/Application/ISO15693-A.c | 9 ++++++--- Firmware/Chameleon-Mini/Application/ISO15693-A.h | 12 ++++++++++-- .../Chameleon-Mini/Application/TITagitstandard.c | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) 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 936dbe4..ac8fc31 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -63,21 +63,29 @@ #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 -#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_USER_LOCK ( 1 << 0 ) +#define ISO15693_MASK_FACTORY_LOCK ( 1 << 1 ) + typedef struct { uint8_t* Flags; uint8_t* Command; 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 aa237f0767480fdc00e3f783ade978b502e713f3 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Tue, 18 Dec 2018 00:13:57 +0100 Subject: [PATCH 16/31] 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 17/31] 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 18/31] 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 19/31] 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 20/31] 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 21/31] 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 22/31] 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 23/31] 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 24/31] 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 25/31] 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(); } } From ab1fdddb16ec655733f6d831c28d359b07c265b9 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Wed, 26 Dec 2018 23:13:57 +0100 Subject: [PATCH 26/31] Removed old LockBit masks and updated a couple of commands to mimick real tag behaviour --- Firmware/Chameleon-Mini/Application/EM4233.c | 171 +++++++++--------- .../Chameleon-Mini/Application/ISO15693-A.h | 1 + 2 files changed, 82 insertions(+), 90 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index 54a20f4..7cb4ce4 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -18,9 +18,6 @@ bool loggedIn; CurrentFrame FrameInfo; -uint64_t EM4233_FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ -uint64_t EM4233_UserLockBits_Mask = 0; /* Holds lock state of blocks */ - void EM4233AppInit(void) { State = STATE_READY; @@ -61,25 +58,28 @@ 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; + uint8_t BlockAddress = *FrameInfo.Parameters; + uint8_t LockStatus = 0; + + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + BlockAddress), 1); if (FrameInfo.ParamLen != 1) - return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ - if (PageAddress > EM4233_NUMBER_OF_BLCKS) { + if (BlockAddress > EM4233_NUMBER_OF_BLCKS) { // 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; + + if (LockStatus > ISO15693_MASK_UNLOCKED) { /* LockStatus 0x00 represent unlocked block, greater values are different kind of locks */ 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; + LockStatus |= ISO15693_MASK_USER_LOCK; + MemoryWriteBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + BlockAddress), 1); /* write user lock in memory */ + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ } @@ -135,7 +135,7 @@ uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) 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; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_BLK_NOT_AVL; ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } @@ -145,11 +145,11 @@ uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) 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[FramePtr] = 0x02; /* return bit 1 set as 1 (factory locked) */ + FrameBuf[FramePtr] = ISO15693_MASK_FACTORY_LOCK; /* 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) */ + FrameBuf[FramePtr] = ISO15693_MASK_USER_LOCK; /* return bit 0 set as 1 (user locked) */ } else - FrameBuf[FramePtr] = 0x00; /* return lock status 00 (unlocked) */ + FrameBuf[FramePtr] = ISO15693_MASK_UNLOCKED; /* return lock status 00 (unlocked) */ FramePtr += 1; /* block's data from byte 2 */ ResponseByteCount += 1; } @@ -159,7 +159,7 @@ uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ ResponseByteCount += 1; - + return ResponseByteCount; } @@ -168,14 +168,14 @@ 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 = FrameInfo.Parameters[1] + 0x01; /* according to ISO standard, we have to read 8 blocks if we get 0x07 in request */ + uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01; /* according to ISO standard, we have to read 0x08 blocks if we get 0x07 in request */ if (FrameInfo.ParamLen != 2) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ 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; + // 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 */ @@ -191,7 +191,7 @@ uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) } 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 */ + uint8_t LockStatusBuffer[ BlocksNumber ]; /* a temporary 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); @@ -200,20 +200,15 @@ uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) 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) */ + FrameBuf[FramePtr++] = LockStatusBuffer[block]; /* Byte in dump equals to the byte that has to be sent */ + /* I.E. We store 0x01 to identify user lock, which is the same as what ISO15693 enforce */ ResponseByteCount += 1; - FramePtr += 1; /* 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; - } + FrameBuf[FramePtr++] = DataBuffer[block * EM4233_BYTES_PER_BLCK + 0]; + FrameBuf[FramePtr++] = DataBuffer[block * EM4233_BYTES_PER_BLCK + 1]; + FrameBuf[FramePtr++] = DataBuffer[block * EM4233_BYTES_PER_BLCK + 2]; + FrameBuf[FramePtr++] = DataBuffer[block * EM4233_BYTES_PER_BLCK + 3]; ResponseByteCount += EM4233_BYTES_PER_BLCK; } } @@ -227,41 +222,44 @@ 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; + 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; + 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; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ 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; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + // ResponseByteCount += 1; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } uint16_t EM4233_Lock_AFI(uint8_t* FrameBuf, uint16_t FrameBytes) { uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; - uint8_t LockStatus = 0; + 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; + 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; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } @@ -269,8 +267,9 @@ uint16_t EM4233_Lock_AFI(uint8_t* FrameBuf, uint16_t FrameBytes) MemoryWriteBlock(&LockStatus, EM4233_MEM_INF_ADDRESS, 1); /* Actually write new AFI */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + // ResponseByteCount += 1; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } @@ -278,50 +277,54 @@ 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; + 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; + if (LockStatus & EM4233_MASK_DSFID_STATUS ) { /* The DSFID is locked */ + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + // ResponseByteCount += 2; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } - MemoryWriteBlock(&DSFID, EM4233_MEM_DSFID_ADDRESS, 1); /* Actually write new AFI */ + MemoryWriteBlock(&DSFID, EM4233_MEM_DSFID_ADDRESS, 1); /* Actually write new DSFID */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + // ResponseByteCount += 1; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } uint16_t EM4233_Lock_DSFID(uint8_t* FrameBuf, uint16_t FrameBytes) { uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; - uint8_t LockStatus = 0; + 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; + if (LockStatus & EM4233_MASK_DSFID_STATUS ) { /* The DSFID is already locked */ + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC; + // ResponseByteCount += 2; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } LockStatus |= EM4233_MASK_DSFID_STATUS; - MemoryWriteBlock(*FrameInfo.Parameters, EM4233_MEM_INF_ADDRESS, 4); /* Actually write the new PASSWORD */ + MemoryWriteBlock(*FrameInfo.Parameters, EM4233_MEM_INF_ADDRESS, 4); /* Actually write the new DSFID */ - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ + // ResponseByteCount += 1; + ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ return ResponseByteCount; } @@ -345,7 +348,7 @@ uint8_t EM4233_Get_SysInfo(uint8_t* FrameBuf, uint16_t FrameBytes) */ /* System info flags */ - FrameBuf[FramePtr] = EM4233_SYSINFO_BYTE; /* check pdf for this */ + FrameBuf[FramePtr] = EM4233_SYSINFO_BYTE; /* check EM4233SLIC datasheet for this */ FramePtr += 1; /* Move forward the buffer data pointer */ ResponseByteCount += 1; /* Increment the response count */ @@ -389,7 +392,7 @@ uint8_t EM4233_Get_SysInfo(uint8_t* FrameBuf, uint16_t FrameBytes) } FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + ResponseByteCount += 1; return ResponseByteCount; } @@ -398,40 +401,28 @@ 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; + uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01; 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++) { - - 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 */ - } + /* read all at once to reduce timing issues */ + MemoryReadBlock(&FrameBuf[FramePtr], EM4233_MEM_LSM_ADDRESS + BlockAddress, BlocksNumber); + ResponseByteCount += BlocksNumber; FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + ResponseByteCount += 1; return ResponseByteCount; } @@ -463,13 +454,13 @@ uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) return ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ } - return ISO15693_APP_NO_RESPONSE; + return ISO15693_APP_NO_RESPONSE; /* Just because you never know... */ } 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 }; + uint8_t Password[4] = { 0 }; if (FrameInfo.ParamLen != 4) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ @@ -489,10 +480,10 @@ uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) loggedIn = true; - MemoryWriteBlock(Password, EM4233_MEM_PSW_ADDRESS, 4); /* Actually write new AFI */ + MemoryWriteBlock(Password, EM4233_MEM_PSW_ADDRESS, 4); /* Store password in memory for retrival */ FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ - ResponseByteCount += 1; + ResponseByteCount += 1; return ResponseByteCount; } diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index ac8fc31..afe6691 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -76,6 +76,7 @@ * The byte used for the lock status has its bits addressed as follow: * */ +#define ISO15693_MASK_UNLOCKED ( 0 << 0 ) #define ISO15693_MASK_USER_LOCK ( 1 << 0 ) #define ISO15693_MASK_FACTORY_LOCK ( 1 << 1 ) From 9b5dfc2708dc690269e6d1790d8b0ead3984d48f Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Thu, 27 Dec 2018 00:16:34 +0100 Subject: [PATCH 27/31] Updated EM4233 header and example dump We thought that the user had access to 64 blocks, while in EM4233 factsheet it's stated that only 52 blocks are available --- Dumps/EM4233_example.dmp | Bin 352 -> 292 bytes Firmware/Chameleon-Mini/Application/EM4233.h | 23 ++++++++---------- .../Chameleon-Mini/Application/ISO15693-A.h | 5 +--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Dumps/EM4233_example.dmp b/Dumps/EM4233_example.dmp index e9f4caaa5851d6022b8c6f217498f1dc7ec28296..4387c6ee17d99fcb848b2ae1fbf8e97a322d9b3d 100644 GIT binary patch delta 13 UcmaFBw1jEGg-MJqlLHt904Cc6v;Y7A delta 65 hcmZ3&^nhu?1p_5CV2lPB(7?nCE)zfSOcr4j006ZA3{wCA diff --git a/Firmware/Chameleon-Mini/Application/EM4233.h b/Firmware/Chameleon-Mini/Application/EM4233.h index e1d370b..a7efbee 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.h +++ b/Firmware/Chameleon-Mini/Application/EM4233.h @@ -11,25 +11,24 @@ #include "Application.h" #define EM4233_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE -#define EM4233_STD_MEM_SIZE 208 // Bytes +#define EM4233_STD_MEM_SIZE 0xD0 // Bytes #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) ) -#define EM4233_IC_REFERENCE 0x02 +#define EM4233_IC_REFERENCE 0x02 // From EM4233SLIC datasheet and checked against real tags -#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_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_UID_ADDRESS 0xD0 // From 0x0100 to 0x0107 - UID +#define EM4233_MEM_AFI_ADDRESS 0xD8 // AFI byte address +#define EM4233_MEM_DSFID_ADDRESS 0xD9 // DSFID byte adress +#define EM4233_MEM_INF_ADDRESS 0xDC // Some status bits -#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_MEM_LSM_ADDRESS 0xE0 // From 0xE0 to 0x0113 - Lock status masks +#define EM4233_MEM_PSW_ADDRESS 0x0114 // From 0x0114 to 0x0117 - 32 bit Password +#define EM4233_MEM_KEY_ADDRESS 0x0118 // From 0x0118 to 0x0123 - 96 bit Encryption Key -#define EM4233_SYSINFO_BYTE 0x0F // DSFID - AFI - VICC mem size - IC ref are present +#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 @@ -37,8 +36,6 @@ #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 ) - /* Custom command code */ #define EM4233_CMD_SET_EAS 0xA2 #define EM4233_CMD_RST_EAS 0xA3 diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index afe6691..2d43f6b 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -72,10 +72,7 @@ #define ISO15693_CRC16_POLYNORMAL 0x8408 #define ISO15693_CRC16_PRESET 0xFFFF -/* - * The byte used for the lock status has its bits addressed as follow: - * - */ +/* The lock status byte has bits assigned as follow */ #define ISO15693_MASK_UNLOCKED ( 0 << 0 ) #define ISO15693_MASK_USER_LOCK ( 1 << 0 ) #define ISO15693_MASK_FACTORY_LOCK ( 1 << 1 ) From f3f59beb9a11d90d5770e78c944f9c4cb6a79542 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Thu, 27 Dec 2018 01:21:07 +0100 Subject: [PATCH 28/31] Added 010 hex Editor template file To aid in quick dump modifications --- Software/EM4233_010Editor_Template.bt | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Software/EM4233_010Editor_Template.bt diff --git a/Software/EM4233_010Editor_Template.bt b/Software/EM4233_010Editor_Template.bt new file mode 100644 index 0000000..e762546 --- /dev/null +++ b/Software/EM4233_010Editor_Template.bt @@ -0,0 +1,33 @@ +//------------------------------------------------ +//--- 010 Editor v9.0.1 Binary Template +// +// File: EM4233 ChameleonMini dump format +// Authors: ceres-c +// Version: 1.0 +// Purpose: Quick edit of custom dumps +// Category: Electronics +// File Mask: +// ID Bytes: +// History: +// 1.0 2018-12-27 ceres-c: Initial release +//------------------------------------------------ + +struct FILE { + struct Card_dump { + char Data[4] ; + } block [52]; + + struct Emulation_data { + char UID[8] ; + char AFI[1] ; + char DSFID[1] ; + char RFU[2] ; + char Info_bits[4] ; + struct Lock_status_bytes { + char lsbyte ; + } lsb [52]; + char Password[4] ; + char Key[12] ; + } emudata; + +} file ; \ No newline at end of file From 5f6c35d7a690c7c9ceb83a412ccb7f3f67627362 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Fri, 28 Dec 2018 00:28:22 +0100 Subject: [PATCH 29/31] First draft of anticollision sequence Only 1 slot mode has been implemented, but it seems to work even for 16 slots mode. This needs to be checked with other readers. --- Firmware/Chameleon-Mini/Application/EM4233.c | 18 ++++-- .../Chameleon-Mini/Application/ISO15693-A.c | 58 ++++++++++++++++++- .../Chameleon-Mini/Application/ISO15693-A.h | 3 +- .../Application/TITagitstandard.c | 5 +- .../Application/TITagitstandard.h | 3 +- 5 files changed, 77 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index 7cb4ce4..c94097c 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -15,6 +15,7 @@ static enum { } State; bool loggedIn; +uint8_t MyAFI; /* This variable holds current tag's AFI (is used in inventory) */ CurrentFrame FrameInfo; @@ -29,6 +30,7 @@ void EM4233AppInit(void) FrameInfo.Addressed = false; FrameInfo.Selected = false; loggedIn = false; + MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1); } @@ -238,6 +240,7 @@ uint16_t EM4233_Write_AFI(uint8_t* FrameBuf, uint16_t FrameBytes) } MemoryWriteBlock(&AFI, EM4233_MEM_AFI_ADDRESS, 1); /* Actually write new AFI */ + MyAFI = AFI; /* And update global variable */ // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ // ResponseByteCount += 1; @@ -493,15 +496,20 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) uint8_t Uid[ActiveConfiguration.UidSize]; EM4233GetUid(Uid); - if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid)) + if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid, MyAFI)) return ISO15693_APP_NO_RESPONSE; 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); - ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid); - ResponseByteCount = 10; + if (FrameInfo.ParamLen == 0) + return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ + + if (ISO15693AntiColl (FrameBuf, FrameBytes, &FrameInfo, Uid)) { + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + MemoryReadBlock(&FrameBuf[ISO15693_RES_ADDR_PARAM], EM4233_MEM_DSFID_ADDRESS, 1); + ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid); + ResponseByteCount += 10; + } } else if ( (*FrameInfo.Command == ISO15693_CMD_STAY_QUIET ) && FrameInfo.Addressed) { State = STATE_QUIET; diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index b271db8..9224606 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -65,7 +65,7 @@ bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize) * * Authors: ceres-c & MrMoDDoM */ -bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid) +bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid, uint8_t MyAFI) { if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE)) /* malformed frame */ @@ -91,10 +91,18 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* 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 -> Parameters += 0x01; + } + else if ( ((*FrameStruct -> Command) == ISO15693_CMD_INVENTORY) && (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_AFI)) { + /* or if it is Inventory with AFI flag set */ + /* then between CMD and UID is placed another byte which is requested AFI, but we don't need it */ + if (FrameBuf[ISO15693_REQ_ADDR_PARAM] != MyAFI) + /* if requested AFI is different from our current one, then don't respond */ + return false; + FrameStruct -> Parameters += 0x01; } FrameStruct -> ParamLen = FrameBuf + (FrameBytes - ISO15693_CRC16_SIZE) - (FrameStruct -> Parameters); @@ -108,3 +116,49 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* return true; } } + +/* + * ISO15693AntiColl + * + * This function performs ISO15693 Anticollision + * + * Returns: + * - true: Inventory is addressed to us and a response is needed + * - false: Request is not addressed to us (different bitmask) + * and no response should be issued. + * + * Authors: ceres-c + * + * TODO: + * - Implement 16 slots mode (still, it seems to work as it is, even for 16 slots mode ._.) + */ +bool ISO15693AntiColl(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid) { + uint8_t CurrentUID[ ISO15693_GENERIC_UID_SIZE ]; /* Holds the UID flipped */ + ISO15693CopyUid(CurrentUID, MyUid); + + uint8_t MaskLenght = *FrameStruct -> Parameters; /* First byte of parameters is mask lenght... */ + uint8_t* MaskValue = FrameStruct -> Parameters + 1; /* ... then the mask itself begins */ + uint8_t BytesNum = MaskLenght / 8; /* Gets the number of full bytes in mask */ + uint8_t BitsNum = MaskLenght % 8; /* Gets the number of spare bits */ + + uint8_t B; /* B stands for Bytes and will be our reference point (I know, terrible name, I'm sorry) */ + /* Compare the full bytes in mask with UID */ + for (B = 0; B < BytesNum; B++ ) { + if (CurrentUID[B] != MaskValue[B]) + return false; /* UID different */ + } + /* Once we got here, B points for sure to the last byte of the mask, the one composed of spare bits */ + + /* Compare spare bits in mask with bits of UID */ + uint8_t BitsMask = ((1 << BitsNum) - 1); /* (1 << Bits) = 00010000 -> (1 << Bits) - 1 = 00001111 */ + if ((MaskValue[B] & BitsMask) != (CurrentUID[B] & BitsMask)) { + /* |-----------------------| Here we extract bits from the mask we received from the reader + * |------------------------| Here we extract bits from the UID + * The two extracted bit vectors are compared, if different then we're not the addressee. + * Only the latest byte of MaskValue and UID is considered. + */ + return false; + } + + return true; +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index 2d43f6b..f99c6b6 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -88,7 +88,8 @@ typedef struct { void ISO15693AppendCRC(uint8_t* FrameBuf, uint16_t FrameBufSize); bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize); -bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid); +bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid, uint8_t MyAFI); +bool ISO15693AntiColl(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid); INLINE bool ISO15693CompareUid(uint8_t* Uid1, uint8_t* Uid2) diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 3208bf6..3e1cc5d 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -16,6 +16,7 @@ static enum { STATE_QUIET } State; +uint8_t MyAFI; /* Holds current tag's AFI (is used in inventory) */ uint16_t UserLockBits_Mask = 0; /* Holds lock state of blocks */ uint16_t FactoryLockBits_Mask = 0; /* Holds lock state of blocks */ CurrentFrame FrameInfo; @@ -33,6 +34,8 @@ void TITagitstandardAppInit(void) FrameInfo.ParamLen = 0; FrameInfo.Addressed = false; FrameInfo.Selected = false; + + MemoryReadBlock(&MyAFI, TITAGIT_MEM_AFI_ADDRESS, 1); } void TITagitstandardAppReset(void) @@ -64,7 +67,7 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) uint8_t Uid[ActiveConfiguration.UidSize]; TITagitstandardGetUid(Uid); - if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid)) + if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid, MyAFI)) return ISO15693_APP_NO_RESPONSE; switch(State) { diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.h b/Firmware/Chameleon-Mini/Application/TITagitstandard.h index a433913..2c264c6 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.h +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.h @@ -12,10 +12,11 @@ #include "Application.h" #define TITAGIT_STD_UID_SIZE ISO15693_GENERIC_UID_SIZE //ISO15693_UID_SIZE -#define TITAGIT_STD_MEM_SIZE 44 //TAG-IT STANDARD MAX MEM SIZE +#define TITAGIT_STD_MEM_SIZE 44 //TAG-IT STANDARD MAX MEM SIZE #define TITAGIT_BYTES_PER_PAGE 4 #define TITAGIT_NUMBER_OF_SECTORS ( TITAGIT_STD_MEM_SIZE / TITAGIT_BYTES_PER_PAGE ) #define TITAGIT_MEM_UID_ADDRESS 0x20 +#define TITAGIT_MEM_AFI_ADDRESS 0x28 // AFI byte address void TITagitstandardAppInit(void); void TITagitstandardAppReset(void); From 39c251c7d508f89d0ae9f94680d9a27dc406141f Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Fri, 28 Dec 2018 13:42:17 +0100 Subject: [PATCH 30/31] Fixed Select command and some minor bug fixes Select command did not fall back to READY state if Select was issued on another tag. PrepareFrame allowed the tag to respond to Selected requests even if we were not in SELECTED state. Also fixed Read Single and Read Multiple out of bound reads in case of addressed commands. --- Firmware/Chameleon-Mini/Application/EM4233.c | 123 +++++++++++------- .../Chameleon-Mini/Application/ISO15693-A.c | 12 +- .../Chameleon-Mini/Application/ISO15693-A.h | 2 +- .../Chameleon-Mini/Application/Sl2s2002.h | 3 - .../Application/TITagitstandard.c | 2 +- 5 files changed, 87 insertions(+), 55 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index c94097c..8fc69c7 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -3,6 +3,9 @@ * * Created on: 12-05-2018 * Author: ceres-c & MrMoDDoM + * TODO: + * - Check with real tag every command's actual response in addressed/selected State + * (Only EM4233_Read_Single and EM4233_Read_Multiple have been checked up to now) */ #include "ISO15693-A.h" @@ -91,22 +94,21 @@ uint16_t EM4233_Lock_Block(uint8_t* FrameBuf, uint16_t FrameBytes) 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 BlockAddress = *FrameInfo.Parameters; + uint8_t* Dataptr = BlockAddress + 0x01; /* Data to write begins on 2nd byte of the frame received by the reader */ 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) { + if (BlockAddress > EM4233_NUMBER_OF_BLCKS) { // 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; + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + BlockAddress), 1); if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; @@ -117,7 +119,7 @@ uint16_t EM4233_Write_Single(uint8_t* FrameBuf, uint16_t FrameBytes) // 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); + MemoryWriteBlock(Dataptr, BlockAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; ResponseByteCount += 1; } @@ -129,23 +131,25 @@ 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 BlockAddress = FrameInfo.Parameters[0]; 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; - ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* real tag does not respond anyway */ - return ResponseByteCount; + if (BlockAddress >= EM4233_NUMBER_OF_BLCKS) { /* check if the reader is requesting a sector out of bound */ + if (FrameInfo.Addressed) { /* If the request is addressed */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = 0x0F; /* Magic number from real tag */ + ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */ + } + return ResponseByteCount; /* If not addressed real tag does not respond */ } FramePtr = 1; if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set */ - MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + PageAddress), 1); + MemoryReadBlock(&LockStatus, (EM4233_MEM_LSM_ADDRESS + BlockAddress), 1); if (LockStatus & ISO15693_MASK_FACTORY_LOCK) { /* tests if the n-th bit of the factory bitmask if set to 1 */ FrameBuf[FramePtr] = ISO15693_MASK_FACTORY_LOCK; /* 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 */ @@ -156,7 +160,7 @@ uint16_t EM4233_Read_Single(uint8_t* FrameBuf, uint16_t FrameBytes) ResponseByteCount += 1; } - MemoryReadBlock(&FrameBuf[FramePtr], PageAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); + MemoryReadBlock(&FrameBuf[FramePtr], BlockAddress * EM4233_BYTES_PER_BLCK, EM4233_BYTES_PER_BLCK); ResponseByteCount += 4; FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */ @@ -175,11 +179,13 @@ uint16_t EM4233_Read_Multiple(uint8_t* FrameBuf, uint16_t FrameBytes) if (FrameInfo.ParamLen != 2) return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */ - 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; + if (BlockAddress >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a block out of bound */ + if (FrameInfo.Addressed) { /* If the request is addressed */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + FrameBuf[ISO15693_RES_ADDR_PARAM] = 0x0F; /* Magic number from real tag */ + ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */ + } + return ResponseByteCount; /* If not addressed real tag does not respond */ } 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 */ } @@ -431,6 +437,7 @@ uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t* FrameBuf, uint16_t FrameBytes) uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) { + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; /* I've no idea how this request could generate errors ._. if ( ) { FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; @@ -442,22 +449,48 @@ uint16_t EM4233_Select(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) bool UidEquals = ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], Uid); - if (!FrameInfo.Addressed || FrameInfo.Selected) { + if (!(FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_ADDRESS) || + (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_SELECT) + ) { /* 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 */ + } else if (!UidEquals) { + /* tag should remain silent and reset if Select is performed against another UID, + * whether our the tag is selected or not + */ 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 */ + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount += 1; + return ResponseByteCount; } +} - return ISO15693_APP_NO_RESPONSE; /* Just because you never know... */ +uint16_t EM4233_Reset_To_Ready(uint8_t* FrameBuf, uint16_t FrameBytes) +{ + uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; + /* 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; + } + */ + FrameInfo.Flags = NULL; + FrameInfo.Command = NULL; + FrameInfo.Parameters = NULL; + FrameInfo.ParamLen = 0; + FrameInfo.Addressed = false; + FrameInfo.Selected = false; + + State = STATE_READY; + + FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; + ResponseByteCount += 1; + return ResponseByteCount; } uint16_t EM4233_Login(uint8_t* FrameBuf, uint16_t FrameBytes, uint8_t* Uid) @@ -496,7 +529,14 @@ uint16_t EM4233AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) uint8_t Uid[ActiveConfiguration.UidSize]; EM4233GetUid(Uid); - if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid, MyAFI)) + if (FrameBuf[ISO15693_REQ_ADDR_CMD] == ISO15693_CMD_SELECT) { + /* Select has its own path before PrepareFrame because we have to change the variable State + * from Select to Ready if "Select" cmd is addressed to another tag. + * It felt weird to add this kind of check in ISO15693PrepareFrame, which should not + * interfere with tag specific variables, such as State in this case. + */ + ResponseByteCount = EM4233_Select(FrameBuf, FrameBytes, Uid); + } else if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, State == STATE_SELECTED, Uid, MyAFI)) return ISO15693_APP_NO_RESPONSE; if (State == STATE_READY || State == STATE_SELECTED) { @@ -543,30 +583,25 @@ 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 == ISO15693_CMD_RESET_TO_READY) { + ResponseByteCount = EM4233_Reset_To_Ready (FrameBuf, FrameBytes); } else if (*FrameInfo.Command == EM4233_CMD_LOGIN) { ResponseByteCount = EM4233_Login(FrameBuf, FrameBytes, Uid); + } else if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) { + /* This is just a placeholder to avoid falling in the following else */ + } else { - FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; - FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP; - ResponseByteCount = 2; + /* EM4233 does not respond to non existing commands */ + // FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR; + // FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP; + // ResponseByteCount = 2; } } else if (State == 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; - FrameInfo.Selected = false; + ResponseByteCount = EM4233_Reset_To_Ready (FrameBuf, FrameBytes); } } diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.c b/Firmware/Chameleon-Mini/Application/ISO15693-A.c index 9224606..a206bc8 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.c +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.c @@ -65,7 +65,7 @@ bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize) * * Authors: ceres-c & MrMoDDoM */ -bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid, uint8_t MyAFI) +bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t IsSelected, uint8_t* MyUid, uint8_t MyAFI) { if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE)) /* malformed frame */ @@ -96,8 +96,7 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* return false; FrameStruct -> Parameters += 0x01; } - else if ( ((*FrameStruct -> Command) == ISO15693_CMD_INVENTORY) && (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_AFI)) { - /* or if it is Inventory with AFI flag set */ + else if ( ((*FrameStruct -> Command) == ISO15693_CMD_INVENTORY) && (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_AFI)) { /* or if it is Inventory with AFI flag set */ /* then between CMD and UID is placed another byte which is requested AFI, but we don't need it */ if (FrameBuf[ISO15693_REQ_ADDR_PARAM] != MyAFI) /* if requested AFI is different from our current one, then don't respond */ @@ -107,11 +106,12 @@ bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct -> ParamLen = FrameBuf + (FrameBytes - ISO15693_CRC16_SIZE) - (FrameStruct -> Parameters); - uint8_t *uid = (FrameStruct -> Parameters) - ISO15693_GENERIC_UID_SIZE; - - if (FrameStruct -> Addressed && !ISO15693CompareUid( uid, MyUid)) { + if (FrameStruct -> Addressed && !ISO15693CompareUid(&FrameBuf[ISO15693_REQ_ADDR_PARAM], MyUid)) { /* addressed request but we're not the addressee */ return false; + } else if (FrameStruct -> Selected && !IsSelected) { + /* selected request but we're not in selected state */ + return false; } else { return true; } diff --git a/Firmware/Chameleon-Mini/Application/ISO15693-A.h b/Firmware/Chameleon-Mini/Application/ISO15693-A.h index f99c6b6..42b1655 100644 --- a/Firmware/Chameleon-Mini/Application/ISO15693-A.h +++ b/Firmware/Chameleon-Mini/Application/ISO15693-A.h @@ -88,7 +88,7 @@ typedef struct { void ISO15693AppendCRC(uint8_t* FrameBuf, uint16_t FrameBufSize); bool ISO15693CheckCRC(void* FrameBuf, uint16_t FrameBufSize); -bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid, uint8_t MyAFI); +bool ISO15693PrepareFrame(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t IsSelected, uint8_t* MyUid, uint8_t MyAFI); bool ISO15693AntiColl(uint8_t* FrameBuf, uint16_t FrameBytes, CurrentFrame* FrameStruct, uint8_t* MyUid); INLINE diff --git a/Firmware/Chameleon-Mini/Application/Sl2s2002.h b/Firmware/Chameleon-Mini/Application/Sl2s2002.h index be37eb2..9f58761 100644 --- a/Firmware/Chameleon-Mini/Application/Sl2s2002.h +++ b/Firmware/Chameleon-Mini/Application/Sl2s2002.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 Sl2s2002AppInit(void); void Sl2s2002AppReset(void); void Sl2s2002AppTask(void); diff --git a/Firmware/Chameleon-Mini/Application/TITagitstandard.c b/Firmware/Chameleon-Mini/Application/TITagitstandard.c index 3e1cc5d..3a34177 100644 --- a/Firmware/Chameleon-Mini/Application/TITagitstandard.c +++ b/Firmware/Chameleon-Mini/Application/TITagitstandard.c @@ -67,7 +67,7 @@ uint16_t TITagitstandardAppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) uint8_t Uid[ActiveConfiguration.UidSize]; TITagitstandardGetUid(Uid); - if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, Uid, MyAFI)) + if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, State == STATE_SELECTED, Uid, MyAFI)) return ISO15693_APP_NO_RESPONSE; switch(State) { From 3c775c06cce7b6e7c3798cbe11b18a8b72a1480c Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Fri, 28 Dec 2018 17:10:02 +0100 Subject: [PATCH 31/31] Stupid me introduced a bug in Write_Single --- Firmware/Chameleon-Mini/Application/EM4233.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/EM4233.c b/Firmware/Chameleon-Mini/Application/EM4233.c index 8fc69c7..a2379a8 100644 --- a/Firmware/Chameleon-Mini/Application/EM4233.c +++ b/Firmware/Chameleon-Mini/Application/EM4233.c @@ -95,7 +95,7 @@ uint16_t EM4233_Write_Single(uint8_t* FrameBuf, uint16_t FrameBytes) { uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE; uint8_t BlockAddress = *FrameInfo.Parameters; - uint8_t* Dataptr = BlockAddress + 0x01; /* Data to write begins on 2nd byte of the frame received by the reader */ + uint8_t* Dataptr = FrameInfo.Parameters + 0x01; /* Data to write begins on 2nd byte of the frame received by the reader */ uint8_t LockStatus = 0; if (FrameInfo.ParamLen != 5)