495 lines
9.3 KiB
C++
495 lines
9.3 KiB
C++
#include <cstdlib>
|
||
#include "VCDOurs.h"
|
||
#include "qlogging.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。这个任务应该交给VICC,VICC会返回错误通知用户;
|
||
// 用户可以在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*4, 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;
|
||
}
|
||
}
|