495 lines
9.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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。这个任务应该交给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*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;
}
}