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

Port ISO15693 codec and applications updates by ceres-c to the right branch #40

Merged
merged 23 commits into from
Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0bca278
Modified Reader14443A to only use configured card types
epozzobon Nov 7, 2019
31b0b63
CLONE_MFU: command and button action
hsanjuan Nov 20, 2019
0290bb7
Merge pull request #239 from hsanjuan/feat/mfu_clone
fptrs Nov 25, 2019
c857696
make style
fptrs Nov 25, 2019
dabef1b
update LATEST
fptrs Nov 25, 2019
e83cdcd
Docs: add documentation for CLONE_MFU button and command actions
hsanjuan Nov 25, 2019
3bb7fc0
Merge pull request #241 from hsanjuan/docs/clone_mfu
fptrs Dec 6, 2019
7d20428
Merge branch 'master' of git://github.com/epozzobon/ChameleonMini int…
fptrs Dec 6, 2019
a1ea90a
Merge branch 'epozzobon-master'
fptrs Dec 6, 2019
1c8b05d
Merge branch 'master' of https://github.com/emsec/ChameleonMini
fptrs Dec 6, 2019
1a41b8a
fix merge issue
fptrs Dec 6, 2019
247a0ff
Faster ISR sharing in ASM
ceres-c Dec 8, 2019
868d8b6
Merge pull request #243 from ceres-c/master
fptrs Dec 11, 2019
d81c339
update LATEST
fptrs Dec 11, 2019
22023b7
add macro for shared isr call
fptrs Dec 13, 2019
86be22d
Shared a function I forgot about, documented sharing practises
ceres-c Aug 26, 2020
c82572d
Updated code to build with GCC 10 - Updated ISR Sharing
ceres-c Aug 26, 2020
8494044
Merge fixes for GCC 10
ceres-c Aug 28, 2020
4135ca1
ISO15693 Codec minor fixes
ceres-c Sep 3, 2020
c6b9366
Improved ISO15693 applications performance
ceres-c Sep 3, 2020
d439424
Fixed hasty copy-paste
ceres-c Sep 9, 2020
ebd6ab5
Fixed timing issues with Read Multiple Blocks
ceres-c Sep 10, 2020
c5b0798
Merge remote-tracking branch 'ceres/rrg-iso15693-codec-upd' into prox…
aveao Sep 15, 2020
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 Doc/DoxygenPages/Buttons.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* `RECALL_MEM` | Recalls a setting from the permanent Flash memory. Equivalent to the `RECALL` command.
* `TOGGLE_FIELD` | Activates the reader field if it was deactivated, deactivates the reader field if it was activated.
* `STORE_LOG` | Writes the current log from SRAM to FRAM and clears the SRAM log. Equivalent to the `STORE_LOG` command.
* `CLONE_MFU` | Triggers the clone of a Mifare Ultralight card in range of the antenna to the selected slot and configures it to emulate it. Equivalent to the `CLONE_MFU` command.
*
* Note the UID commands have no effect when the slot is configured as reader.
*/
1 change: 1 addition & 0 deletions Doc/DoxygenPages/CommandLine.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
* `SEND_RAW <BYTEVALUE>`| Does NOT add parity bits, sends the given byte string <BYTEVALUE> and returns the cards answer
* `GETUID` | Obtains the UID of a card that is in the range of the antenna and returns it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `DUMP_MFU` | Reads the whole content of a Mifare Ultralight card that is in the range of the antenna and returns it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `CLONE_MFU` | Clones a Mifare Ultralight card that is in the range of the antenna to the current slot, which is then accordingly configured to emulate it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `IDENTIFY` | Identifies the type of a card in the range of the antenna and returns it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `THRESHOLD=?` | Returns the possible number range for the reader threshold.
* `THRESHOLD=<NUMBER>` | Globally sets the reader threshold. The <NUMBER> influences the reader function and range. Setting a wrong value may result in malfunctioning of the reader. DEFAULT: 400
Expand Down
116 changes: 62 additions & 54 deletions Firmware/Chameleon-Mini/Application/EM4233.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ static enum {
} State;

bool loggedIn;
uint8_t MyAFI; /* This variable holds current tag's AFI (is used in inventory) */

CurrentFrame FrameInfo;

