Files
Federico Cerutti ebd6ab5842 Fixed timing issues with Read Multiple Blocks
ISO15693 CRC calculation is slow and it delayed too much transmission of long
frames. Some readers marked transmission as unsuccesfull and ignored data.
Moving CRC calculation inside the codec allows to start modulating the field
while the CRC is not yet ready but, by the time it has to be trasmitted,
calculation will be done.
This fixes https://github.com/emsec/ChameleonMini/issues/262

In EM4233, there still are issues with Read Multiple command when block
locking status is requested for more than 0x1F blocks

Implemented a check in ISO15693 codec to avoid out of bound CRC writes.
2020-09-10 16:05:35 +02:00

165 lines
6.2 KiB
C

/*
* ISO15693.c
*
* Created on: 01-03-2017
* Author: Phillip Nash
*
* TODO:
* - ISO15693AddressedLegacy should be replaced with ISO15693Addressed and appropriate check
* should be performed (see TITagitstandard.c) - ceres-c
*/
#include "Sl2s2002.h"
#include "../Codec/ISO15693.h"
#include "../Memory.h"
#include "Crypto1.h"
#include "../Random.h"
#include "ISO15693-A.h"
#define BYTES_PER_PAGE 4
#define MEM_UID_ADDRESS 0x00
static enum {
STATE_READY,
STATE_SELECTED,
STATE_QUIET
} State;
void Sl2s2002AppInit(void) {
State = STATE_READY;
}
void Sl2s2002AppReset(void) {
State = STATE_READY;
}
void Sl2s2002AppTask(void) {
}
void Sl2s2002AppTick(void) {
}
uint16_t Sl2s2002AppProcess(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[8];
MemoryReadBlock(Uid, MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
switch (State) {
case STATE_READY:
if (Command == ISO15693_CMD_INVENTORY) {
FrameBuf[0] = 0x00; /* Flags */
FrameBuf[1] = 0x00; /* DSFID */
ISO15693CopyUid(&FrameBuf[2], Uid);
ResponseByteCount = 10;
} else if (Command == ISO15693_CMD_STAY_QUIET) {
if (ISO15693AddressedLegacy(FrameBuf, Uid)) {
State = STATE_QUIET;
}
} else if (Command == ISO15693_CMD_GET_SYS_INFO) {
if (ISO15693AddressedLegacy(FrameBuf, Uid)) {
FrameBuf[0] = 0; /* Flags */
FrameBuf[1] = 0x0F; /* InfoFlags */
ISO15693CopyUid(&FrameBuf[2], Uid);
FrameBuf[10] = 0x00;
FrameBuf[11] = 0xC2;
FrameBuf[12] = 0x03;
FrameBuf[13] = 0x03;
FrameBuf[14] = 0x01;
ResponseByteCount = 15;
}
} else if (Command == ISO15693_CMD_READ_SINGLE) {
if (ISO15693AddressedLegacy(FrameBuf, Uid)) {
uint8_t PageAddress = FrameBuf[10];
if (FrameBuf[0] & ISO15693_REQ_FLAG_OPTION) {
FrameBuf[0] = 0x00; /* Flags */
FrameBuf[1] = 0x00; /* security dummy to 0 */
MemoryReadBlock(FrameBuf + 2, PageAddress * BYTES_PER_PAGE, BYTES_PER_PAGE);
ResponseByteCount = 6;
} else {
FrameBuf[0] = 0x00; /* Flags */
MemoryReadBlock(FrameBuf + 1, PageAddress * BYTES_PER_PAGE, BYTES_PER_PAGE);
ResponseByteCount = 5;
}
}
} else if (Command == ISO15693_CMD_READ_MULTIPLE) {
if (ISO15693AddressedLegacy(FrameBuf, Uid)) {
uint16_t PageAddress = FrameBuf[10];
uint16_t PageAddressCount = FrameBuf[11] + 1;
uint8_t *FrameBufPtr = FrameBuf + 1;
if (FrameBuf[0] & ISO15693_REQ_FLAG_OPTION) {
uint8_t count;
for (count = 0; count < PageAddressCount; count++) {
*FrameBufPtr++ = 0; // block security status = unlocked
MemoryReadBlock(FrameBufPtr, PageAddress * BYTES_PER_PAGE, BYTES_PER_PAGE);
FrameBufPtr += BYTES_PER_PAGE;
PageAddress += 1;
}
ResponseByteCount = 1 + (BYTES_PER_PAGE + 1) * PageAddressCount;
} else {
MemoryReadBlock(FrameBufPtr, PageAddress * BYTES_PER_PAGE, BYTES_PER_PAGE * PageAddressCount);
ResponseByteCount = 1 + BYTES_PER_PAGE * PageAddressCount;
}
FrameBuf[0] = 0; /* Flags */
}
} else if (Command == ISO15693_CMD_GET_BLOCK_SEC) { // TODO read out block security status
if (ISO15693AddressedLegacy(FrameBuf, Uid)) {
//uint8_t PageAddressStart = FrameBuf[10];
uint8_t PageAddressCount = FrameBuf[11] + 1;
FrameBuf[0] = 0; /* Flags */
for (uint8_t i = 0; i < PageAddressCount; i++) {
FrameBuf[i] = 0x00;
}
ResponseByteCount = 1 + PageAddressCount;
}
}
break;
case STATE_SELECTED:
break;
case STATE_QUIET:
if (Command == ISO15693_CMD_RESET_TO_READY) {
if (ISO15693AddressedLegacy(FrameBuf, Uid)) {
FrameBuf[0] = 0;
ResponseByteCount = 1;
State = STATE_READY;
}
}
break;
default:
break;
}
return ResponseByteCount;
} else { // Invalid CRC
return ISO15693_APP_NO_RESPONSE;
}
} else { // Min frame size not met
return ISO15693_APP_NO_RESPONSE;
}
}
void Sl2s2002GetUid(ConfigurationUidType Uid) {
MemoryReadBlock(&Uid[0], MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void Sl2s2002SetUid(ConfigurationUidType Uid) {
MemoryWriteBlock(Uid, MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}