mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-05-12 11:20:37 -07:00
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.
165 lines
6.2 KiB
C
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);
|
|
}
|
|
|
|
|
|
|