Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add implementation of TI Tagit Plus vicinity card #70

Open
wants to merge 2 commits into
base: proxgrind
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Firmware/Chameleon-Mini/Application/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "Vicinity.h"
#include "Sl2s2002.h"
#include "TITagitstandard.h"
#include "TITagitplus.h"
#include "Sniff14443A.h"
#include "EM4233.h"
#include "NTAG215.h"
Expand Down
257 changes: 257 additions & 0 deletions Firmware/Chameleon-Mini/Application/TITagitplus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
/*
* TITagitplus.c
*
* Created 20210409
* Author: leandre84
* Based on TI Tag-it Standard implementation, read multiple inspired by Sl2s2002 implementation
*/

#ifdef CONFIG_TITAGITPLUS_SUPPORT

#include "ISO15693-A.h"
#include "TITagitplus.h"

static enum {
STATE_READY,
STATE_SELECTED,
STATE_QUIET
} State;

uint64_t UserLockBits_Mask_Tagitplus = 0; /* Holds lock state of blocks 1-64 */
uint64_t FactoryLockBits_Mask_Tagitplus = 0; /* Holds lock state of blocks 1-64 */

void TITagitplusAppInit(void) {
State = STATE_READY;

FrameInfo.Flags = NULL;
FrameInfo.Command = NULL;
FrameInfo.Parameters = NULL;
FrameInfo.ParamLen = 0;
FrameInfo.Addressed = false;
FrameInfo.Selected = false;

MemoryReadBlock(&MyAFI, TITAGIT_PLUS_MEM_AFI_ADDRESS, 1);
TITagitplusGetUid(Uid);
}

void TITagitplusAppReset(void) {
State = STATE_READY;

FrameInfo.Flags = NULL;
FrameInfo.Command = NULL;
FrameInfo.Parameters = NULL;
FrameInfo.ParamLen = 0;
FrameInfo.Addressed = false;
FrameInfo.Selected = false;

MemoryReadBlock(&MyAFI, TITAGIT_PLUS_MEM_AFI_ADDRESS, 1);
TITagitplusGetUid(Uid);
}


void TITagitplusAppTask(void) {

}

void TITagitplusAppTick(void) {

}

uint16_t TITagitplusAppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
ResponseByteCount = ISO15693_APP_NO_RESPONSE;

if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE))
/* malformed frame */
return ResponseByteCount;

if (!ISO15693PrepareFrame(FrameBuf, FrameBytes, &FrameInfo, State == STATE_SELECTED, Uid, MyAFI))
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 || *FrameInfo.Command == ISO15693_CMD_READ_MULTIPLE) {
uint8_t *FramePtr; /* holds the address where block's data will be put */
uint8_t PageAddress = *FrameInfo.Parameters;
uint8_t PageAddressCount = 1;

if (*FrameInfo.Command == ISO15693_CMD_READ_SINGLE) {
if (FrameInfo.ParamLen != 1) {
break; /* malformed: not enough or too much data */
}
} else {
if (FrameInfo.ParamLen != 2) {
break; /* malformed: not enough or too much data */
}
PageAddressCount = *(FrameInfo.Parameters+1)+1;
}

if (PageAddress >= TITAGIT_PLUS_NUMBER_OF_USER_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;
}

/* position to one after flag bit and keep its value for now as we still need it to determine if option bit is set */
FramePtr = FrameBuf + 1;
ResponseByteCount = 1;

for (int i = 0; i < PageAddressCount; i++) {
/* write additional bit with locking information */
if (FrameBuf[ISO15693_ADDR_FLAGS] & ISO15693_REQ_FLAG_OPTION) { /* request with option flag set - handle extra byte in response*/
if (FactoryLockBits_Mask_Tagitplus & (1 << PageAddress)) { /* tests if the n-th bit of the factory bitmask if set to 1 */
*(FramePtr) = 0x02; /* return bit 1 set as 1 (factory locked) */
} else if (UserLockBits_Mask_Tagitplus & (1 << PageAddress)) { /* tests if the n-th bit of the user bitmask if set to 1 */
*(FramePtr) = 0x01; /* return bit 0 set as 1 (user locked) */
} else {
*(FramePtr) = 0x00; /* return lock status 00 (unlocked) */
}

FramePtr++;
ResponseByteCount++;
}

/* write data page, increment response bytes and prepare pointer etc for next iteration */
MemoryReadBlock(FramePtr, PageAddress * TITAGIT_PLUS_BYTES_PER_PAGE, TITAGIT_PLUS_BYTES_PER_PAGE);
FramePtr += TITAGIT_PLUS_BYTES_PER_PAGE;
ResponseByteCount += TITAGIT_PLUS_BYTES_PER_PAGE;
PageAddress++;
}

FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR; /* flags */

} 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_PLUS_NUMBER_OF_USER_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 = FrameInfo.Parameters + 1;

