重构各页面代码,从h文件改为cpp文件;

添加硬件接口并添加,readerAPI使用硬件接口获取invenory信息和connect;
完成开卡初始页面,获取卡号和学号。
This commit is contained in:
2024-07-29 11:24:26 +08:00
parent f229cd4a28
commit 4b8460f4ce
17 changed files with 1411 additions and 157 deletions

493
VCDOurs.cpp Normal file
View File

@@ -0,0 +1,493 @@
#include <cstdlib>
#include "VCDOurs.h"
CVCDOurs::CVCDOurs(void)
{
m_bComOpened = false;
}
CVCDOurs::~CVCDOurs(void)
{
if( m_bComOpened )
{
t15portClose();
}
}
// 使用串口和建立连接
int CVCDOurs::connectReaderByCOM( int comno )
{
if(t15portOpen(comno))
{
t15bSubCarrier=m_ucSubCarrier;
t15bDataCoding=m_ucDataCoding;
t15bFullPower=1;
t15bDataRate=m_ucDataRate;
m_bComOpened = true;
if( t15setProtocol() == 0 )
{
return 1;
}
}
return 0;
}
void CVCDOurs::disconnectReaderByCOM( )
{
if( m_bComOpened )
{
t15portClose( );
}
}
int CVCDOurs::inventory(
bool bAFIUsed,
uchar_t ucAFI,
int nViccNum, // 应用层的接收的UID数量;
uchar_t aucDSFID[],
uchar_t aucUID[][8] )
{
t15bInventory=1;
// t15bAddress & t15bSelect在inventory=1的情况下表示: AFI 和 NBSlots
// 而NBSlots为16取值为0.
t15bAddress=0; // 本来就没有用
t15bOption=0; // 没用用.
if( bAFIUsed )
{
t15bSelect=1; // 此处的含义是没有AFI其实可以有
sprintf( t15AFI, "%02x", ucAFI );
}
char* strUID[16];
for( int i = 0; i < 16; i++ )
{
strUID[i] = new char[50];
}
int n = doInventory( strUID );
n = ( n >= nViccNum ) ? nViccNum : n;
// 开始解析.
for( int i = 0; i < n; i++ )
{
StringToHex( strUID[i], aucUID[i] );
}
for( int i = 0; i < 16; i++ )
{
delete []strUID[i];
}
return n;
}
// Ours
// 1. 执行inventory时因为t15bSelect=0因此没有AFI flag.
// 2. 没有处理返回的DSFID.
//
int CVCDOurs::inventory( char *pTagUID[] )
{
t15bInventory=1;
// t15bAddress & t15bSelect在inventory=1的情况下表示: AFI 和 NBSlots
// 而NBSlots为16取值为0.
t15bAddress=0; // 本来就没有用
t15bSelect=0; // 此处的含义是没有AFI其实可以有
t15bOption=0; // 没用用.
return doInventory( pTagUID );
}
int CVCDOurs::doInventory( char *pTagUID[] )
{
// 对返回的UID
// 每个[]一个UID
// []表示分配的slot数
// [z,40]中, 'z'表示发生了冲突
// 返回的序列是防冲突过程中的全部序列。
//
char cmdsend[CMD_LEN],reply[CMD_LEN]/*="23[,40][2343334239,55][,49][abcderfdsdfs0d,30]"*/;
t15execute(INVENTORY,cmdsend,reply);
int k = 0;
char *p,*q,tstr[50]={0};
p=reply;
while (1)
{
p = strchr(p,'[');
if (NULL == p)
break ;
q = strchr(p+1,',');
if (NULL == q)
break ;
// 'z'表示冲突
if (q != (p+1) && *(p+1) != 'z' )
{
t15changeByteOrder(tstr,p+1,q-p-1); //返回的数据是低字节在前,调整字节序
strcpy( pTagUID[k++], tstr );
// 获取某个Tag的详细信息call GetSystemInfo().
setVICCStr( pTagUID[k-1] );
}
p = q+1;
}
return k;
}
//已经通过UID获得了VICC的信息.
int CVCDOurs::getSystemInfo(
uchar_t *pucUID,
uchar_t *pinfoFlag,
uchar_t *pDSFID, uchar_t *pAFI, uchar_t *pBlockNum, uchar_t *pBlockSize, uchar_t *pICRef
)
{
char str[100];
t15bOption = 0;
t15bInventory = 0;
if( pucUID )
{
t15bAddress=1;
t15bSelect = 0;
HexToString( pucUID, 8, str );
t15changeByteOrder( t15UID, str, 16 );
t15UID[16]=0;
}
else
{
t15bAddress=0;
t15bSelect =1;
}
//执行命令
char cmdstr[CMD_LEN] = {0},reply[CMD_LEN] = {0};
if (!t15execute(T15SYSTEM_INFO,cmdstr,reply))
{
return 0;
}
// 开始解释数据.
char *p;
char tflag[5], iflag, rflag;
{
if (! (p = strchr (reply, '[') ) )
return 0;
p++;
if (*p && (*p == ']' || *p == 'z' || *p == 'Z') )
return 0;
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
rflag=(char)strtol(tflag,NULL,16);
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
if( rflag != 0x00) //Err-Flag is set
{
return rflag;
}
else
{
iflag=(char)strtol(tflag,NULL,16);
*pinfoFlag = iflag;
p += 16;
if( iflag & 0x01 )
{
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
*pDSFID =(char)strtol(tflag,NULL,16);
}
if( iflag & 0x02 )
{
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
*pAFI =(char)strtol(tflag,NULL,16);
}
if( iflag & 0x04 )
{
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
*pBlockNum =(char)strtol(tflag,NULL,16);
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
*pBlockSize = ((char)strtol(tflag,NULL,16))&0x1F;
}
if( iflag & 0x08 )
{
tflag[0]=*p++;
tflag[1]=*p++;
tflag[2]='\0';
*pICRef = ((char)strtol(tflag,NULL,16))&0x1F;
}
}
}
return rflag;
}
// VCD不处理一些参数的合法性判断比如nFirstBlock等
// 因为1. VCD没有必要保留2.射频场中可能存在不同的VICC从而导致参数不同;
// 3. 不要说VCD知道每个UID的参数所以判断。虽然可以但不合理即使pucUID=NULL即处理SELECT模式的VICC时虽然
// VCD的确知道是哪个VICC。这个任务应该交给VICCVICC会返回错误通知用户
// 用户可以在inventory后使用get system info获取需要的信息;
int CVCDOurs::readBlocks( int nFirstBlock, int nBlockNum, uchar_t *pDat, uchar_t *pSecurity, uchar_t *pucUID )
{
// m_nBlockNum想表示 VICC 的可用block数。
// 可以不做这种判断毕竟m_nBlockNum不是VCD的参数而是VICC的属性应该由VICC判断并返回.
char str[100];
t15bOption = 0;
t15bInventory = 0;
if( pucUID )
{
t15bSelect = 0;
t15bAddress=1;
HexToString( pucUID, 8, str );
t15changeByteOrder( t15UID, str, 16 );
t15UID[16]=0;
}
else
{
t15bSelect = 1;
t15bAddress =0;
}
sprintf( t15FirstBN, "%02d", nFirstBlock );
sprintf( t15NumBl, "%02d", nBlockNum - 1 );
//执行命令
char cmdstr[CMD_LEN] = {0},reply[CMD_LEN] = {0};
int cmdno = ( nBlockNum == 1 )?READ_SB:READ_MB;
if (!t15execute(cmdno,cmdstr,reply))
{
return false;
}
//处理返回数据
char *p,*q,tstr[CMD_LEN];
p=strchr(reply,'[')+1;
if(NULL == p)
return 0;
q=strchr(p,']');
if(NULL == q)
return 0;
*q=0;
// if('z' == *p )
// 2023/7/4修改:
// 返回的reply出现过如下的值: “[]”
// 此时*q=0,导致']'被0替换
// 后续代码 tf[0/1] = *p++,导致 p > q;
// 再调用t15changeByteOrder()时q-p = -2 < 0;
// 而t15changeByteOrder()函数定义如下:
/*
HF15693_API void t15changeByteOrder(char *pout, const char *pin,int lenbytes)
{
int i;
for (i = 0; i < lenbytes; i += 2)
{
pout[lenbytes-2-i] = pin[i];
pout[lenbytes-1-i] = pin[i+1];
}
pout[lenbytes] = 0;
}
*/
// 在 lenbytes =-2 < 0的情况下直接访问了pout[-2],导致程序直接崩溃!
// 修改如下:
if('z' == *p || p == q )
{
return 0;
}
// 同时放开该判断!
if(2 < q-p)
{
char tf[3];
tf[0]=*p++;
tf[1]=*p++;
tf[2]=0;
int tfi=strtoul(tf,NULL,10);
// 因为代码:*q = 0导致tf是空串
// 因此tfi=0, 所以下述语句起不到判断作用;
if(OP_RESPONSE_FLAG_ERROR & tfi) //检查标志位,是否发生错误
return 0;
if(READ_SB == cmdno)
{
t15changeByteOrder(tstr,p,q-p);
}
else
{
int i=strtoul(t15NumBl,NULL,10)+1;
t15changeByteOrder_MB(tstr,p,i);
}
StringToHex( tstr, pDat );
return strlen( tstr )/2;
}
return 0;
}
int CVCDOurs::getValueFromChar( char c )
{
if( c >= '0' && c <= '9' )
{
return c-'0';
}
else if( c >= 'a' && c <= 'f' )
{
return c-'a' + 10;
}
else if( c >= 'A' && c <= 'F' )
{
return c - 'A' + 10;
}
else
{
return -1;
}
}
// 返回UID的字节长度
// 如果不是偶数把str最后一个字符丢弃
int CVCDOurs::StringToHex( char *str, uchar_t aucUID[] )
{
int k = 0;
int t1, t2;
int len = strlen( str )/2;
for( int i = 0; i < len; i++ )
{
t1 = getValueFromChar(str[k++]);
t2 = getValueFromChar(str[k++]);
aucUID[i] = ( t1 << 4 ) + t2;
}
return len;
}
void CVCDOurs::HexToString( uchar_t aucDat[], int len, char *str )
{
int k = 0;
int t;
for( int i = 0; i < len; i++ )
{
t = aucDat[i] >> 4;
if( t <= 9 )
{
str[k++] = t + '0';
}
else
{
str[k++] = t - 10 + 'A';
}
t = aucDat[i] & 0x0F;
if( t <= 9 )
{
str[k++] = t + '0';
}
else
{
str[k++] = t - 10 + 'A';
}
}
str[k] = '\0';
}
int CVCDOurs::writeBlocks( int nFirstBlock, int nBlockNum, uchar_t *pDat, uchar_t *pucUID )
{
int k = 0;
for( int i = 0; i < nBlockNum; i++ )
{
k += writeBlock( nFirstBlock + i, pDat+i*8, pucUID );
}
return k;
}
int CVCDOurs::writeBlock( int nFirstBlock, uchar_t *pDat, uchar_t *pucUID )
{
char str[100];
t15bOption = 0;
t15bInventory = 0;
t15bSelect = 0;
if( pucUID )
{
t15bAddress = 1;
HexToString( pucUID, 8, str );
t15changeByteOrder( t15UID, str, 16 );
t15UID[16]=0;
}
else
{
t15bAddress = 0;
}
sprintf( t15FirstBN, "%02d", nFirstBlock );
sprintf( t15NumBl, "00" );
// 此处4是blocksize.
HexToString( pDat, 4, str );
t15changeByteOrder( t15Data, str, 8 );
t15Data[8]=0;
strcpy( str, t15Data );
char cmdstr[CMD_LEN] = {0}, reply[CMD_LEN] = {0};
if (!t15execute(WRITE_SB,cmdstr,reply))
{
// MessageBox("执行错误,可能参数错误", 0, MB_ICONSTOP);
return 0 ;
}
char *p,*e;
if (! (p = strchr (reply, '[') ) )
return 0;
p++;
//if (*p && (*p == ']' || *p == 'z' || *p == 'Z') ) return 2;
if (! (e = strchr(p, ']')))
return 0;
if (e == p)
return 0;
// if( 2 <= e-p)
{
char tf[3];
tf[0] = *p++;
tf[1] = *p++;
tf[2] = '\0';
char tfi=(char)strtol(tf,NULL,16);//
if (OP_RESPONSE_FLAG_ERROR & tfi)
return 0;
else
return 1;
}
}