void EM4233AppInit(void) {
State = STATE_READY;
Expand All @@ -38,7 +35,7 @@ void EM4233AppInit(void) {
FrameInfo.Selected = false;
loggedIn = false;
MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1);

MemoryReadBlock(&Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}

void EM4233AppReset(void) {
Expand All @@ -51,6 +48,8 @@ void EM4233AppReset(void) {
FrameInfo.Addressed = false;
FrameInfo.Selected = false;
loggedIn = false;
MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1);
MemoryReadBlock(&Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}

void EM4233AppTask(void) {
Expand All @@ -62,7 +61,7 @@ void EM4233AppTick(void) {
}

uint16_t EM4233_Lock_Block(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t BlockAddress = *FrameInfo.Parameters;
uint8_t LockStatus = 0;

Expand Down Expand Up @@ -92,7 +91,7 @@ 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;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t BlockAddress = *FrameInfo.Parameters;
uint8_t *Dataptr = FrameInfo.Parameters + 0x01; /* Data to write begins on 2nd byte of the frame received by the reader */
uint8_t LockStatus = 0;
Expand Down Expand Up @@ -127,7 +126,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;
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 LockStatus = 0;
Expand All @@ -138,7 +137,7 @@ uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
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 */
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC;
ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */
}
return ResponseByteCount; /* If not addressed real tag does not respond */
Expand Down Expand Up @@ -168,7 +167,7 @@ uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
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 0x08 blocks if we get 0x07 in request */
Expand All @@ -179,7 +178,7 @@ uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
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 */
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC;
ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */
}
return ResponseByteCount; /* If not addressed real tag does not respond */
Expand Down Expand Up @@ -224,7 +223,7 @@ uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Write_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t AFI = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;

Expand All @@ -251,7 +250,7 @@ uint16_t EM4233_Write_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Lock_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t LockStatus = 0;

if (FrameInfo.ParamLen != 0)
Expand All @@ -278,7 +277,7 @@ uint16_t EM4233_Lock_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Write_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t DSFID = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;

Expand All @@ -304,7 +303,7 @@ uint16_t EM4233_Write_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Lock_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t LockStatus = 0;

if (FrameInfo.ParamLen != 0)
Expand All @@ -331,7 +330,7 @@ uint16_t EM4233_Lock_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */

if (FrameInfo.ParamLen != 0)
Expand All @@ -354,8 +353,6 @@ uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
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 */
Expand Down Expand Up @@ -398,7 +395,7 @@ uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
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;
Expand Down Expand Up @@ -427,7 +424,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;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
/* I've no idea how this request could generate errors ._.
if ( ) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
Expand Down Expand Up @@ -463,7 +460,7 @@ uint16_t EM4233_Select(uint8_t *FrameBuf, uint16_t FrameBytes, uint8_t *Uid) {
}

uint16_t EM4233_Reset_To_Ready(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
/* I've no idea how this request could generate errors ._.
if ( ) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
Expand All @@ -487,7 +484,7 @@ uint16_t EM4233_Reset_To_Ready(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Login(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Password[4] = { 0 };

if (FrameInfo.ParamLen != 4 || !FrameInfo.Addressed || !(FrameInfo.Selected && State == STATE_SELECTED))
Expand Down Expand Up @@ -523,7 +520,7 @@ uint16_t EM4233_Login(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Auth1(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
// uint8_t KeyNo = *FrameInfo.Parameters; /* Right now this parameter is unused, but it will be useful */

if (FrameInfo.ParamLen != 1) /* Malformed: not enough or too much data */
Expand All @@ -548,7 +545,7 @@ uint16_t EM4233_Auth1(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233_Auth2(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
// uint8_t A2 = FrameInfo.Parameters;
// uint8_t f = FrameInfo.Parameters + 0x08;
// uint8_t g[3] = { 0 }; /* Names according to EM Marin definitions */
Expand All @@ -566,9 +563,7 @@ uint16_t EM4233_Auth2(uint8_t *FrameBuf, uint16_t FrameBytes) {
}

uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Uid[ActiveConfiguration.UidSize];
EM4233GetUid(Uid);
ResponseByteCount = ISO15693_APP_NO_RESPONSE;

if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE))
/* malformed frame */
Expand All @@ -585,8 +580,8 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
return ISO15693_APP_NO_RESPONSE;

if (State == STATE_READY || State == STATE_SELECTED) {

if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) {
switch (*FrameInfo.Command) {
case ISO15693_CMD_INVENTORY:
if (FrameInfo.ParamLen == 0)
return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */

Expand All @@ -596,79 +591,92 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid);
ResponseByteCount += 10;
}
break;

} else if ((*FrameInfo.Command == ISO15693_CMD_STAY_QUIET) && FrameInfo.Addressed) {
State = STATE_QUIET;
case ISO15693_CMD_STAY_QUIET:
if (FrameInfo.Addressed)
State = STATE_QUIET;
break;

} else if (*FrameInfo.Command == ISO15693_CMD_READ_SINGLE) {
case ISO15693_CMD_READ_SINGLE:
ResponseByteCount = EM4233_Read_Single(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_SINGLE) {
case ISO15693_CMD_WRITE_SINGLE:
ResponseByteCount = EM4233_Write_Single(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) {
case ISO15693_CMD_LOCK_BLOCK:
ResponseByteCount = EM4233_Lock_Block(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_READ_MULTIPLE) {
case ISO15693_CMD_READ_MULTIPLE:
ResponseByteCount = EM4233_Read_Multiple(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_AFI) {
case ISO15693_CMD_WRITE_AFI:
ResponseByteCount = EM4233_Write_AFI(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_AFI) {
case ISO15693_CMD_LOCK_AFI:
ResponseByteCount = EM4233_Lock_AFI(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_DSFID) {
case ISO15693_CMD_WRITE_DSFID:
ResponseByteCount = EM4233_Write_DSFID(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_DSFID) {
case ISO15693_CMD_LOCK_DSFID:
ResponseByteCount = EM4233_Lock_DSFID(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_GET_SYS_INFO) {
case ISO15693_CMD_GET_SYS_INFO:
ResponseByteCount = EM4233_Get_SysInfo(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_GET_BLOCK_SEC) {
case ISO15693_CMD_GET_BLOCK_SEC:
ResponseByteCount = EM4233_Get_Multi_Block_Sec_Stat(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) {
case ISO15693_CMD_RESET_TO_READY:
ResponseByteCount = EM4233_Reset_To_Ready(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == EM4233_CMD_LOGIN) {
case EM4233_CMD_LOGIN:
ResponseByteCount = EM4233_Login(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == EM4233_CMD_AUTH1) {
case EM4233_CMD_AUTH1:
ResponseByteCount = EM4233_Auth1(FrameBuf, FrameBytes);
break;

} else if (*FrameInfo.Command == EM4233_CMD_AUTH2) {
case EM4233_CMD_AUTH2:
ResponseByteCount = EM4233_Auth2(FrameBuf, FrameBytes);
break;

} else {
default:
if (FrameInfo.Addressed) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP;
ResponseByteCount = 2;
} /* EM4233 respond with error flag only to addressed commands */
}
break;
}

} else if (State == STATE_QUIET) {
if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) {
ResponseByteCount = EM4233_Reset_To_Ready(FrameBuf, FrameBytes);
}
}

if (ResponseByteCount > 0) {
/* There is data to send. 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);
void EM4233SetUid(ConfigurationUidType NewUid) {
memcpy(Uid, NewUid, ActiveConfiguration.UidSize);
MemoryWriteBlock(NewUid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
5 changes: 5 additions & 0 deletions Firmware/Chameleon-Mini/Application/ISO15693-A.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
#include "../Common.h"
#include <util/crc16.h>

CurrentFrame FrameInfo;
uint8_t Uid[ISO15693_GENERIC_UID_SIZE];
uint8_t MyAFI;
uint16_t ResponseByteCount;

//Refer to ISO/IEC 15693-3:2001 page 41
uint16_t calculateCRC(void *FrameBuf, uint16_t FrameBufSize) {
uint16_t reg = ISO15693_CRC16_PRESET;
Expand Down
4 changes: 4 additions & 0 deletions Firmware/Chameleon-Mini/Application/ISO15693-A.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ typedef struct {
bool Addressed;
bool Selected;
} CurrentFrame;
extern CurrentFrame FrameInfo; /* Holds current frame information */
extern uint8_t Uid[];
extern uint8_t MyAFI; /* Holds current tag's AFI, used during inventory */
extern uint16_t ResponseByteCount; /* Length of response, used when building response frames */

void ISO15693AppendCRC(uint8_t *FrameBuf, uint16_t FrameBufSize);
bool ISO15693CheckCRC(void *FrameBuf, uint16_t FrameBufSize);
Expand Down
Loading