📄 cdatalink.cpp
字号:
// cDataLink.cpp: implementation of the cDataLink class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include "cos.h"
#include "CDataLink.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDataLink::CDataLink()
{
// Declaration of PICC or Application specific settings
power_level_indication = 0x00; // 00: PICC does not support power level indication
nad = 0x0F; // e.g.
wtxm = 0x15; // e.g.
// Internal Variables Declaration
i = 0; // Loop parameter only for I-Block -> Chaining PCD
j = 0; // Loop parameter only for I-Block -> Chaining PICC
n = 0; // Loop parameter
r = 0; // Loop parameter
offset = 0; // Counter to calculate the maximum space for INF Bytes
byte_cnt = 0; // Byte Counter only used for Chaining PICC
byte_nr = 1;
temp = 0;
processing = READY;
fsdi = 128; // will be later corrected
//prot_state = RECEIVE_WAIT;
block_number = 0x00; // Initializised to 0 (Rule B)
}
CDataLink::~CDataLink()
{
}
int CDataLink::ImplementLinker(BYTE cid,BYTE prot_state,CInfBuf *CInfBuffer)
{
// Loop to processing the ISO/IEC 14443-4 Transmission Protocol
while ( 1 )
{
switch ( prot_state )
{
// WAIT STATE
case RECEIVE_WAIT:
// Reset variable
byte_nr = 1;
// Protocol error catching
if ( processing == PROTOCOL_ERROR )
{
// If a protocol error occurs all flag have to be reset
i = 0;
j = 0;
byte_cnt = 0;
CComBuf.ClearBuffer();
processing = READY;
}
if (CComBuf.ReceiveBuffer()!= 0)
{
//test code require
return 0;
// Error occur(Rule 4)
if (processing == S_DESELECT_REQ)
{
//Rule 8
prot_state = SEND_S_DES_REQ;
break;
}
if (processing == PICC_CHAINING)
{
//Rule 5
prot_state = SEND_R_ACK;
break;
}
prot_state = SEND_R_NAK;
break;
}
// Error detecting and Decoding of the PCB Byte
// Check the validation of the CID
if ( (CComBuf.GetBufferValue(0) & M_CID) != 0 )
{
if ( (CComBuf.GetBufferValue(byte_nr) & M_CID_BYTE) != cid )
{
// CID not matched
prot_state = RECEIVE_WAIT; // If not -> Wait State
break;
}
else
{
// CID matched
//add_cid = true;
byte_nr++;
}
}
else
{
prot_state = RECEIVE_WAIT;
break;
}
// Check PCB Byte for I-Block
if ( (CComBuf.GetBufferValue(0) & M_I_BLOCK) == I_BLOCK )
{
//add_nad = false;
prot_state = RECEIVE_I;
break;
}
// Check PCB Byte for R(ACK)-Block
if ( (CComBuf.GetBufferValue(0) & M_R_BLOCK) == R_BLOCK_ACK )
{
if ( CComBuf.GetBufferCount()!= byte_nr )
{
// Transmission error occured
prot_state = SEND_R_NAK;
break;
}
else
{
// R-Block ACK received
prot_state = RECEIVE_R_ACK;
break;
}
}
// Check PCB Byte for S(DES)-Block
if ( (CComBuf.GetBufferValue(0) & M_S_BLOCK) == S_BLOCK_DES )
{
if ( CComBuf.GetBufferCount() != byte_nr )
{
// Transmission error occured
prot_state = SEND_S_DES_REQ ;
break;
}
else
{
// S-Block DES received
//prot_state = RECEIVE_S_DES_REQ;
return 0;
}
}
// Check PCB Byte for S(WTX)request-Block
if ( (CComBuf.GetBufferValue(0) & M_S_BLOCK) == S_BLOCK_WTX )
{
if ( CComBuf.GetBufferCount() != (byte_nr + 1) )
{
// Transmission error occured
prot_state = SEND_R_NAK;
break;
}
else
{
// S-Block WTX received
prot_state = SEND_S_WTX_RES;
break;
}
}
// Block received with no valid coding
prot_state = SEND_R_NAK;
break;
//SEND DESELECT REQUEST
case SEND_S_DES_REQ:
CComBuf.ClearBuffer();
temp = S_BLOCK_DES | M_CID; // Set CID bit
CComBuf.AddBufferValue(temp); // Append PCB Byte to transmit buffer
// Generate CID Byte with Power Level Indication
temp = 0x00 | cid; // Add Power Level Indication and cid to CID Byte
CComBuf.AddBufferValue(temp); // Append CID Byte to transmit buffer
// Save then send S (Des)
CBufferCopy.CopyBuffer(CComBuf);
CComBuf.TransmitBuffer();
processing = S_DESELECT_REQ;
prot_state = RECEIVE_WAIT;
break;
// SEND S (WTX) RESPONSE
case SEND_S_WTX_RES:
CComBuf.ClearBuffer();
temp = S_BLOCK_WTX | M_CID; // Set CID bit
CComBuf.AddBufferValue(temp); // Append PCB Byte to transmit buffer
// Generate CID Byte
temp = 0x00|cid;
CComBuf.AddBufferValue(temp); // Append CID Byte to transmit buffer
temp = 0x00 | wtxm;
CComBuf.AddBufferValue(temp); // Append WTXM Byte to transmit buffer
// Save then send WTX(Res)
CBufferCopy.CopyBuffer(CComBuf);
CComBuf.TransmitBuffer();
prot_state = RECEIVE_WAIT;
break;
// Retransmit the last block
case SEND_RETRANSMIT:
CBufferCopy.RestoreBuffer(&CComBuf);
CComBuf.TransmitBuffer();
// Goto next state
prot_state = RECEIVE_WAIT;
break;
// Send R (ACK) after received part of chain
case SEND_R_ACK:
CComBuf.ClearBuffer();
temp = R_BLOCK_ACK | M_CID; // Set CID bit
temp = temp | block_number; // Add Block Number
CComBuf.AddBufferValue(temp); // Append PCB Byte to transmit buffer
// Generate CID Byte
temp = power_level_indication | cid; // Add Power Level Indication and cid to CID Byte
CComBuf.AddBufferValue(temp); // Append CID Byte to transmit buffer
// Save the transmission data
CBufferCopy.CopyBuffer(CComBuf);
// Send R (ACK)
CComBuf.TransmitBuffer();
// Goto next State
prot_state = RECEIVE_WAIT;
break;
case SEND_R_NAK:
CComBuf.ClearBuffer();
temp = R_BLOCK_NAK | M_CID; // Set CID bit
temp = temp | block_number; // Add Block Number
CComBuf.AddBufferValue(temp); // Append PCB Byte to transmit buffer
// Generate CID Byte
temp = 0x00 | cid; // cid to CID Byte
CComBuf.AddBufferValue(temp); // Append CID Byte to transmit buffer
// Save the transmission data
CBufferCopy.CopyBuffer(CComBuf);
// Send R (ACK)
CComBuf.TransmitBuffer();
// Goto next State
prot_state = RECEIVE_WAIT;
break;
//R (ACK) Received
case RECEIVE_R_ACK:
// Block numbering rules (Rule B)
if ( (CComBuf.GetBufferValue(0) & M_BLOCK_NUMBER) == block_number )
{
// Received Block Number is equal to the current PCD Block number
block_number ^= 0x01; // Toggle the block number
prot_state = SEND_I;
break;
}
else
{
// Transmission error occured,Retransmit last block
prot_state = SEND_RETRANSMIT;
break;
}
//I-BLOCK Received
case RECEIVE_I:
n = 0; // Reset of the loop parameter
// Block number handling
if ( (CComBuf.GetBufferValue(0) & M_BLOCK_NUMBER) == block_number )
{
// Received Block Number is equal to the current PCD Block number
block_number ^= 0x01; // Toggle the block number
}
// Chaining?
if ( (CComBuf.GetBufferValue(0) & M_CHAINING) == 0 )
{
// No Chaining or last part of Chain
// Get INF Bytes from the received block
CInfBuffer->ClearBuffer();
for ( n = byte_nr; n < CComBuf.GetBufferCount(); n++)
{
CInfBuffer->AddBufferValue(CComBuf.GetBufferValue(n));
}
processing = READY; // Reset this Flag for protocol error detecting
// Goto next State
prot_state = APPLICATION_STATE;
break;
}
else
{
//Set Chaining Flag
processing = PICC_CHAINING;
// Get part of INF Bytes from the received block and add it to
// the former received Bytes
for ( n = byte_nr; n < CComBuf.GetBufferCount(); n++)
{
CInfBuffer->AddBufferValue(CComBuf.GetBufferValue(n));
}
//Rule 5
prot_state = SEND_R_ACK;
break;
}
//Send I Block
case SEND_I:
CComBuf.ClearBuffer();
offset = 4; // 1xPCB + 1xCID + 2xCRC
// Append I-Block Code to PCB Byte
temp = I_BLOCK | block_number;
temp|=M_CID;
CComBuf.AddBufferValue(temp);
//Append CID
temp = 0x00 | cid; // Add cid to CID Byte temp = cid;
CComBuf.AddBufferValue(temp);
// NO CHAINING
if ( (offset + (CInfBuffer->GetBufferCount()- byte_cnt)) <= fsdi )
{
// No Chaining required
n = CInfBuffer->GetBufferCount() - byte_cnt;
// Append INF Bytes
for ( j = 0; j < n ; j++ )
{
// Append Byte
CComBuf.AddBufferValue(CInfBuffer->GetBufferValue(byte_cnt++));
}
// Reset of the Loop parameter
j = 0;
offset = 0;
n = 0;
byte_cnt = 0;
processing = READY;
CInfBuffer->ClearBuffer();
}
else
{
// Chaining required
processing = PCD_CHAINING; // Set PCD Chaining flag
// Set chaining bit in PCB
CComBuf.SetBufferValue(CComBuf.GetBufferValue(0)| M_CHAINING,0);
// Append INF Bytes
for ( j = 0; j < (fsdi - offset); j++ )
{
// Append Byte
CComBuf.AddBufferValue(CInfBuffer->GetBufferValue(byte_cnt++));
}
}
// Save the transmission data
CBufferCopy.CopyBuffer(CComBuf);
// Send I-Block
CComBuf.TransmitBuffer();
prot_state = RECEIVE_WAIT;
break;
// Application State
case APPLICATION_STATE:
return 1;
// Error has been occured -> WAIT State
default:
processing = PROTOCOL_ERROR;
prot_state = RECEIVE_WAIT;
}//switch
}//while
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -