Files
2016-10-24 13:55:40 +02:00

147 lines
4.5 KiB
C

/*
* ISO14443-2A.h
*
* Created on: 19.03.2013
* Author: skuser
*/
#ifndef ISO14443_3A_H_
#define ISO14443_3A_H_
#include "../Common.h"
#include <string.h>
#define ISO14443A_UID_SIZE_SINGLE 4 /* bytes */
#define ISO14443A_UID_SIZE_DOUBLE 7
#define ISO14443A_UID_SIZE_TRIPLE 10
#define ISO14443A_CMD_REQA 0x26
#define ISO14443A_CMD_WUPA 0x52
#define ISO14443A_CMD_SELECT_CL1 0x93
#define ISO14443A_CMD_SELECT_CL2 0x95
#define ISO14443A_CMD_SELECT_CL3 0x97
#define ISO14443A_CMD_HLTA 0x50
#define ISO14443A_NVB_AC_START 0x20
#define ISO14443A_NVB_AC_END 0x70
#define ISO14443A_CL_UID_OFFSET 0
#define ISO14443A_CL_UID_SIZE 4
#define ISO14443A_CL_BCC_OFFSET 4
#define ISO14443A_CL_BCC_SIZE 1 /* Byte */
#define ISO14443A_CL_FRAME_SIZE ((ISO14443A_CL_UID_SIZE + ISO14443A_CL_BCC_SIZE) * 8) /* UID[N...N+3] || BCCN */
#define ISO14443A_SAK_INCOMPLETE 0x04
#define ISO14443A_SAK_COMPLETE_COMPLIANT 0x20
#define ISO14443A_SAK_COMPLETE_NOT_COMPLIANT 0x00
#define ISO14443A_ATQA_FRAME_SIZE (2 * 8) /* Bit */
#define ISO14443A_SAK_FRAME_SIZE (3 * 8) /* Bit */
#define ISO14443A_UID0_RANDOM 0x08
#define ISO14443A_UID0_CT 0x88
#define ISO14443A_CRCA_SIZE 2
#define ISO14443A_CALC_BCC(ByteBuffer) \
( ByteBuffer[0] ^ ByteBuffer[1] ^ ByteBuffer[2] ^ ByteBuffer[3] )
void ISO14443AAppendCRCA(void* Buffer, uint16_t ByteCount);
bool ISO14443ACheckCRCA(const void* Buffer, uint16_t ByteCount);
INLINE bool ISO14443ASelect(void* Buffer, uint16_t* BitCount, uint8_t* UidCL, uint8_t SAKValue);
INLINE bool ISO14443AWakeUp(void* Buffer, uint16_t* BitCount, uint16_t ATQAValue, bool FromHalt);
INLINE
bool ISO14443ASelect(void* Buffer, uint16_t* BitCount, uint8_t* UidCL, uint8_t SAKValue)
{
uint8_t* DataPtr = (uint8_t*) Buffer;
uint8_t NVB = DataPtr[1];
//uint8_t CollisionByteCount = (NVB >> 4) & 0x0F;
//uint8_t CollisionBitCount = (NVB >> 0) & 0x0F;
switch (NVB) {
case ISO14443A_NVB_AC_START:
/* Start of anticollision procedure.
* Send whole UID CLn + BCC */
DataPtr[0] = UidCL[0];
DataPtr[1] = UidCL[1];
DataPtr[2] = UidCL[2];
DataPtr[3] = UidCL[3];
DataPtr[4] = ISO14443A_CALC_BCC(DataPtr);
*BitCount = ISO14443A_CL_FRAME_SIZE;
return false;
case ISO14443A_NVB_AC_END:
/* End of anticollision procedure.
* Send SAK CLn if we are selected. */
if ( (DataPtr[2] == UidCL[0]) &&
(DataPtr[3] == UidCL[1]) &&
(DataPtr[4] == UidCL[2]) &&
(DataPtr[5] == UidCL[3]) ) {
DataPtr[0] = SAKValue;
ISO14443AAppendCRCA(Buffer, 1);
*BitCount = ISO14443A_SAK_FRAME_SIZE;
return true;
} else {
/* We have not been selected. Don't send anything. */
*BitCount = 0;
return false;
}
default:
{
uint8_t CollisionByteCount = ((NVB >> 4) & 0x0f) - 2;
uint8_t CollisionBitCount = (NVB >> 0) & 0x0f;
uint8_t mask = 0xFF >> (8 - CollisionBitCount);
// Since the UidCL does not contain the BCC, we have to distinguish here
if (
((CollisionByteCount == 5 || (CollisionByteCount == 4 && CollisionBitCount > 0)) && memcmp(UidCL, &DataPtr[2], 4) == 0 && (ISO14443A_CALC_BCC(UidCL) & mask) == (DataPtr[6] & mask))
||
(CollisionByteCount == 4 && CollisionBitCount == 0 && memcmp(UidCL, &DataPtr[2], 4) == 0)
||
(CollisionByteCount < 4 && memcmp(UidCL, &DataPtr[2], CollisionByteCount) == 0 && (UidCL[CollisionByteCount] & mask) == (DataPtr[CollisionByteCount + 2] & mask))
)
{
DataPtr[0] = UidCL[0];
DataPtr[1] = UidCL[1];
DataPtr[2] = UidCL[2];
DataPtr[3] = UidCL[3];
DataPtr[4] = ISO14443A_CALC_BCC(DataPtr);
*BitCount = ISO14443A_CL_FRAME_SIZE;
} else {
*BitCount = 0;
}
return false;
}
/* TODO: No anticollision supported */
*BitCount = 0;
return false;
}
}
INLINE
bool ISO14443AWakeUp(void* Buffer, uint16_t* BitCount, uint16_t ATQAValue, bool FromHalt)
{
uint8_t* DataPtr = (uint8_t*) Buffer;
if ( ((! FromHalt) && (DataPtr[0] == ISO14443A_CMD_REQA)) ||
(DataPtr[0] == ISO14443A_CMD_WUPA) ){
DataPtr[0] = (ATQAValue >> 0) & 0x00FF;
DataPtr[1] = (ATQAValue >> 8) & 0x00FF;
*BitCount = ISO14443A_ATQA_FRAME_SIZE;
return true;
} else {
*BitCount = 0;
return false;
}
}
#endif