From d091e2291b9095eddc33f10569c4ca62abafaada Mon Sep 17 00:00:00 2001 From: Federico Cerutti Date: Mon, 3 Dec 2018 23:07:50 +0100 Subject: [PATCH] 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)