📄 paypass_tcl.c
字号:
//=============================================================================
// Copyright (C) INSIDE Contactless 1998-2005
//
// INSIDE Contactless reserves the right to make changes, without notice,
// to any product (including application note) herein to improve
// reliability, functionality, or design. INSIDE Contactless advises its
// customers to obtain the latest version of device data sheets to verify,
// before placing orders, that the information being relied upon by the
// customer is current.
//
// INSIDE Contactless makes no warranty that the use will not infringe any
// third party patent, copyright or trademark.
//
// Information furnished by INSIDE Contactless is believed to be accurate
// and reliable. However, INSIDE Contactless does not assume any liability
// resulting from the application or use of any product described within.
//
// All rights are reserved. Reproduction in whole or in part is prohibited
// without the written consent of the copyright owner.
//
// Bat 11a,
// Parc Club du Golf,
// Z.A.C. du Pichaury Tel : +33 (0)4.42.39.33.00
// 13856 Aix-en-Provence Cedex 3 Fax : +33 (0)4.42.39.63.19
// FRANCE Email : info@insidefr.com
//
//-----------------------------------------------------------------------------
// Project Code : PAYPASS LIBRARY
// Project Name : PAYPASS LIBRARY
// Module Name : PAYPASS_TCL.c
// Platform dev : Keil 礦ision 3 (IDE ) + Keil ARM Compiler
// Target : LPC2103 (ARM7TDMI Core)
// Language : C ANSI
// Revision : 1.0
// Description : PayPass TCL commands
//=============================================================================
// When Who Ver What
// 06-04-24 MCY 1.1 restructuration
// 06-05-12 FPK 1.2 corrections
//=============================================================================
#include "Paypass_Main_Defines.h"
#include "Paypass_TCL.h"
#if ((defined PAYPASS) || (defined FULL))
TTCLConfiguration g_TCLCard;
//-----------------------------------------------------------------------------
// Function name : v_fnTCLFrameBuild
//-----------------------------------------------------------------------------
// Description : This function creates the TCL object and initialize its parameters
// CID and NAD are not used in PayPass specifications
//
// IN : p_ePCBType Type of frame to send
// p_pabCommand T=CL command
// p_pabDataIn Data to send
// p_iDataInLength Size of data to send
//
// OUT : p_pabTCLFrameIn Frame to send
// p_piTCLFrameInLength Size of frame to send
// p_piTCLFrameOutLength Size of frame which will be received
//
// RETURN : - none -
//
// Notes : - none -
//-----------------------------------------------------------------------------
void v_fnTCLFrameBuild ( unsigned char p_ePCBType,
unsigned char *p_pabCommand,
unsigned char *p_pabDataIn,
unsigned char p_iDataInLength,
unsigned char *p_pabTCLFrameIn,
unsigned short *p_piTCLFrameInLength,
unsigned short *p_piTCLFrameOutLength)
{
// INIT TCL FRAME IN LENGTH
p_piTCLFrameInLength[0] =0x0;
// CHECK IF COMMAND
if (p_pabCommand != NULL)
{
// COPY COMMAND IN OUTPUT BUFFER
memcpy(p_pabTCLFrameIn, p_pabCommand, 5);
// SET TCL FRAME IN LENGTH
p_piTCLFrameInLength[0] = 5 ;
}
// CHECK IF DATA IN
if (p_pabDataIn != NULL)
{
// ADD DATA IN
memcpy(&p_pabTCLFrameIn[p_piTCLFrameInLength[0]], p_pabDataIn, p_iDataInLength);
// INIT OUT BUFFER LENGTH WITH IN BUFFER LENGTH + COMMAND LENGTH
p_piTCLFrameInLength[0] += p_iDataInLength;
}
// SHIFT OF 1 BYTE TO ADD PCB
memmove(&p_pabTCLFrameIn[1], p_pabTCLFrameIn, p_piTCLFrameInLength[0]);
// INC IN AND OUT TCL FRAME LENGTH
p_piTCLFrameInLength[0]++;
p_piTCLFrameOutLength[0]++;
// ADD PCB
switch (p_ePCBType)
{
case CST_pcbtINoChaining:
p_pabTCLFrameIn[0] = (unsigned char)(PCB_I | (g_TCLCard.f_iBlockNumber & 0x01));
break;
case CST_pcbtIWithChaining:
p_pabTCLFrameIn[0] = (unsigned char)(PCB_I | PCB_I_WITH_CHAINING | (g_TCLCard.f_iBlockNumber & 0x01));
break;
case CST_pcbtRACK:
p_pabTCLFrameIn[0] = (unsigned char)(PCB_R | PCB_R_WITH_ACK | (g_TCLCard.f_iBlockNumber & 0x01));
break;
case CST_pcbtRNACK:
p_pabTCLFrameIn[0] = (unsigned char)(PCB_R | PCB_R_WITH_NACK | (g_TCLCard.f_iBlockNumber & 0x01));
break;
case CST_pcbtSWTX:
p_pabTCLFrameIn[0] = (unsigned char)(PCB_S | PCB_S_WITH_WTX);
break;
case CST_pcbtDESELECT:
p_pabTCLFrameIn[0] = (unsigned char)(PCB_S | PCB_S_WITH_DESELECT);
break;
}
// ADD STATUS BYTES
p_piTCLFrameOutLength[0] += 2;
}
//-----------------------------------------------------------------------------
// Function name : b_fnTCLFrameExtract
//-----------------------------------------------------------------------------
// Description : This function extracts the data from a TCL frame and returns its type.
//
// IN : p_piTCLFrameLength Length of TCL frame received
// p_pabTCLFrame TCL frame received
// p_pwStatus Status from the ReceiveBuffer
//
// OUT : p_pabData Data extracted of the TCL frame
// p_pwStatus Status word
//
// RETURN : type of TCL frame
//
// Notes : - none -
//-----------------------------------------------------------------------------
unsigned char b_fnTCLFrameExtract( unsigned short *p_piTCLFrameLength,
unsigned char *p_pabTCLFrame,
unsigned char *p_pabData,
unsigned short *p_pwStatus)
{
unsigned char l_bPCB;
// SAVE PCB
l_bPCB = p_pabTCLFrame[0];
// PROTOCOL ERROR (Requirements 10.2)
if ( (l_bPCB == 0x02) || (l_bPCB == 0x03) || (l_bPCB == 0x12) || (l_bPCB == 0x13) || (l_bPCB == 0xA2) || (l_bPCB == 0xA3) || (l_bPCB == 0xB2) || (l_bPCB == 0xB3) || (l_bPCB == 0xF2) || (l_bPCB == 0xC2) )
{
// IF ( BLOCK NUMBER != PCD BLOCK NUMBER ) (Requirements 10.9)
/*Debug 11/12/06*/
// No block number with S-Block
if ( ((l_bPCB & 0xC0)!= 0xC0) && ( (l_bPCB & 0x01) != (g_TCLCard.f_iBlockNumber & 0x01)) )
{
#ifdef MODE_DEBUG_TCL
printf("Block num error\n");
#endif
return CST_pcbPROTOCOL_ERROR;
}
// I BLOCK
if ((l_bPCB & 0xE2) == PCB_I)
{
// REMOVE PCB
memcpy(p_pabTCLFrame, p_pabTCLFrame + 1, --p_piTCLFrameLength[0]);
// CHECK IF CHAINING
if ((l_bPCB & 0x10) == 0x10)
{
// TRANSFERT DATA
memcpy(p_pabData, p_pabTCLFrame, p_piTCLFrameLength[0]);
// RESULT
return CST_pcbtIWithChaining ;
}
else
{
// TRANSFERT DATA
memcpy(p_pabData, p_pabTCLFrame, p_piTCLFrameLength[0] - 2);
//GET STATUS
p_pwStatus[0] = (p_pabTCLFrame[p_piTCLFrameLength[0] - 2] << 8) | p_pabTCLFrame[p_piTCLFrameLength[0] - 1];
// DATA LENGTH WITHOUT STATUS WORD AND PCB
p_piTCLFrameLength[0] -= 2;
// RESULT
return CST_pcbtINoChaining ;
}
}
// R BLOCK
if ((l_bPCB & 0xE2) == PCB_R)
{
//CHECK IF ACK OR NACK
if ((l_bPCB & 0x10) == 0x10)
{
#ifdef MODE_DEBUG_TCL
printf("Extract NACK\n");
#endif
// R(NAK) RECEIVED CONSIDERED AS PROTOCOL ERROR (Requirements 10.9)
return CST_pcbPROTOCOL_ERROR;
}
else
{
return CST_pcbtRACK ;
}
}
// S BLOCK
if ( (l_bPCB & 0xC2) == PCB_S )
{
// CHECK IF SWTX OR DESELECT
if ( (l_bPCB & PCB_S_WITH_WTX) == PCB_S_WITH_WTX )
{
// PROTOCOL ERROR IF WTXM = 0 (Requirements 10.4)
if ( (p_pabTCLFrame[1] & 0x3F) == 0x00 )
{
#ifdef MODE_DEBUG_TCL
printf("Protocol Error WTX\n");
#endif
return CST_pcbPROTOCOL_ERROR;
}
// SET RESULT
return CST_pcbtSWTX;
}
return CST_pcbtDESELECT;
}
// Default path: return error
return CST_pcbtError;
}
else
{
#ifdef MODE_DEBUG_TCL
printf("Other protocol\n");
#endif
return CST_pcbPROTOCOL_ERROR;
}
}
//-----------------------------------------------------------------------------
// Function name : b_fnCardConnect
//-----------------------------------------------------------------------------
// Description : This function resets the RF field is requested and try to perform the requested
// anti-collisions ISO-14443-A/B-3, and establishes with a card a T=CL channel.
//
// IN : p_pchoice Protocol(s) used to connect the card
// p_iPCDMaximumInputFrameSize FDSI=p_iPCDMaximumInputFrameSize=8
//
// OUT : - none -
//
// RETURN : Result of card connection (TRUE/FALSE)
//
// Notes : - none -
//-----------------------------------------------------------------------------
unsigned char b_fnCardConnect( unsigned char p_pchoice,
unsigned short p_iPCDMaximumInputFrameSize)
{
unsigned char l_bProtocolInfo1;
unsigned char l_bProtocolInfo2;
// Initialize T=CL parameters
g_TCLCard.f_iBlockNumber = 0;
g_TCLCard.f_ePCDBitRate = CST_tclbr106kbps;
g_TCLCard.f_ePICCBitRate = CST_tclbr106kbps;
g_TCLCard.f_dPCDWaitingTimeBeforeSendingAnotherFrame = 0;
g_TCLCard.f_eCardType = CST_tclctISO_14443_A_B_4;
g_TCLCard.f_iPCDMaximumInputFrameSize = p_iPCDMaximumInputFrameSize;
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x20;
// ISO 14443-A CARD
if (p_pchoice == END_ACTIVATE_A)
{
// Set PCD waiting time before sending another frame (DEFAULT VALUE : 1172 / fc)
/*Debug FP DEFAULT VALUE remove bad compute*/
// g_TCLCard.f_dPCDWaitingTimeBeforeSendingAnotherFrame = 1172 / 13560000;
// Initialize ATS
if (g_lDataBytesReceived > 0x01)
{
//DECODE PICC MAXIMUM INPUT FRAME SIZE
switch (g_abRATS_ATTRIB[1] & 0x0F)
{
case 0:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x10;
break;
case 1:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x18;
break;
case 2:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x20;
break;
case 3:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x28;
break;
case 4:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x30;
break;
case 5:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x40;
break;
case 6:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x60;
break;
case 7:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x80;
break;
case 8:
g_TCLCard.f_iPICCMaximumInputFrameSize = 0x100;
break;
default:
return FALSE;
}
// Check if TA(1) is present
if ((g_abRATS_ATTRIB[1] & 0x10) == 0x10)
{
// Get protocol info 1
l_bProtocolInfo1 = g_abRATS_ATTRIB[2];
/* ONLY 106 kbits/s
// Detect PCD bit rate supported by PICC
if ((l_bProtocolInfo1 & 0x80) == 0x00)
{
//GET PICC BIT RATE & PCD BIT RATE ACCEPTANCE
if ((l_bProtocolInfo1 & 0x10) == 0x10) g_TCLCard.f_ePICCBitRate = CST_tclbr212kbps;
if ((l_bProtocolInfo1 & 0x20) == 0x20) g_TCLCard.f_ePICCBitRate = CST_tclbr424kbps;
if ((l_bProtocolInfo1 & 0x40) == 0x40) g_TCLCard.f_ePICCBitRate = CST_tclbr847kbps;
if ((l_bProtocolInfo1 & 0x01) == 0x01) g_TCLCard.f_ePCDBitRate = CST_tclbr212kbps;
if ((l_bProtocolInfo1 & 0x02) == 0x02) g_TCLCard.f_ePCDBitRate = CST_tclbr424kbps;
if ((l_bProtocolInfo1 & 0x04) == 0x04) g_TCLCard.f_ePCDBitRate = CST_tclbr847kbps;
}
else
{
//PCD & PICC SAME BIT RATE
if ((l_bProtocolInfo1 & 0x10) == 0x10) g_TCLCard.f_ePICCBitRate = CST_tclbr212kbps;
if ((l_bProtocolInfo1 & 0x20) == 0x20) g_TCLCard.f_ePICCBitRate = CST_tclbr424kbps;
if ((l_bProtocolInfo1 & 0x40) == 0x40) g_TCLCard.f_ePICCBitRate = CST_tclbr847kbps;
//SET PDC BIT RATE IDENTICAL
g_TCLCard.f_ePCDBitRate = g_TCLCard.f_ePICCBitRate ;
}
//Debug OC Test 103.0, 103.2
if ((l_bProtocolInfo1 & 0x08) == 0x08)
{
return FALSE;
}
*/
}
// Check if TB(1) is present
if ((g_abRATS_ATTRIB[1] & 0x20) == 0x20)
{
// Get protocol info 2
l_bProtocolInfo2 = g_abRATS_ATTRIB[3];
// Get the time which the PCD must wait before sending another frame
g_FWT_SFGT = b_fnFWT_SFGTCalculate(_SFGT,l_bProtocolInfo2,0); // Without D(SFGT)
g_TCLCard.f_dPCDWaitingTimeBeforeSendingAnotherFrame = g_FWT_SFGT ;
// Get the maximum time the PCD have to wait for receiving the response of the PICC
g_FWT_SFGT = b_fnFWT_SFGTCalculate(_FWT,l_bProtocolInfo2,1);
}
}
// Assign card type
g_TCLCard.f_eCardType = CST_tclctISO_14443_A_4;
// Return success
return TRUE;
}
// ISO 14443-B CARD
else
{
// Assign card type
g_TCLCard.f_eCardType = CST_tclctISO_14443_B_4;
l_bProtocolInfo1 = g_abATQBResponse[10];
l_bProtocolInfo2 = g_abATQBResponse[11];
switch (l_bProtocolInfo1 >> 4)
{
case 0: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x10; break;
case 1: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x18; break;
case 2: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x20; break;
case 3: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x28; break;
case 4: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x30; break;
case 5: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x40; break;
case 6: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x60; break;
case 7: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x80; break;
case 8: g_TCLCard.f_iPICCMaximumInputFrameSize = 0x100; break;
default: return FALSE;
}
// Get the maximum time the PCD have to wait for receiving the response of the PICC
g_FWT_SFGT = b_fnFWT_SFGTCalculate(_FWT,l_bProtocolInfo2,1); // With D(FWT)
// Return success
return TRUE;
}
}
//-----------------------------------------------------------------------------
// Function name : b_fnCardDisconnect
//-----------------------------------------------------------------------------
// Description : This function sends an DESELECT APDU using the ISO-14443-4 T=CL protocol.
//
// IN : p_pStructReader Pointer to the used StructReader structure
//
// OUT : - none -
//
// RETURN : TRUE Card deselected
//
// Notes : - none -
//-----------------------------------------------------------------------------
unsigned char b_fnCardDisconnect(StructReader *p_pStructReader)
{
unsigned char l_abTCLFrame[300];
unsigned char l_abDataIn[1];
unsigned char l_abDataOut[2];
unsigned char l_iRetryCount;
unsigned char l_iRetryCount2;
unsigned short l_wStatus;
unsigned char l_ePCBType;
unsigned char l_eTransmitStep;
unsigned char l_bWTX;
unsigned short l_iTCLFrameInLength;
unsigned short l_iTCLFrameOutLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -