#ifndef	__MCU_ATR_H__
#define	__MCU_ATR_H__

#include "pcscdefines.h"
#include <string.h>
#include "ATR.h"

#define BOOL	int
#define TRUE	(1)
#define FALSE	(0)

/* Invert order of bits in a byte: b7->b0, b0->b7 */
#ifndef INVERT_BYTE
#define INVERT_BYTE(a)	((((a) << 7) & 0x80) | \
						(((a) << 5) & 0x40) | \
						(((a) << 3) & 0x20) | \
						(((a) << 1) & 0x10) | \
						(((a) >> 1) & 0x08) | \
						(((a) >> 3) & 0x04) | \
						(((a) >> 5) & 0x02) | \
						(((a) >> 7) & 0x01))
#endif

typedef enum
{
	MCU_ATR_CONVENTION_DIRECT,
	MCU_ATR_CONVENTION_INVERSE
} MCU_ATR_CONVENTION, *PMCU_ATR_CONVENTION;

typedef enum
{
	MCU_ATR_PROTO_T0	= ATR_TDI_PROTO_T0,
	MCU_ATR_PROTO_T1	= ATR_TDI_PROTO_T1,
	MCU_ATR_PROTO_T2	= ATR_TDI_PROTO_T2,
	MCU_ATR_PROTO_T3	= ATR_TDI_PROTO_T3,
	MCU_ATR_PROTO_T14	= ATR_TDI_PROTO_T14
} MCU_ATR_PROTO, *PMCU_ATR_PROTO;

typedef enum
{
	MCU_ATR_INTEGER_VALUE_FI,
	MCU_ATR_INTEGER_VALUE_DI,
	MCU_ATR_INTEGER_VALUE_II,
	MCU_ATR_INTEGER_VALUE_PI1,
	MCU_ATR_INTEGER_VALUE_N,
	MCU_ATR_INTEGER_VALUE_PI2
} MCU_ATR_INTEGER_VALUE;

typedef enum
{
	MCU_ATR_PARAMETER_F,
	MCU_ATR_PARAMETER_D,
	MCU_ATR_PARAMETER_I,
	MCU_ATR_PARAMETER_P,
	MCU_ATR_PARAMETER_N
} MCU_ATR_PARAMETER;

#define MCU_ATR_MAX_SIZE		(33) /* Max ATR byte array size */
#define MCU_ATR_MAX_HISTORICAL	(15) /* Max historical size */
#define MCU_ATR_MAX_PROTOCOLS	(7)	/* Max no. of protocols */
#define MCU_ATR_MAX_IB			(4) /* Max no. of interface/protocol */

typedef enum
{
	MCU_ATR_INTERFACE_TA	= 0,
	MCU_ATR_INTERFACE_TB	= 1,
	MCU_ATR_INTERFACE_TC	= 2,
	MCU_ATR_INTERFACE_TD	= 3
} MCU_ATR_INTERFACE;

typedef enum
{
	MCU_ATR_OK			= 0,
	MCU_ATR_NOT_FOUND,		/* Data no present in ATR */
	MCU_ATR_MALFORMED		/* ATR can't be parsed */
} MCU_ATR_RESULT;

typedef struct _MCU_ATR
{
	int	length;

	UCHAR	TS;
	UCHAR	T0;

	struct {
		UCHAR	value;
		BOOL	bPresent;
	} ib[MCU_ATR_MAX_PROTOCOLS][MCU_ATR_MAX_IB], TCK;
	int		numProtocol;

	UCHAR	historical[MCU_ATR_MAX_HISTORICAL];
	int		historicalSize;
} MCU_ATR, *PMCU_ATR;

extern int		MCU_ATR_FIDecode[16];
extern double	MCU_ATR_DIDecode[16];
extern int		MCU_ATR_IIDecode[4];

MCU_ATR_RESULT
MCUAtrInit(	PMCU_ATR	pMCUAtr,
			PUCHAR		atrBuf,
			int			atrBufLen);

void
MCUAtrCleanUp(PMCU_ATR	pMCUAtr);

/* General smartcard characteristics */
MCU_ATR_RESULT
MCUAtrGetConvention(PMCU_ATR			pMCUAtr,
					PMCU_ATR_CONVENTION	pConvention);

int
MCUAtrGetNumProtocol(PMCU_ATR	pMCUAtr);

MCU_ATR_RESULT
MCUAtrGetProtocol(	PMCU_ATR		pMCUAtr,
					int				protoNo,
					PMCU_ATR_PROTO	pProto);

/* ATR parameters and integer values */
MCU_ATR_RESULT	MCUAtrGetInterfaceByte(
					PMCU_ATR			pMCUAtr,
					int					protoNo,
					MCU_ATR_INTERFACE	interfaceNo,
					PUCHAR				pValue);

MCU_ATR_RESULT	MCUAtrGetIntegerValue(
					PMCU_ATR				pMCUAtr,
					MCU_ATR_INTEGER_VALUE	integerValue,
					PUCHAR					pValue);

double	MCUAtrGetParameter(	PMCU_ATR			pMCUAtr,
							MCU_ATR_PARAMETER	parameter);

MCU_ATR_RESULT	MCUAtrGetHistoricalBytes(	PMCU_ATR	pMCUAtr,
											PUCHAR		pHist,
											int*		pLength);

MCU_ATR_RESULT	MCUAtrGetCheckByte(	PMCU_ATR	pMCUAtr,
									PUCHAR		pCheckByte);

unsigned long MCUAtrGetFsMax(PMCU_ATR	pMCUAtr);

double	MCUAtrDecodeFI(UCHAR	fi);

double	MCUAtrDecodeDI(UCHAR	di);

#endif	/* __MCU_ATR_H__ */