if (FactoryLockBits_Mask_Tagitplus & (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_Tagitplus & (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_PLUS_BYTES_PER_PAGE, TITAGIT_PLUS_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_PLUS_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_Tagitplus & (1 << PageAddress)) || (UserLockBits_Mask_Tagitplus & (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_Tagitplus |= (1 << PageAddress); /* */
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_NO_ERROR;
ResponseByteCount = 1;
}

} else if (*FrameInfo.Command == ISO15693_CMD_GET_SYS_INFO) {
FrameBuf[0] = 0; /* Flags */
FrameBuf[1] = 0x0F; /* InfoFlags */
ISO15693CopyUid(&FrameBuf[2], Uid);
FrameBuf[10] = 0x00;
FrameBuf[11] = 0x00;
FrameBuf[12] = 0x3F;
FrameBuf[13] = 0x03;
FrameBuf[14] = 0x8B;
ResponseByteCount = 15;
} 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;
}

return ResponseByteCount;
}

void TITagitplusGetUid(ConfigurationUidType Uid) {
MemoryReadBlock(&Uid[0], TITAGIT_PLUS_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);

// Reverse UID after reading it
TITagitplusFlipUid(Uid);
}

void TITagitplusSetUid(ConfigurationUidType NewUid) {
memcpy(Uid, NewUid, ActiveConfiguration.UidSize); // Update the local variable
// Reverse UID before writing it
TITagitplusFlipUid(Uid);

MemoryWriteBlock(Uid, TITAGIT_PLUS_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}

void TITagitplusFlipUid(ConfigurationUidType Uid) {
uint8_t tmp, *tail;
tail = Uid + ActiveConfiguration.UidSize - 1;
while (Uid < tail) {
tmp = *Uid;
*Uid++ = *tail;
*tail-- = tmp;
}
}

#endif
33 changes: 33 additions & 0 deletions Firmware/Chameleon-Mini/Application/TITagitplus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* TITagitplus.h
*
* Created 20210409
* Author: leandre84
* Based on TI Tag-it Standard implementation, read multiple inspired by Sl2s2002 implementation
*/

#ifndef TITAGITPLUS_H_
#define TITAGITPLUS_H_

#include "Application.h"
#include "ISO15693-A.h"

#define TITAGIT_PLUS_UID_SIZE ISO15693_GENERIC_UID_SIZE //ISO15693_UID_SIZE
#define TITAGIT_PLUS_MEM_SIZE 0x110 //TAG-IT PLUS MAX MEM SIZE
#define TITAGIT_PLUS_BYTES_PER_PAGE 4
#define TITAGIT_PLUS_NUMBER_OF_SECTORS ( TITAGIT_PLUS_MEM_SIZE / TITAGIT_PLUS_BYTES_PER_PAGE )
#define TITAGIT_PLUS_NUMBER_OF_USER_SECTORS ( TITAGIT_PLUS_NUMBER_OF_SECTORS - 4 )
#define TITAGIT_PLUS_MEM_UID_ADDRESS 0x100 // UID byte address (two pages)
#define TITAGIT_PLUS_MEM_DSFID_ADDRESS 0x108 // DSFID byte address
#define TITAGIT_PLUS_MEM_AFI_ADDRESS 0x10C // AFI byte address

void TITagitplusAppInit(void);
void TITagitplusAppReset(void);
void TITagitplusAppTask(void);
void TITagitplusAppTick(void);
uint16_t TITagitplusAppProcess(uint8_t *FrameBuf, uint16_t FrameBytes);
void TITagitplusGetUid(ConfigurationUidType Uid);
void TITagitplusSetUid(ConfigurationUidType Uid);
void TITagitplusFlipUid(ConfigurationUidType Uid);

#endif /* TITAGITPLUS_H_ */
21 changes: 21 additions & 0 deletions Firmware/Chameleon-Mini/Configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ static const MapEntryType PROGMEM ConfigurationMap[] = {
#ifdef CONFIG_TITAGITSTANDARD_SUPPORT
{ .Id = CONFIG_TITAGITSTANDARD, .Text = "TITAGITSTANDARD" },
#endif
#ifdef CONFIG_TITAGITPLUS_SUPPORT
{ .Id = CONFIG_TITAGITPLUS, .Text = "TITAGITPLUS" },
#endif
#ifdef CONFIG_EM4233_SUPPORT
{ .Id = CONFIG_EM4233, .Text = "EM4233" },
#endif
Expand Down Expand Up @@ -463,6 +466,24 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = {
.TagFamily = TAG_FAMILY_ISO15693
},
#endif
#ifdef CONFIG_TITAGITPLUS_SUPPORT
[CONFIG_TITAGITPLUS] = {
.CodecInitFunc = ISO15693CodecInit,
.CodecDeInitFunc = ISO15693CodecDeInit,
.CodecTaskFunc = ISO15693CodecTask,
.ApplicationInitFunc = TITagitplusAppInit,
.ApplicationResetFunc = TITagitplusAppReset,
.ApplicationTaskFunc = TITagitplusAppTask,
.ApplicationTickFunc = TITagitplusAppTick,
.ApplicationProcessFunc = TITagitplusAppProcess,
.ApplicationGetUidFunc = TITagitplusGetUid,
.ApplicationSetUidFunc = TITagitplusSetUid,
.UidSize = TITAGIT_PLUS_UID_SIZE,
.MemorySize = TITAGIT_PLUS_MEM_SIZE,
.ReadOnly = false,
.TagFamily = TAG_FAMILY_ISO15693
},
#endif
#ifdef CONFIG_EM4233_SUPPORT
[CONFIG_EM4233] = {
.CodecInitFunc = ISO15693CodecInit,
Expand Down
3 changes: 3 additions & 0 deletions Firmware/Chameleon-Mini/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ typedef enum {
#ifdef CONFIG_TITAGITSTANDARD_SUPPORT
CONFIG_TITAGITSTANDARD,
#endif
#ifdef CONFIG_TITAGITPLUS_SUPPORT
CONFIG_TITAGITPLUS,
#endif
#ifdef CONFIG_EM4233_SUPPORT
CONFIG_EM4233,
#endif
Expand Down
5 changes: 3 additions & 2 deletions Firmware/Chameleon-Mini/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ SETTINGS += -DCONFIG_ISO14443A_READER_SUPPORT
SETTINGS += -DCONFIG_NTAG215_SUPPORT
SETTINGS += -DCONFIG_VICINITY_SUPPORT
SETTINGS += -DCONFIG_SL2S2002_SUPPORT
SETTINGS += -DCONFIG_TITAGITSTANDARD_SUPPORT
# SETTINGS += -DCONFIG_TITAGITSTANDARD_SUPPORT
SETTINGS += -DCONFIG_TITAGITPLUS_SUPPORT
# SETTINGS += -DCONFIG_ISO15693_SNIFF_SUPPORT
SETTINGS += -DCONFIG_EM4233_SUPPORT

Expand Down Expand Up @@ -114,7 +115,7 @@ SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Termina
SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S
SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c Application/CryptoTDEA.S
SRC += Codec/ISO15693.c
SRC += Application/Vicinity.c Application/Sl2s2002.c Application/TITagitstandard.c Application/ISO15693-A.c Application/EM4233.c Application/NTAG215.c
SRC += Application/Vicinity.c Application/Sl2s2002.c Application/TITagitstandard.c Application/TITagitplus.c Application/ISO15693-A.c Application/EM4233.c Application/NTAG215.c
SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH = ../LUFA
CC_FLAGS = -flto -DUSE_LUFA_CONFIG_HEADER -DFLASH_DATA_ADDR=$(FLASH_DATA_ADDR) -DFLASH_DATA_SIZE=$(FLASH_DATA_SIZE) -DSPM_HELPER_ADDR=$(SPM_HELPER_ADDR) -DBUILD_DATE=$(BUILD_DATE) -DCOMMIT_ID=\"$(COMMIT_ID)\" $(SETTINGS)
Expand Down