From 5f6c35d7a690c7c9ceb83a412ccb7f3f67627362 Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Fri, 28 Dec 2018 00:28:22 +0100 Subject: [PATCH] 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);