📄 m500auc.c
字号:
///////////////////////////////////////////////////////////////////////
char M500PcdMfOutSelect(unsigned char type) /* TYPE为MFOUT输出的信号是什么类型 */
{
WriteIO(RegMfOutSelect,type&0x7); /* MFOUTSELECT寄存器(26H)=TYPE--低三位有效 */
return MI_OK;
}
///////////////////////////////////////////////////////////////////////
// Request Command defined in ISO14443(MIFARE)
// Request,Anticoll,Select,return CardType(2 bytes)+CardSerialNo(4 bytes)
// 寻卡,防冲突,选择卡 返回卡类型(2 bytes)+ 卡系列号(4 bytes)
///////////////////////////////////////////////////////////////////////
char M500PiccCommonRequest(unsigned char req_code,unsigned char *atq)
{ /* ATQ=ANSWER TO REQUEST:响应信息,两个字节 */
char idata status = MI_OK;
M500PcdSetTmo(3); /* 计数器工作于模式3 */
WriteIO(RegChannelRedundancy,0x03); /* 通道冗余寄存器置3--奇校验,每个字节后附加一个校验位,无CRC校验 */
ClearBitMask(RegControl,0x08); /* 清加密算法位(09H) */
WriteIO(RegBitFraming,0x07); /* 最后三位为111,表示最后一字节须传送的位数为1(0FH) */
SetBitMask(RegTxControl,0x03); /* TX脚发送被数据调制好的能量载波信号(11H) */
ResetInfo(MInfo); /* 信息接口 */
SerBuffer[0] = req_code; /* REQ_CODE=26H:REQUESTALL, REQ_CODE=52H:REQUESTIDLE, */
MInfo.nBytesToSend = 1;
/* 上面是REQUEST指令相关信息 */
status = M500PcdCmd(PCD_TRANSCEIVE,SerBuffer,&MInfo); /* 执行TRANSCEIVE指令(寻卡--REQUEST) */
if (status) /* 返回标志为1 */
{
*atq = 0; /* 则响应值置0 */
}
else /* 返回标志为0--成功了一半 */
{
if (MInfo.nBitsReceived != 16) /* 如果收到的比特数不是16,则命令执行失败 */
{
*atq = 0; /* 则响应值置0 */
status = MI_BITCOUNTERR; /* 置状态寄存器为比特计数器错 */
}
else
{
status = MI_OK; /* 是16,命令执行成功 */
memcpy(atq,SerBuffer,2); /* 从单片机数据缓冲区中读取响应信号(ATQ) */
}
}
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////
// Cascaded Anti-Collision Command defined in ISO14443(MIFARE)
/* 防冲突 读卡的系列号 MLastSelectedSnr四位的序列号 */
///////////////////////////////////////////////////////////////////
char M500PiccCascAnticoll (unsigned char bcnt,unsigned char *snr)
{ /* BCNT=0--32,比特计数器;SNR=序列号存储缓冲区4个字节; */
char idata status = MI_OK;
char idata snr_in[4];
char idata nbytes = 0;
char idata nbits = 0;
char idata complete = 0;
char idata i = 0;
char idata byteOffset = 0;
unsigned char dummyShift1;
unsigned char dummyShift2;
M500PcdSetTmo(106); /* 初始化计时器--方式106 */
memcpy(snr_in,snr,4); /* 序列号复制 */
WriteIO(RegDecoderControl,0x28); /* 任何在比特碰撞出现之后接收到的信号位进被屏蔽为0,大大简化ISO14443A标准 */
ClearBitMask(RegControl,0x08); /* 清加密算法位(09H) */
complete = 0;
while (!complete && (status == MI_OK) ) /* 如果这两个条件都成立则在此循环 */
{
ResetInfo(MInfo);
WriteIO(RegChannelRedundancy,0x03); /* 通道冗余寄存器置3--奇校验,每个字节后附加一个校验位,无CRC校验 */
nbits = bcnt % 8; /* NBIT=BCNT除以8的余数 */
if(nbits) /* 如果不为0 */
{
WriteIO(RegBitFraming,nbits << 4 | nbits); /* 如果不为0 */
nbytes = bcnt / 8 + 1; /* NBYTES为收到的序列号字节数,要加一 */
if (nbits == 7)
{
MInfo.cmd = PICC_ANTICOLL1;
WriteIO(RegBitFraming,nbits); /* */
}
}
else /* 余数为0 */
{
nbytes = bcnt / 8; /* NBYTES为收到的序列号字节数 */
}
SerBuffer[0] = 0x93; /* 标准选卡命令 */
SerBuffer[1] = 0x20 + ((bcnt/8) << 4) + nbits;
for (i = 0; i < nbytes; i++)
{
SerBuffer[i + 2] = snr_in[i]; /* 序列号输入接口 */
}
MInfo.nBytesToSend = 2 + nbytes; /* 输入字节个数 */
status = M500PcdCmd(PCD_TRANSCEIVE,SerBuffer,&MInfo);
if (nbits == 7)
{ /* 反碰撞处理过程? */
dummyShift1 = 0x00;
for (i = 0; i < MInfo.nBytesReceived; i++)
{
dummyShift2 = SerBuffer[i];
SerBuffer[i] = (dummyShift1 >> (i+1)) | (SerBuffer[i] << (7-i));
dummyShift1 = dummyShift2;
}
MInfo.nBitsReceived -= MInfo.nBytesReceived;
if ( MInfo.collPos ) MInfo.collPos += 7 - (MInfo.collPos + 6) / 9;
}
if ( status == MI_OK || status == MI_COLLERR)
{
if ( MInfo.nBitsReceived != (40 - bcnt) )
{
status = MI_BITCOUNTERR;
}
else
{
byteOffset = 0;
if( nbits != 0 )
{
snr_in[nbytes - 1] = snr_in[nbytes - 1] | SerBuffer[0];
byteOffset = 1;
}
for ( i =0; i < (4 - nbytes); i++)
{
snr_in[nbytes + i] = SerBuffer[i + byteOffset];
}
if (status != MI_COLLERR )
{
dummyShift2 = snr_in[0] ^ snr_in[1] ^ snr_in[2] ^ snr_in[3];
dummyShift1 = SerBuffer[MInfo.nBytesReceived - 1];
if (dummyShift2 != dummyShift1)
{
status = MI_SERNRERR;
}
else
{
complete = 1;
}
}
else
{
bcnt = bcnt + MInfo.collPos - nbits;
status = MI_OK;
}
}
}
}
if (status == MI_OK) /* 如果状态标志成功 */
{
memcpy(snr,snr_in,4); /* 保存序列号 */
}
else
{
memcpy(snr,"0000",4); /* 不成功,则返回0000 */
}
ClearBitMask(RegDecoderControl,0x20); /* 清掉反碰撞位 */
return status; /* 返回状态值 */
}
//////////////////////////////////////////////////////////////////
// Cascaded Select command defined in ISO14443(MIFARE)
/* 选择卡,确定序列号是否大于4字节 */
//////////////////////////////////////////////////////////////////
char M500PiccCascSelect(unsigned char *snr,unsigned char *sak)
{ /* snr为序列号首址, sak为一字节选卡回应值*/
char idata status = MI_OK;
M500PcdSetTmo(106); /* 计时器初始化 */
WriteIO(RegChannelRedundancy,0x0F); /* 通道冗余寄存器置f--16bit crc校验,确定数据帧最后两个字节为crc字节,奇校验,每个字节后附加一个校验位 */
ClearBitMask(RegControl,0x08); /* 清加密算法位(09H) */
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* 送rc500FIFO的相关信息,与命令函数m500pcdcmd()配合 */
ResetInfo(MInfo); /* 给rc500的相关信息,与指令相配合 */
SerBuffer[0] = 0x93; /* 给rc500的相关信息,写入指令(选卡)数据 */
SerBuffer[1] = 0x70; /* 给rc500的相关信息,写入数据 */
memcpy(SerBuffer + 2,snr,4); /* 将原指针snr对应的序列号拷贝到发送缓冲区serbuffer中去 */
SerBuffer[6] = SerBuffer[2] ^ SerBuffer[3] ^ SerBuffer[4] ^ SerBuffer[5]; /* 序号中四字节按位异或得到crc校验字节 */
MInfo.nBytesToSend = 7; /* 给rc500的相关信息,与指令相配合,须发送的字节数 */
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
status = M500PcdCmd(PCD_TRANSCEIVE,SerBuffer,&MInfo); /* 执行命令函数m500pcdcmd(),返回STATUS */
*sak = 0; /* sak选卡回应值先置0 */
if (status == MI_OK) /* 返回值为执行成功标志MI_OK */
{
if (MInfo.nBitsReceived != 8) /* 如果接收到的不是一个字节 */
{
status = MI_BITCOUNTERR; /* 则置标志位为MI_BITCOUNTERR */
}
else /* 如果接收到的是一个字节 */
{
*sak = SerBuffer[0]; /* 则将该值存于SAK中 */
}
}
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////////
// Key loading into the MF RC500's EEPROM
// 将RC500的EEROM中的密钥载入密钥缓冲区,校验卡密码(E2)
///////////////////////////////////////////////////////////////////////
char M500PiccAuthE2( unsigned char auth_mode,unsigned char *snr,
unsigned char keynr,unsigned char block)
/* 入口参数:AUTH_MODE:A/B卡型号,SNR:卡序列号,KEYNR:密钥所在扇区数,BLOCK:密钥所在数据块*/
{
char idata status = MI_OK;
unsigned int e2addr = 0x80 + keynr * 0x18; /* 得出密钥在EEROM中的位置 */
//unsigned char *e2addrbuf = (unsigned char*)&e2addr;
unsigned char *e2addrbuf;
e2addrbuf = (unsigned char *)&e2addr;
if (auth_mode == PICC_AUTHENT1B) /* 如果是B类卡 */
{
e2addr += 12; /* 密钥地址加12 */
}
FlushFIFO();
ResetInfo(MInfo);
memcpy(SerBuffer,e2addrbuf,2); /* 从E2ADDRBUF中取出存密钥的EEROM地址(两个字节) */
SerBuffer[2] = SerBuffer[0];
SerBuffer[0] = SerBuffer[1];
SerBuffer[1] = SerBuffer[2];
MInfo.nBytesToSend = 2;
if ((status=M500PcdCmd(PCD_LOADKEYE2,SerBuffer,&MInfo)) == MI_OK)
{ /* 下载密钥成功 */
status = M500PiccAuthState(auth_mode,snr,block);
} /* 三轮认证 */
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////////
// Authentication key coding
/* 将密钥换成标准密钥形式 */
///////////////////////////////////////////////////////////////////////
char M500HostCodeKey( unsigned char *uncoded, unsigned char *coded)
{
char idata status = MI_OK;
unsigned char idata cnt = 0;
unsigned char idata ln = 0;
unsigned char idata hn = 0;
for (cnt = 0; cnt < 6; cnt++) /* 密钥由6字节转成12字节 */
{
ln = uncoded[cnt] & 0x0F; /* 密钥一字节的低四位 */
hn = uncoded[cnt] >> 4; /* 密钥一字节的高四位 */
coded[cnt * 2 + 1] = (~ln << 4) | ln;
coded[cnt * 2 ] = (~hn << 4) | hn;
}
return MI_OK;
}
///////////////////////////////////////////////////////////////////
// Authentication with direct key loading from the uC
/*直接校验从单片机载入的密码,针对卡中的某一块数据来说(16块,每块64字节) */
//////////////////////////////////////////////////////////////////
char M500PiccAuthKey( unsigned char auth_mode,
unsigned char *snr,
unsigned char *keys,
unsigned char block)
{
char idata status = MI_OK;
//PcdSetTmo(2);
FlushFIFO();
ResetInfo(MInfo);
memcpy(SerBuffer,keys,12);
MInfo.nBytesToSend = 12;
if ((status=M500PcdCmd(PCD_LOADKEY,SerBuffer,&MInfo)) == MI_OK)
{ /* 直接从单片机载入密码到FIFO,然后再载入密钥缓冲区 */
status = M500PiccAuthState(auth_mode,snr,block);
} /* 三轮认证 */
return status;
} /* 返回状态值 */
///////////////////////////////////////////////////////////////////////
/* 三轮认证函数 */
///////////////////////////////////////////////////////////////////////
char M500PiccAuthState( unsigned char auth_mode,unsigned char *snr,unsigned char block)
{ /* 入口参数:AUTH_MODE:A/B卡型号,SNR:卡序列号,BLOCK:要访问所在数据块*/
char idata status = MI_OK;
unsigned char idata i = 0;
status = ReadIO(RegErrorFlag); /* 读RC500中的错误标志寄存器 */
if (status != MI_OK) /* 载入密钥不成功 */
{
if (status & 0x40)
{
status = MI_KEYERR; /* 密钥出错标志 */
}
else
{
status = MI_AUTHERR; /* 认证出错标志 */
}
}
else /* 载入密钥成功 */
{ /* 三轮认证开始 */
SerBuffer[0] = auth_mode;
SerBuffer[1] = block;
memcpy(SerBuffer + 2,snr,4);
ResetInfo(MInfo);
MInfo.nBytesToSend = 6;
/* 上面为认证命令1的入口参数:卡型,要访问的数据块,序列号,相关流动信息,要发送的字节数 */
if ((status = M500PcdCmd(PCD_AUTHENT1,SerBuffer,&MInfo)) == MI_OK)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -