我正在研究一个间歇性的问题,即从HID OMNIKEY非接触式读卡器的TI Tag HF-I RFID卡读取8块数据。下面的ReadEightBlocks
例程从for
循环中调用8次,每次循环startBlockNum
增加8。读取卡上的所有64个数据块,8个读取8个块。 ReadEightBlocks
调用SmartCardTransmit()
,然后调用SCardTransmit()
。但是,读取后8个块偶尔会失败,错误代码为0x6A 0x82
。任何人都可以解释为什么即使发出正确的命令,读取偶尔会失败吗?
protected bool ReadEightBlocks(ulong uid, int startBlockNum, out UInt32[] blocksData)
{
bool bFlag = false;
int numBlocks = 8;
int numBytePerBlock = 8;
int rxBufIndx = 0;
string rxBufData = string.Empty;
SmartCardData pack = new SmartCardData();
blocksData = new UInt32[numBlocks];
try
{
byte[] sendBuffer = { 0xFF, 0xB0, 0x00, Convert.ToByte(startBlockNum), 0x20 };
SCardTransmitReceived rxBuf = SmartCardTransmit(sendBuffer, sendBuffer.Length);
if (rxBuf.RcvFlag == SCardTransmitFlag.SUCCESS)
{
if ((rxBuf.RcvBuf[rxBuf.RcvBufLen - 2] == 0x90) && (rxBuf.RcvBuf[rxBuf.RcvBufLen - 1] == 0))
{
rxBufData = ParseRcvBuffer(rxBuf.RcvBuf, rxBuf.RcvBufLen);
pack.TransmitData = rxBufData;
numBlocks = rxBufData.Length / numBytePerBlock;
blocksData = new UInt32[numBlocks];
try
{
for (int i = 0; i < numBlocks; i++)
{
// Get a substring of the next 8 characters. This is the block data in hex, little-endian.
string blockDataString = rxBufData.Substring(rxBufIndx, numBytePerBlock);
blocksData[i] = System.UInt32.Parse(blockDataString, System.Globalization.NumberStyles.AllowHexSpecifier);
blocksData[i] = (uint)System.Net.IPAddress.HostToNetworkOrder((int)blocksData[i]);
// Next block
rxBufIndx += numBytePerBlock;
}
}
catch
{
return bFlag;
}
bFlag = true;
}
else if ((rxBuf.RcvBuf[rxBuf.RcvBufLen - 2] == 0x62) && (rxBuf.RcvBuf[rxBuf.RcvBufLen - 1] == 0x81))
{
// Warning
pack.TransmitData = string.Format("ReadEightBlocks(startBlockNum = {0}) --> Part of returned data may be corrupted.", startBlockNum.ToString());
}
else if ((rxBuf.RcvBuf[rxBuf.RcvBufLen - 2] == 0x62) && (rxBuf.RcvBuf[rxBuf.RcvBufLen - 1] == 0X82))
{
// Warning
pack.TransmitData = string.Format("ReadEightBlocks(startBlockNum = {0}) --> End of file reached before reading expected number of bytes.", startBlockNum.ToString());
}
else
{
// Error
pack.TransmitData = string.Format("ReadEightBlocks(startBlockNum = {0}) --> Error code.", startBlockNum.ToString());
}
pack.ReaderEvent = AvedroSmartCard.SmartCardReaderEvent.ReadEightBlocks;
OnRaisePacketReceivedEvent(new PacketReceivedEventArgs(pack));
_logger.Debug("Packet transmit data" + pack.TransmitData);
_logger.Debug("rxBuf.RcvBuf[rxBuf.RcvBufLen - 2] = " + (rxBuf.RcvBuf[rxBuf.RcvBufLen - 2]).ToString("X"));
_logger.Debug("rxBuf.RcvBuf[rxBuf.RcvBufLen - 1] = " + (rxBuf.RcvBuf[rxBuf.RcvBufLen - 1]).ToString("X"));
}
else
{
// Raise Error
_logger.Debug("rxBuf.RcvFlag != SUCCESS!");
}
}
catch (Exception ex)
{
string sMsg = String.Format("{0} - {1} {2}", MethodBase.GetCurrentMethod().Name, ex.GetType(), ex.Message);
_logger.DebugException(sMsg, ex);
}
return bFlag;
}
protected SCardTransmitReceived SmartCardTransmit(Byte[] sendBuffer, int sendbufferlen)
{
int iRetval;
SCardTransmitReceived rcvBufObj = new SCardTransmitReceived();
HiDWinscard.SCARD_IO_REQUEST sioreq;
sioreq.dwProtocol = 0x2;
sioreq.cbPciLength = 8;
HiDWinscard.SCARD_IO_REQUEST rioreq;
rioreq.cbPciLength = 8;
rioreq.dwProtocol = 0x2;
Byte[] receiveBuffer = new Byte[255]; //Receive Buffer in SCardTransmit
int receivebufferlen = 255;
try
{
iRetval = HID.SCardTransmit(m_hCard, ref sioreq, sendBuffer, sendbufferlen, ref rioreq, receiveBuffer, ref receivebufferlen);
if (iRetval == 0)
{
receiveBuffer.CopyTo(rcvBufObj.RcvBuf, 0);
rcvBufObj.RcvBufLen = receivebufferlen;
rcvBufObj.RcvFlag = SCardTransmitFlag.SUCCESS;
}
else
{
_logger.Debug(string.Format("SCardTransmit() Failed. Error Code: {0}.", iRetval.ToString()));
}
}
catch (Exception ex)
{
string sMsg = String.Format("{0} - {1} {2}", MethodBase.GetCurrentMethod().Name, ex.GetType(), ex.Message);
}
return rcvBufObj;
}