

#include "Mifare.h"
#include "RC522Config.h"


//=================================================================================================
/**************************************************************************************************
** 函数原型:    char PiccAuthKey(unsigned char auth_mode,unsigned char *snr,
**                               unsigned char *key,unsigned char addr)
** 函数功能:    验证Mifare卡选择的扇区
** 入口参数:    unsigned char auth_mode     ; 验证模式阿:A密钥/B密钥
**              unsigned char *snr    ; 4字节UID
**              unsigned char *key    ; 6字节密钥
**              unsigned char addr          ; 验证的扇区号
** 出口参数:    -
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccAuthKey(unsigned char auth_mode,unsigned char *snr,
                 unsigned char *key,unsigned char addr)
{
    char status;
    unsigned char RegVal;
	unsigned char SerBuffer[12];	

    ResetInfo();

    SerBuffer[0] = auth_mode;                   // 密钥类型
    SerBuffer[1] = addr;                        // 验证的地址
    memcpy(SerBuffer+2,key,6);                  // 6字节密钥
    memcpy(SerBuffer+8,snr,4);                  // UID
    MInfo.nBytesToSend = 12;
    SetTimeOut(20);
    status = PcdCmd(CMD_AUTHENT, SerBuffer);
    if(status == STATUS_SUCCESS)
    {
      	RegVal = RcGetReg(REG_STATUS2);
        if((RegVal & 0x0f) != 0x08)
            status = STATUS_AUTHENT_ERROR;
    }
    return status;
}
/**************************************************************************************************
** 函数原型:    char PiccRead(unsigned char addr, unsigned char *_data)
** 函数功能:    从指定的块号读出一块数据
** 入口参数:    unsigned char addr          ; 块号
** 出口参数:    unsigned char *_data  ; 读出的数据(16字节)
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccRead(unsigned char addr, unsigned char *_data)
{
   char status = STATUS_SUCCESS;
   //char tmp    = 0;
	unsigned char SerBuffer[16];	

   ResetInfo();
   SerBuffer[0] = MIFARE_READ;
   SerBuffer[1] = addr;
   MInfo.nBytesToSend   = 2;
   SetTimeOut(100);
   status = PcdCmd(CMD_TRANSCEIVE,
                       SerBuffer);

   if (status != STATUS_SUCCESS)
   {
      if (status != STATUS_IO_TIMEOUT )
      {
         if (MInfo.nBitsReceived == 4)
         {
             SerBuffer[0] &= 0x0f;
             if ((SerBuffer[0] & 0x0a) == 0)
             {
                status = STATUS_AUTHENT_ERROR;
             }
             else
             {
                status = STATUS_INVALID_FORMAT;
             }
          }
      }
   }
   else
   {
      if (MInfo.nBytesReceived != 16)
      {
         status = STATUS_ACCESS_DENIED;
      }
      else
      {
         memcpy(_data,SerBuffer,16);
      }
   }
   return status;
}

char MFCheckAck(char Status, unsigned char Rsponse)
{
	if(Status == STATUS_ACK_SUPPOSED)
	{
		if (MInfo.nBitsReceived != 4)
       	{
          	Status = STATUS_BITCOUNT_ERROR;
       	}
       	else
       	{
          	Rsponse &= 0x0f;
           	switch(Rsponse)
           	{
              	case 0x00:
                 	Status = STATUS_AUTHENT_ERROR;
                 	break;
              	case 0x0a:
                 	Status = STATUS_SUCCESS;
                 	break;
              	case 0x01:
                 	Status = STATUS_INVALID_FORMAT;
                 	break;
              	default:
                 	Status = STATUS_OTHER_ERROR;
                 	break;
           	}
       	}
	}
	return Status;
}

/**************************************************************************************************
** 函数原型:    char PiccWrite(unsigned char addr, unsigned char *_data)
** 函数功能:    向指定的扇区写入16字节数据
** 入口参数:    unsigned char addr          ; 块号
**              unsigned char *_data  ; 写入的数据(16字节)
** 出口参数:    
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccWrite( unsigned char addr, unsigned char *_data)
{
    char status = STATUS_SUCCESS;
	unsigned char SerBuffer[16];	

    ResetInfo();
    SerBuffer[0] = MIFARE_WRITE;
    SerBuffer[1] = addr;
    MInfo.nBytesToSend   = 2;
    SetTimeOut(200);
    status = PcdCmd(CMD_TRANSCEIVE,
                        SerBuffer);

    status = MFCheckAck(status, SerBuffer[0]);

    if ( status == STATUS_SUCCESS)
    {

       SetTimeOut(50);

       ResetInfo();
       memcpy(SerBuffer,_data,16);
       MInfo.nBytesToSend   = 16;
       status = PcdCmd(CMD_TRANSCEIVE,
                           SerBuffer);

       status = MFCheckAck(status, SerBuffer[0]);
    }
  	return status;
}

/**************************************************************************************************
** 函数原型:    char PiccULWrite( unsigned char addr,unsigned char *_data)
** 函数功能:    向指定的块写入4字节数据(MF IC U1)
** 入口参数:    unsigned char addr              ; 块号
**              unsigned char *_data      ; 写入的数据(4字节)
** 出口参数:    
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccULWrite( unsigned char addr,unsigned char *_data)
{
	char status = STATUS_SUCCESS;
	unsigned char SerBuffer[6];	

    ResetInfo();
    SerBuffer[0] = PICC_ULWRITE;
    SerBuffer[1] = addr;
	memcpy(&SerBuffer[2],_data,4);
    MInfo.nBytesToSend   = 6;
    
    SetTimeOut(200);
    status = PcdCmd(CMD_TRANSCEIVE,SerBuffer);

	status = MFCheckAck(status, SerBuffer[0]);
	return status;
}
/**************************************************************************************************
** 函数原型:    char PiccValue(unsigned char OperMode,unsigned char addr,
**                             unsigned char *value,unsigned char trans_addr)
** 函数功能:    值块操作函数(增、减或者传输)
** 入口参数:    unsigned char OperMode          ; 操作模式(增、减)
**              unsigned char addr              ; 块号
**              unsigned char *value      ; 操作值块的值
**              unsigned char trans_addr        ; 保存操作结果的块号
** 出口参数:    -
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccValue( unsigned char OperMode,unsigned char addr,
                unsigned char *value,unsigned char trans_addr)
{
   char status = STATUS_SUCCESS;
	unsigned char SerBuffer[4];	

   ResetInfo();
   SerBuffer[0] = OperMode;
   SerBuffer[1] = addr;
   MInfo.nBytesToSend   = 2;
   SetTimeOut(200);
   status = PcdCmd(CMD_TRANSCEIVE,
                       SerBuffer);

   status = MFCheckAck(status, SerBuffer[0]);

     if ( status == STATUS_SUCCESS)
     {
        SetTimeOut(100);
        ResetInfo();
        memcpy(SerBuffer,value,4);
        MInfo.nBytesToSend   = 4;
        status = PcdCmd(CMD_TRANSCEIVE,
                            SerBuffer);

        if (status == STATUS_IO_TIMEOUT)
        {
            status = STATUS_SUCCESS;
        }
        else
        {
            status = STATUS_OTHER_ERROR;
        }
     }
     if ( status == STATUS_SUCCESS)
     {
        ResetInfo();
        SerBuffer[0] = MIFARE_TRANSFER;
        SerBuffer[1] = trans_addr;
        MInfo.nBytesToSend   = 2;
        status = PcdCmd(CMD_TRANSCEIVE,
                            SerBuffer);

        status = MFCheckAck(status, SerBuffer[0]);
     }
   return status;
}




