
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/kthread.h>
#include <linux/freezer.h> 
#include <linux/random.h>
#include <linux/delay.h>
#include "si522a.h"

#define NFC_DRIVER_NAME "nfc_si522a"
#define NFC_DEVICE_NAME "nfc_dev"
struct nfc_data {
    struct i2c_client *client;
    struct cdev cdev;
    dev_t devno;
    struct class *cls;
    
	u32 irq_flags;
	struct gpio_desc *irq_gpio;
	struct gpio_desc *rst_gpio;	    
	struct gpio_desc *pwr_gpio;	    
    
    u8 data[128];
    int data_len;
	u8 datatype;
	u8 status;
    bool card_present;

    struct fasync_struct *async_queue;
    wait_queue_head_t read_wait;
    struct mutex lock;
	struct task_struct *task;
	u8  taskrunn;
};

static struct nfc_data *g_nfc = NULL;
#if 1
uint8_t Si522_IRQ_flagA ;
unsigned char gdata[128]={0};
int gdatalen = 0;
unsigned char gdatatype = 0;
unsigned char dataserio = 0;


typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;

#define READ   0
#define WRITE  1
#define delay_us(n)   usleep_range(n, 600)
#define delay_ms   msleep
#define printf printk
unsigned char gATQA[2]={0};  //卡类型
unsigned char  UIDB[10];//放置B 卡ID
unsigned char  UIDA[10];//放置A 卡ID
unsigned char gSAK = 0;
unsigned char CardReadBuf[16] = {0};
unsigned char CardWriteBuf[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned char DefaultKeyABuf[10] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

static int nfc_write_reg(struct nfc_data *nfc, u8 reg, u8 val);
static int nfc_read_reg(struct nfc_data *nfc, u8 reg, u8 *val);

void I_SI522_IO_Write(unsigned char RegAddr,unsigned char value)
{
	if (g_nfc == NULL) {
		//printk(">>>sjl I_SI522_IO_Write error\n");
		return;
	}
    if (nfc_write_reg(g_nfc, RegAddr,value) < 0) {
		//printk(">>>sjl I_SI522_IO_Write error 111\n");
	}
}

unsigned char I_SI522_IO_Read(unsigned char RegAddr)
{
	unsigned char val;
	
	if (g_nfc == NULL) {
		//printk(">>>sjl I_SI522_IO_Read error\n");
		return -1;
	}
	if (nfc_read_reg(g_nfc, RegAddr, &val) < 0) {
		//printk(">>>sjl I_SI522_IO_Read error 111\n");
		return -1;		
	}	
    return val;
}
/////////////////////////////////////////////////////////////////////
//开启天线  
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn(void)
{
    unsigned char i;
    i = I_SI522_IO_Read(TxControlReg);
    I_SI522_IO_Write(TxControlReg, i | 0x03);
    delay_ms(1);
}

/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
	I_SI522_ClearBitMask(TxControlReg, 0x03);
}

/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{
    unsigned char i,n;
    I_SI522_ClearBitMask(DivIrqReg,0x04);
    I_SI522_IO_Write(CommandReg,PCD_IDLE);
    I_SI522_SetBitMask(FIFOLevelReg,0x80);
    for (i=0; i<len; i++)
    {   I_SI522_IO_Write(FIFODataReg, *(pIndata+i));   }
    I_SI522_IO_Write(CommandReg, PCD_CALCCRC);
    i = 0xFF;
    do 
    {
        n = I_SI522_IO_Read(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));
    pOutData[0] = I_SI522_IO_Read(CRCResultRegL);
    pOutData[1] = I_SI522_IO_Read(CRCResultRegH);
}


unsigned char aaa = 0;


/////////////////////////////////////////////////////////////////////
//功    能：通过RC522和ISO14443卡通讯
//参数说明：Command[IN]:RC522命令字
//          pInData[IN]:通过RC522发送到卡片的数据
//          InLenByte[IN]:发送数据的字节长度
//          pOutData[OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
//status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
char PcdComMF522(unsigned char Command, 
                 unsigned char *pInData, 
                 unsigned char InLenByte,
                 unsigned char *pOutData, 
                 unsigned int *pOutLenBit)
{
    char status = MI_ERR;
    unsigned char irqEn   = 0x00;
    unsigned char waitFor = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;
    switch (Command)
    {
        case PCD_AUTHENT:
			irqEn   = 0x12;
			waitFor = 0x10;
			break;
		case PCD_TRANSCEIVE:
			irqEn   = 0x77;
			waitFor = 0x30;
			break;
		default:
			break;
    }
   
    //I_SI522_IO_Write(ComIEnReg,irqEn|0x80);
    I_SI522_ClearBitMask(ComIrqReg,0x80);
    I_SI522_IO_Write(CommandReg,PCD_IDLE);
    I_SI522_SetBitMask(FIFOLevelReg,0x80);
    
    for (i=0; i<InLenByte; i++)
    {   
		I_SI522_IO_Write(FIFODataReg, pInData[i]);    
	}
    I_SI522_IO_Write(CommandReg, Command);
   
    if (Command == PCD_TRANSCEIVE)
    {    
		I_SI522_SetBitMask(BitFramingReg,0x80);  
	}
    
    //i = 600;//根据时钟频率调整，操作M1卡最大等待时间25ms
	i = 2000;
    do 
    {
        n = I_SI522_IO_Read(ComIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitFor));
    I_SI522_ClearBitMask(BitFramingReg,0x80);

    if (i!=0)
    {   
		aaa = I_SI522_IO_Read(ErrorReg);
		
        if(!(I_SI522_IO_Read(ErrorReg)&0x1B))
        {
            status = MI_OK;
            if (n & irqEn & 0x01)
            {   status = MI_NOTAGERR;   }
            if (Command == PCD_TRANSCEIVE)
            {
               	n = I_SI522_IO_Read(FIFOLevelReg);
              	lastBits = I_SI522_IO_Read(ControlReg) & 0x07;
                if (lastBits)
                {   
					*pOutLenBit = (n-1)*8 + lastBits;   
				}
                else
                {   
					*pOutLenBit = n*8;   
				}
                if (n == 0)
                {   
					n = 1;    
				}
                if (n > MAXRLEN)
                {   
					n = MAXRLEN;   
				}
                for (i=0; i<n; i++)
                {   
					pOutData[i] = I_SI522_IO_Read(FIFODataReg);    
				}
            }
        }
        else
        {   
			status = MI_ERR;   
		}
        
    }
   
    I_SI522_SetBitMask(ControlReg,0x80);           // stop timer now
    I_SI522_IO_Write(CommandReg,PCD_IDLE); 
    return status;
}
                     
/////////////////////////////////////////////////////////////////////
//功    能：寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]：卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
	char status;  
	unsigned int unLen;
	unsigned char ucComMF522Buf[MAXRLEN]; 

	I_SI522_ClearBitMask(Status2Reg,0x08);
	I_SI522_IO_Write(BitFramingReg,0x07);
	I_SI522_SetBitMask(TxControlReg,0x03);
 
	ucComMF522Buf[0] = req_code;

	status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
	if ((status == MI_OK) && (unLen == 0x10))
	{    
		*pTagType     = ucComMF522Buf[0];
		*(pTagType+1) = ucComMF522Buf[1];
	}
	else
	{   
		status = MI_ERR;   
	}
   
	return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：防冲撞
//参数说明: pSnr[OUT]:卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////  
char PcdAnticoll(unsigned char *pSnr, unsigned char anticollision_level)
{
    char status;
    unsigned char i,snr_check=0;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    

    I_SI522_ClearBitMask(Status2Reg,0x08);
    I_SI522_IO_Write(BitFramingReg,0x00);
    I_SI522_ClearBitMask(CollReg,0x80);
 
    ucComMF522Buf[0] = anticollision_level;
    ucComMF522Buf[1] = 0x20;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if (status == MI_OK)
	{
		for (i=0; i<4; i++)
		{   
			*(pSnr+i)  = ucComMF522Buf[i];
			snr_check ^= ucComMF522Buf[i];
		}
		if (snr_check != ucComMF522Buf[i])
   		{   
			status = MI_ERR;    
		}
    }
    
    I_SI522_SetBitMask(CollReg,0x80);
    return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：选定卡片
//参数说明: pSnr[IN]:卡片序列号，4字节
//返    回: 成功返回MI_OK
////////////////////////////////////////////////////////////////////
char PcdSelect (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);                                                                      
  
    I_SI522_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

char PcdSelect1 (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    I_SI522_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

char PcdSelect2 (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL2;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    I_SI522_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

char PcdSelect3 (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL2;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    I_SI522_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：命令卡片进入休眠状态
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_HALT;
    ucComMF522Buf[1] = 0;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥 
//          addr[IN]：块地址
//          pKey[IN]：密码
//          pSnr[IN]：卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////               
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = auth_mode;
    ucComMF522Buf[1] = addr;
	memcpy(&ucComMF522Buf[2], pKey, 6); 
	memcpy(&ucComMF522Buf[8], pSnr, 6); 
    
    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if ((status != MI_OK) || (!(I_SI522_IO_Read(Status2Reg) & 0x08)))
    {
		status = MI_ERR;   
	}
    
    return status;
}



/////////////////////////////////////////////////////////////////////
//功    能：读取M1卡一块数据
//参数说明: addr[IN]：块地址
//          pData[OUT]：读出的数据，16字节
//返    回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////// 
char PcdRead(unsigned char addr,unsigned char *pData)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_READ;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
   
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    if ((status == MI_OK) && (unLen == 0x90))
   	{   
		memcpy(pData, ucComMF522Buf, 16);   
	}
    else
    {   
		status = MI_ERR;   
	}
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：写数据到M1卡一块
//参数说明: addr[IN]：块地址
//          pData[IN]：写入的数据，16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////                  
char PcdWrite(unsigned char addr,unsigned char *pData)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_WRITE;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   
		status = MI_ERR;   
	}
        
    if (status == MI_OK)
    {
        memcpy(ucComMF522Buf, pData, 16);
        CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);

        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        {   
			status = MI_ERR;   
		}
    }
    
    return status;
}

/*=================================
 函数功能：循环读取A卡UID

=================================*/
void PCD_SI522_TypeA(void)
{
	//LED_OperaSuccess();	// LED indicator
	
	while(1)
	{
		PCD_SI522_TypeA_GetUID();		//读A卡
		
		//PCD_SI522_TypeA_rw_block();		//读A卡扇区

		delay_ms(500);
	}
}


/*===============================
 函数功能：读A卡初始化配置

 ================================*/
void PCD_SI522_TypeA_Init(void)
{
	//I_SI522_IO_Init();	// Initializes the interface with Si522	
	delay_ms(500);
	
	I_SI522_ClearBitMask(Status2Reg, 0x08);  
	// Reset baud rates
	I_SI522_IO_Write(TxModeReg, 0x00);
	I_SI522_IO_Write(RxModeReg, 0x00);
	// Reset ModWidthReg
	I_SI522_IO_Write(ModWidthReg, 0x26);
	// RxGain:110,43dB by default;
	I_SI522_IO_Write(RFCfgReg, RFCfgReg_Val);
	// When communicating with a PICC we need a timeout if something goes wrong.
	// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
	// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
	I_SI522_IO_Write(TModeReg, 0x80);// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
	I_SI522_IO_Write(TPrescalerReg, 0xa9);// TPreScaler = TModeReg[3..0]:TPrescalerReg
	I_SI522_IO_Write(TReloadRegH, 0x03); // Reload timer 
	I_SI522_IO_Write(TReloadRegL, 0xe8); // Reload timer 
	I_SI522_IO_Write(TxASKReg, 0x40);	// Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
	I_SI522_IO_Write(ModeReg, 0x3D);	// Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
	I_SI522_IO_Write(RxSelReg, 0x86);	// RxWait=6, internal receiver setting
	I_SI522_IO_Write(CommandReg, 0x00);  // Turn on the analog part of receiver   

	PcdAntennaOn();
}

char PCD_SI522_TypeA_GetUID(void)
{
	unsigned char ATQA[2];
	unsigned char UID[12];
	unsigned char SAK = 0;
	unsigned char UID_complate1 = 0;
	unsigned char UID_complate2 = 0;

	//printf("\r\n >>sjl 22 Test_Si522_GetUID");
	I_SI522_IO_Write(RFCfgReg, RFCfgReg_Val); //复位接收增益
	gdatalen = -1;
	memset(gdata, 0, 128);
	gdatatype = 0;
		
	//寻卡
	if( PcdRequest( PICC_REQIDL, ATQA) != MI_OK )  //寻天线区内未进入休眠状态的卡，返回卡片类型 2字节	
	{
		I_SI522_IO_Write(RFCfgReg, 0x48);
		if(PcdRequest( PICC_REQIDL, ATQA) != MI_OK)
		{
			I_SI522_IO_Write(RFCfgReg, 0x58);
			if(PcdRequest( PICC_REQIDL, ATQA) != MI_OK)
			{	
				//printf("\r\n>>sjl Request:fail");
				return 1;
			}
			else
			{
				//printf("\r\n>>sjl Request1:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
			}	
		}
		else
		{
			//printf("\r\n>>sjl Request2:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
		}		
	}
	else
	{
		//printf("\r\n>>sjl Request3:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
	}
	if (dataserio == 0) {
		gdata[0] = ATQA[0];
		gdata[1] = ATQA[1];
		gdatatype = 1;
		gdatalen = 2;
	}
	
//UID长度=4
	//Anticoll 冲突检测 level1
	if(PcdAnticoll(UID, PICC_ANTICOLL1)!= MI_OK) 
	{
		//printf("\r\n>>sjl Anticoll1:fail");
		return 1;		
	}
	else
	{
		if(PcdSelect1(UID,&SAK)!= MI_OK)
		{
			//printf("\r\n>>sjl Select1:fail");
			return 1;		
		}
		else
		{
			//printf("\r\n >>sjl Select1:ok  SAK1:%02x",SAK);
			if(SAK&0x04)                         
			{
				UID_complate1 = 0;
				
				//UID长度=7
				if(UID_complate1 == 0)    
				{
					//Anticoll 冲突检测 level2
					if(PcdAnticoll(UID+4, PICC_ANTICOLL2)!= MI_OK) 
					{
						//printf("\r\n >>sjl Anticoll2:fail");
						return 1;		
					}
					else
					{
						if(PcdSelect2(UID+4,&SAK)!= MI_OK)  
						{
							//printf("\r\n>>sjl Select2:fail");
							return 1;		
						}
						else
						{
							//printf("\r\n>>sjl Select2:ok  SAK2:%02x",SAK);
							if(SAK&0x04)                         
							{
								UID_complate2 = 0;
								
								//UID长度=10
								if(UID_complate2 == 0)     
								{
									//Anticoll 冲突检测 level3
									if(PcdAnticoll(UID+8, PICC_ANTICOLL3)!= MI_OK) 
									{
										//printf("\r\n>>sjl Anticoll3:fail");
										return 1;		
									}
									else
									{
										if(PcdSelect3(UID+8,&SAK)!= MI_OK)  
										{
											//printf("\r\n>>sjl Select3:fail");
											return 1;		
										}
										else
										{
											//printf("\r\n>>sjl Select3:ok  SAK3:%02x",SAK);
											
											if(SAK&0x04)                          
											{
//												UID_complate3 = 0;
												return 1;
											}
											else 
											{
	//											UID_complate3 = 1;                   
												//printf("\r\n>>sjl Anticoll3:ok  UID:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
												//UID[1],UID[2],UID[3],UID[5],UID[6],UID[7],UID[8],UID[9],UID[10],UID[11]);	
												if (dataserio == 2) {
													gdatalen = 10;
													memcpy(gdata, &UID[1], 3);
													memcpy(&gdata[3], &UID[5], 3);
													memcpy(&gdata[6], &UID[8], 4);
												}
											}					
										}							
									}
								}
							}
							else 
							{
								UID_complate2 = 1;  
								if (dataserio == 2) {	
									gdatalen = 7;	
									memcpy(gdata, &UID[1], 7);								
								}
								//printf("\r\n>>sjl Anticoll2:ok  UID:%02x %02x %02x %02x %02x %02x %02x",
								//UID[1],UID[2],UID[3],UID[4],UID[5],UID[6],UID[7]);
							}	
						}			
					}
				}
			}
			else 
			{
				UID_complate1 = 1;   
				if (dataserio == 2) {
					gdatalen = 4;	
					memcpy(gdata, UID, 4);	
				}				
				//printf("\r\n>>sjl Anticoll1:ok  UID:%02x %02x %02x %02x",UID[0],UID[1],UID[2],UID[3]);
			}
		}		
	}
	//Halt
//	if(PcdHalt() != MI_OK)
//	{
//		printf("\r\nHalt:fail");
//		return 1;		
//	}
//	else
//	{
//		printf("\r\nHalt:ok");
//	}	
	if (dataserio == 1) {
		gdata[0] = SAK;
		gdatalen = 1;
		gdatatype = 2;
	}
	dataserio++;
	dataserio = dataserio%3;
	delay_us(100);
	return 0;
}

char PCD_SI522_TypeA_rw_block(void)
{
	unsigned char ATQA[2];
	unsigned char UID[12];
	unsigned char SAK = 0;
	unsigned char CardReadBuf[16] = {0};
	unsigned char CardWriteBuf[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
	unsigned char DefaultKeyABuf[10] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
	unsigned char i=0;
	
	printf("\r\n\r\nTest_Si522_GetCard");
	
	//request 寻卡
	if( PcdRequest( PICC_REQIDL, ATQA) != MI_OK )  //寻天线区内未进入休眠状态的卡，返回卡片类型 2字节	
	{
		printf("\r\nRequest:fail");
		return 1;		
	}
	else
	{
		printf("\r\nRequest:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
	}
	

	//Anticoll 冲突检测
	if(PcdAnticoll(UID, PICC_ANTICOLL1)!= MI_OK)
	{		
		printf("\r\nAnticoll:fail");
		return 1;		
	}
	else
	{	
		printf("\r\nAnticoll:ok  UID:%02x %02x %02x %02x",UID[0],UID[1],UID[2],UID[3]);
	}
	
	//Select 选卡
	if(PcdSelect1(UID,&SAK)!= MI_OK)
	{
		printf("\r\nSelect:fail");
		return 1;		
	}
	else
	{
		printf("\r\nSelect:ok  SAK:%02x",SAK);
	}

	//Authenticate 验证密码
	if(PcdAuthState( PICC_AUTHENT1A, 4, DefaultKeyABuf, UID ) != MI_OK )
	{
		printf("\r\nAuthenticate:fail");
		return 1;		
	}
	else
	{
		printf("\r\nAuthenticate:ok");
	}

	//读BLOCK原始数据
	if( PcdRead( 4, CardReadBuf ) != MI_OK )
	{
		printf("\r\nPcdRead:fail");
		return 1;		
	}
	else
	{
		printf("\r\nPcdRead:ok  ");
		for(i=0;i<16;i++)
		{
			printf(" %02x",CardReadBuf[i]);
		}
	}

	//产生随机数
	for(i=0;i<16;i++) {
		unsigned char data;
		get_random_bytes(&data, 1);
		CardWriteBuf[i] = data;
	}
	//写BLOCK 写入新的数据
	if( PcdWrite( 4, CardWriteBuf ) != MI_OK )
	{
		printf("\r\nPcdWrite:fail");
		return 1;	
	}
	else
	{
		printf("\r\nPcdWrite:ok  ");
		for(i=0;i<16;i++)
		{
			printf(" %02x",CardWriteBuf[i]);
		}
	}
		
	//读BLOCK 读出新写入的数据
	if( PcdRead( 4, CardReadBuf ) != MI_OK )
	{
		printf("\r\nPcdRead:fail");
		return 1;		
	}
	else
	{
		printf("\r\nPcdRead:ok  ");
		for(i=0;i<16;i++)
		{
			printf(" %02x",CardReadBuf[i]);
		}
	}
		
//	//Halt
//	if(PcdHalt() != MI_OK)
//	{
//		printf("\r\nHalt:fail");
//		return 1;		
//	}
//	else
//	{
//		printf("\r\nHalt:ok");
//	}	
	
	return 0;
}

//***********************************//修改新增内容

/*
 * 函数名：PcdReset
 * 描述  ：复位RC522 
 * 输入  ：无
 * 返回  : 无
 * 调用  ：外部调用
 */
void PcdReset ( void )
{
	//hard reset
//	HAL_GPIO_WritePin(S52_NRSTPD_GPIO_Port,S52_NRSTPD_Pin,GPIO_PIN_RESET);
//	delay_us(100);
//	HAL_GPIO_WritePin(S52_NRSTPD_GPIO_Port,S52_NRSTPD_Pin,GPIO_PIN_SET);
//	delay_us(100);
	
	I_SI522_IO_Write(CommandReg, 0x0f);			//向CommandReg 写入 0x0f	作用是使RC522复位
	while(I_SI522_IO_Read(CommandReg) & 0x10 );	//Powerdown位为0时，表示RC522已准备好
	delay_us(100);
}


void Pcd_Hard_Reset(void)
{
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 0);
	}

	delay_ms(50);
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 1);
	}
	delay_ms(5);
}

void PcdPowerdown (void)
{
}


//SI522_interfaces
void I_SI522_ClearBitMask(unsigned char reg,unsigned char mask)  
{
	char tmp = 0x00;
	tmp = I_SI522_IO_Read(reg);
	I_SI522_IO_Write(reg, tmp & ~mask);  // clear bit mask
} 

void I_SI522_SetBitMask(unsigned char reg,unsigned char mask)  
{
	char tmp = 0x00;
	tmp = I_SI522_IO_Read(reg);
	I_SI522_IO_Write(reg,tmp | mask);  // set bit mask
}

void I_SI522_SiModifyReg(unsigned char RegAddr, unsigned char ModifyVal, unsigned char MaskByte)
{
	unsigned char RegVal;
	RegVal = I_SI522_IO_Read(RegAddr);
	if(ModifyVal)
	{
			RegVal |= MaskByte;
	}
	else
	{
			RegVal &= (~MaskByte);
	}
	I_SI522_IO_Write(RegAddr, RegVal);
}

#else
uint8_t PCD_IRQ_flagA ;
unsigned char ACDConfigRegK_Val ;
unsigned char ACDConfigRegC_Val ;
unsigned char flag_read_ic_ok ;
unsigned char gdata[128]={0};
int gdatalen = 0;
unsigned char gdatatype = 0;


typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;

#define READ   0
#define WRITE  1
#define delay_us(n)   usleep_range(n, 600)
#define delay_ms   msleep
#define printf printk
unsigned char ATQA[2]={0};  //卡类型
unsigned char  UIDB[10];//放置B 卡ID
unsigned char  UIDA[10];//放置A 卡ID
	unsigned char SAK = 0;
	unsigned char CardReadBuf[16] = {0};
	unsigned char CardWriteBuf[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
	unsigned char DefaultKeyABuf[10] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

static int nfc_write_reg(struct nfc_data *nfc, u8 reg, u8 val);
static int nfc_read_reg(struct nfc_data *nfc, u8 reg, u8 *val);
void SetTimeOut(unsigned int microseconds);
//////////////////////////////////////////////////////////////////

void I_SI522A_IO_Write(unsigned char RegAddr,unsigned char value)
{
	if (g_nfc == NULL) {
		printk(">>>sjl I_SI522A_IO_Write error\n");
		return;
	}
    if (nfc_write_reg(g_nfc, RegAddr,value) < 0) {
		printk(">>>sjl I_SI522A_IO_Write error 111\n");
	}
}

unsigned char I_SI522A_IO_Read(unsigned char RegAddr)
{
	unsigned char val;
	
	if (g_nfc == NULL) {
		printk(">>>sjl I_SI522A_IO_Read error\n");
		return -1;
	}
	if (nfc_read_reg(g_nfc, RegAddr, &val) < 0) {
		printk(">>>sjl I_SI522A_IO_Read error 111\n");
		return -1;		
	}	
    return val;
}

////////////////////////////////////////////////////////////////
#define	ISO14443B_ANTICOLLISION                  0x05
#define	ISO14443B_ATTRIB                         0x1D
#define	ISO14443B_HLTB                           0x50

#define FSDI 8 //Frame Size for proximity coupling Device, in EMV test. ���֤����FSDI = 8

#define	TP_FWT_302us	2048
#define TP_dFWT	192 

unsigned char  g_fwi = 4;//frame waiting time integer

//////////////////////////////////////////////////////////////////////
// ����ԭ��:    char pcdrequestb(u8 req_code, u8 AFI, u8 N, u8 *ATQB)
// ��������:    B�Ϳ�����
// ��ڲ���:    req_code				// �������	ISO14443_3B_REQIDL 0x00 -- ���еĿ�
//										//			ISO14443_3B_REQALL 0x08 -- ���еĿ�
//				AFI						// Ӧ�ñ�ʶ����0x00��ȫѡ
//				N						// ʱ϶����,ȡֵ��Χ0--4��
// ���ڲ���:    *ATQB					// ����Ӧ��11�ֽ�
// �� �� ֵ:    STATUS_SUCCESS -- �ɹ�������ֵ -- ʧ�ܡ�
// ˵    ��:	-   
//////////////////////////////////////////////////////////////////////
uint8_t PcdRequestB(uint8_t req_code, uint8_t AFI, uint8_t N, uint8_t *ATQB)
{
		uint8_t  status = MI_ERR;
				
		unsigned int   unLen;
		uint8_t   ucComMF522Buf[MAXRLEN]; 
		
		SetTimeOut(1);
		
		ucComMF522Buf[0] = ISO14443B_ANTICOLLISION;
		ucComMF522Buf[1] = AFI;
		ucComMF522Buf[2] = (req_code & 0x00) | (N&0x07);
		status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,3,ucComMF522Buf,&unLen);
	
		if (status !=  MI_OK && status != MI_NOTAGERR)
		{   
				status = MI_COLLERR;   
		}
		if (status == MI_OK && unLen != 96)
		{   
				status = MI_COM_ERR;   
		}
		if (status == MI_OK&&ucComMF522Buf[0]==0x50) 
		{	
				memcpy(ATQB, &ucComMF522Buf[0], 16);
        SetTimeOut(ATQB[11]>>4); // set FWT 
			g_fwi = (ATQB[11]>>4);  //֡�ȴ�ʱ��������4λ��
    }
    return status;
}                      


//////////////////////////////////////////////////////////////////////
//SLOT-MARKER
//////////////////////////////////////////////////////////////////////
uint8_t PcdSlotMarker(uint8_t N, uint8_t *ATQB)
{
    uint8_t status;
		unsigned int   unLen;
		uint8_t   ucComMF522Buf[MAXRLEN]; 

		SetTimeOut(5);

    if(!N || N>15)
		{
			status = MI_WRONG_PARAMETER_VALUE;	
    }
		else
    {
			ucComMF522Buf[0] = 0x05 |(N << 4);
			status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);

			if (status != MI_OK && status != MI_NOTAGERR)
			{   
				status = MI_COLLERR;   
			}
			if (status == MI_OK && unLen != 96)
			{   
			status = MI_COM_ERR;   
			}
			if (status == MI_OK) 
			{	
				memcpy(ATQB, &ucComMF522Buf[0], 16);
				SetTimeOut(ATQB[11]>>4); // set FWT 
				g_fwi = ATQB[11]>>4;
			} 	
    }
    return status;
}                      

            
//////////////////////////////////////////////////////////////////////
//ATTRIB
// ����ԭ��:    INchar PcdAttriB(u8 *PUPI, u8 pro_type, u8 CID, u8 *answer)
//
// ��������:    ѡ��PICC
// ��ڲ���:    u8 *PUPI					// 4�ֽ�PICC��ʶ��
//				u8 dsi_dri					// PCD<-->PICC ����ѡ��
//				u8 pro_type					// ֧�ֵ�Э�飬�������Ӧ�е�ProtocolTypeָ��
// �� �� ֵ:    MI_OK -- �ɹ�������ֵ -- ʧ�ܡ�
// ˵    ��:	-
//////////////////////////////////////////////////////////////////////
uint8_t PcdAttriB(uint8_t *PUPI, uint8_t dsi_dri, uint8_t pro_type, uint8_t CID, uint8_t *answer)
{
    uint8_t  status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN]; 
	
		SetTimeOut(g_fwi);
		//pro_type =pro_type;
		ucComMF522Buf[0] = ISO14443B_ATTRIB;
		memcpy(&ucComMF522Buf[1], PUPI, 4);
		ucComMF522Buf[5] = 0x00;
		ucComMF522Buf[6] = ((dsi_dri << 4) | FSDI);;
		ucComMF522Buf[7] = 0x01;
		ucComMF522Buf[8] = (CID & 0x0f);
	
    I_SI522A_SetBitMask(0X1E, BIT7 | BIT6); //EOF SOF required

    
		status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    if (status == MI_OK)
    {	
    	*answer = ucComMF522Buf[0];
    } 	
    return status;
} 
//////////////////////////////////////////////////////////////////////
//��ȡB�Ϳ�ID
//////////////////////////////////////////////////////////////////////
uint8_t GetIdcardNum(uint8_t *pid)
{
    uint8_t  status;

		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];
	
		ucComMF522Buf[0] =0x00; //ISO14443B_ANTICOLLISION;     	       // APf code
    ucComMF522Buf[1] =0x36;// AFI;                // 
    ucComMF522Buf[2] =0x00; //((req_code<<3)&0x08) | (N&0x07);  // PARAM
		ucComMF522Buf[3] =0x00;
		ucComMF522Buf[4] =0x08;
 
		status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,5,ucComMF522Buf,&unLen);
    if (status == MI_OK) 
    {	
    	memcpy(pid, &ucComMF522Buf[0], 10);
    } 
    return status;
}       

//////////////////////////////////////////////////////////////////////
// ����ԭ��:    char pcd_halt_b(u8 *PUPI)
// ��������:    ����
// ��ڲ���:    INT8U *pPUPI					// 4�ֽ�PICC��ʶ��
// ���ڲ���:    -
// �� �� ֵ:    MI_OK -- �ɹ�������ֵ -- ʧ�ܡ�//////////////////////////////////////////////////////////////////////
uint8_t PcdHaltB(uint8_t *PUPI)
{
    uint8_t  status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];
	
    SetTimeOut(g_fwi);																									

    ucComMF522Buf[0] = ISO14443B_ATTRIB;
    memcpy(&ucComMF522Buf[1], PUPI, 4);
	
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,5,ucComMF522Buf,&unLen);

    return status;
}   


/**
 ****************************************************************
 * @brief select_sr() 
 *
 * ����ײ����
 * @param: 
 * @param: 
 * @return: status ֵΪMI_OK:�ɹ�
 * @retval: chip_id  �õ���SR��Ƭ��chip_id
 ****************************************************************
 */
uint8_t SelectSr(uint8_t *chip_id)
{
		uint8_t status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];

    SetTimeOut(5);

    ucComMF522Buf[0] = 0x06;     	       //initiate card
    ucComMF522Buf[1] = 0;                
    
		status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
 
    if (status!=MI_OK && status!=MI_NOTAGERR) 
    {   
				status = MI_COLLERR;       // collision occurs
		}          
    if(unLen != 8)
    {   
				status = MI_COM_ERR;  
		}   
    if (status == MI_OK)
    {	
        SetTimeOut(5);

        ucComMF522Buf[1] = ucComMF522Buf[0];     	       
        ucComMF522Buf[0] = 0x0E;                 // Slect card
          
				status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
        if (status!=MI_OK && status!=MI_NOTAGERR)  // collision occurs
        {   
						status = MI_COLLERR; 						// collision occurs
				}               
        if (unLen != 8) 
        {   
						status = MI_COM_ERR;   
				}
        if (status == MI_OK)
        { 
						*chip_id = ucComMF522Buf[0]; 
				}
    } 	
    return status;
}  

//////////////////////////////////////////////////////////////////////
//SR176������
//////////////////////////////////////////////////////////////////////
uint8_t ReadSr176(uint8_t addr, uint8_t *readdata)
{
    uint8_t status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];
	
    SetTimeOut(5);
	
    ucComMF522Buf[0] = 0x08;
    ucComMF522Buf[1] = addr;
  
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if ((status==MI_OK) && (unLen!=16))
    {   
				status = MI_BITCOUNTERR;   
		}
    if (status == MI_OK)
    {
        *readdata     = ucComMF522Buf[0];
        *(readdata+1) = ucComMF522Buf[1];
    }
    return status;  
}  
//////////////////////////////////////////////////////////////////////
//SR176��д��
//////////////////////////////////////////////////////////////////////
uint8_t WriteSr176(uint8_t addr, uint8_t *writedata)
{
    uint8_t status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];

    SetTimeOut(5);
	
    ucComMF522Buf[0] = 9;
    ucComMF522Buf[1] = addr;
    ucComMF522Buf[2] = *writedata;
    ucComMF522Buf[3] = *(writedata+1);

		status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    return status;  
}      

  	
//////////////////////////////////////////////////////////////////////
//SR176��������
//////////////////////////////////////////////////////////////////////
uint8_t ProtectSr176(uint8_t lockblock)
{
    uint8_t status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];

    SetTimeOut(5);

		ucComMF522Buf[0] = 0x09;
    ucComMF522Buf[1] = 0x0F;
    ucComMF522Buf[2] = 0;
    ucComMF522Buf[3] = lockblock;
    
		status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    return status;  
}   

//////////////////////////////////////////////////////////////////////
//COMPLETION ST
//////////////////////////////////////////////////////////////////////
uint8_t CompletionSr(void)
{
    uint8_t status;
		unsigned int   unLen;
		uint8_t  ucComMF522Buf[MAXRLEN];

    SetTimeOut(5);
    ucComMF522Buf[0] = 0x0F;
	
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
	
    return status;  
}                                          

/////////////////////////////////////////////////////////////////////
//����PCD��ʱ��
//input:microseconds=0~15
/////////////////////////////////////////////////////////////////////
void SetTimeOut(unsigned int microseconds)

{
		unsigned long  timereload;
	unsigned int  tprescaler;

	if(microseconds == 0)
		microseconds = 1;//��ʱʱ�䲻��Ϊ0
	
	tprescaler = 0;
	timereload = 0;
	while(tprescaler < 0xfff)
	{
		timereload = ((microseconds*(long)13560) - 1)/((tprescaler * 2) + 1);
		
		if( timereload < 0xffff)
			break;
		tprescaler++;
	}
		timereload = timereload & 0xFFFF;
	
	
	I_SI522A_IO_Write(TPrescalerReg, (tprescaler) & 0xFF);
	I_SI522A_IO_Write(TModeReg, BIT7 | (((tprescaler)>>8) & 0xFF));

	I_SI522A_IO_Write(TReloadRegL,  timereload>>8);
	I_SI522A_IO_Write(TReloadRegH,  timereload  & 0xFF);
}


	
/////////////////////////////////////////////////////////////////////
//开启天线  
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn(void)
{
		
 //   unsigned char i;
//	GPIO_WriteBit(GPIOA,GPIO_Pin_2,Bit_SET);    //RST保持为高，才能开启天线！
//    i = I_SI522A_IO_Read(TxControlReg);
//    if (!(i & 0x03))
//    {
//        I_SI522A_SetBitMask(TxControlReg, 0x03);
//    }
//		
	I_SI522A_IO_Write(TxControlReg,I_SI522A_IO_Read(TxControlReg) | 0x03);	//Tx1RFEn=1  Tx2RFEn=1
		delay_ms(1);      //这里加一个小延时，会好一点！
}

/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
//	I_SI522A_ClearBitMask(TxControlReg, 0x03);          //新增
	I_SI522A_IO_Write(TxControlReg,I_SI522A_IO_Read(TxControlReg)&(~0x03));
}

/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
{
    unsigned char i,n;
    I_SI522A_ClearBitMask(DivIrqReg,0x04);
    I_SI522A_IO_Write(CommandReg,PCD_IDLE);
    I_SI522A_SetBitMask(FIFOLevelReg,0x80);
    for (i=0; i<len; i++)
    {   I_SI522A_IO_Write(FIFODataReg, *(pIndata+i));   }
    I_SI522A_IO_Write(CommandReg, PCD_CALCCRC);
    i = 0xFF;
    do 
    {
        n = I_SI522A_IO_Read(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));
    pOutData[0] = I_SI522A_IO_Read(CRCResultRegL);
    pOutData[1] = I_SI522A_IO_Read(CRCResultRegH);
}


unsigned char aaa = 0;


/////////////////////////////////////////////////////////////////////
//功    能：通过RC522和ISO14443卡通讯
//参数说明：Command[IN]:RC522命令字
//          pInData[IN]:通过RC522发送到卡片的数据
//          InLenByte[IN]:发送数据的字节长度
//          pOutData[OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
//status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
char PcdComMF522(unsigned char Command, 
                 unsigned char *pInData, 
                 unsigned char InLenByte,
                 unsigned char *pOutData, 
                 unsigned int *pOutLenBit)
{
    char status = MI_ERR;
    unsigned char irqEn   = 0x00;
    unsigned char waitFor = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;
    switch (Command)
    {
        case PCD_AUTHENT:
			irqEn   = 0x12;
			waitFor = 0x10;
			break;
		case PCD_TRANSCEIVE:
			irqEn   = 0x77;
			waitFor = 0x30;
			break;
		default:
			break;
    }
   
//    I_SI522A_IO_Write(ComIEnReg,irqEn|0x80);
    I_SI522A_ClearBitMask(ComIrqReg,0x80);
    I_SI522A_IO_Write(CommandReg,PCD_IDLE);
		delay_ms(1);
    I_SI522A_SetBitMask(FIFOLevelReg,0x80);
    
    for (i=0; i<InLenByte; i++)
    {   
		I_SI522A_IO_Write(FIFODataReg, pInData[i]);    
	}
    I_SI522A_IO_Write(CommandReg, Command);
   
    if (Command == PCD_TRANSCEIVE)
    {    
		I_SI522A_SetBitMask(BitFramingReg,0x80);  
	}
    
    //i = 600;//根据时钟频率调整，操作M1卡最大等待时间25ms
	i = 2000;
    do 
    {
        n = I_SI522A_IO_Read(ComIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitFor));
    I_SI522A_ClearBitMask(BitFramingReg,0x80);

    if (i!=0)
    {   
	//	aaa = I_SI522A_IO_Read(ErrorReg);
		
        if(!(I_SI522A_IO_Read(ErrorReg)&0x1B))
        {
            status = MI_OK;
            if (n & irqEn & 0x01)
            {   status = MI_NOTAGERR;   }
            if (Command == PCD_TRANSCEIVE)
            {
               	n = I_SI522A_IO_Read(FIFOLevelReg);
              	lastBits = I_SI522A_IO_Read(ControlReg) & 0x07;
                if (lastBits)
                {   
					*pOutLenBit = (n-1)*8 + lastBits;   
				}
                else
                {   
					*pOutLenBit = n*8;   
				}
                if (n == 0)
                {   
					n = 1;    
				}
                if (n > MAXRLEN)
                {   
					n = MAXRLEN;   
				}
                for (i=0; i<n; i++)
                {   
					pOutData[i] = I_SI522A_IO_Read(FIFODataReg);    
				}
            }
        }
        else
        {   
			status = MI_ERR;   
		}
        
    }
   
    I_SI522A_SetBitMask(ControlReg,0x80);           // stop timer now
    I_SI522A_IO_Write(CommandReg,PCD_IDLE); 
    return status;
}
                     
/////////////////////////////////////////////////////////////////////
//功    能：寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]：卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
	char status;  
	unsigned int unLen;
	unsigned char ucComMF522Buf[MAXRLEN]; 

	I_SI522A_ClearBitMask(Status2Reg,0x08);
	I_SI522A_IO_Write(BitFramingReg,0x07);
  I_SI522A_SetBitMask(TxControlReg,0x03);

 
	ucComMF522Buf[0] = req_code;

	status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);

	if ((status == MI_OK) && (unLen == 0x10))
	{    
		*pTagType     = ucComMF522Buf[0];
		*(pTagType+1) = ucComMF522Buf[1];
	}
	else
	{   
		status = MI_ERR;   
	}
   
	return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：防冲撞
//参数说明: pSnr[OUT]:卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////  
char PcdAnticoll(unsigned char *pSnr, unsigned char anticollision_level)
{
    char status;
    unsigned char i,snr_check=0;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    

    I_SI522A_ClearBitMask(Status2Reg,0x08);
    I_SI522A_IO_Write(BitFramingReg,0x00);
    I_SI522A_ClearBitMask(CollReg,0x80);
 
    ucComMF522Buf[0] = anticollision_level;
    ucComMF522Buf[1] = 0x20;

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

    if (status == MI_OK)
	{
		for (i=0; i<4; i++)
		{   
			*(pSnr+i)  = ucComMF522Buf[i];
			snr_check ^= ucComMF522Buf[i];
		}
		if (snr_check != ucComMF522Buf[i])
   		{   
			status = MI_ERR;    
		}
    }
    
    I_SI522A_SetBitMask(CollReg,0x80);
    return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：选定卡片
//参数说明: pSnr[IN]:卡片序列号，4字节
//返    回: 成功返回MI_OK
////////////////////////////////////////////////////////////////////
char PcdSelect (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);                                                                      
  
    I_SI522A_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

char PcdSelect1 (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    I_SI522A_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

char PcdSelect2 (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL2;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    I_SI522A_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

char PcdSelect3 (unsigned char * pSnr, unsigned char *sak)
{
    char status;
    unsigned char i;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_ANTICOLL2;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
    for (i=0; i<4; i++)
    {
    	ucComMF522Buf[i+2] = *(pSnr+i);
    	ucComMF522Buf[6]  ^= *(pSnr+i);
    }
    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  
    I_SI522A_ClearBitMask(Status2Reg,0x08);

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    
    if ((status == MI_OK) && (unLen == 0x18))
    {   
		*sak = ucComMF522Buf[0];
		status = MI_OK;  
	}
    else
    {   
		status = MI_ERR;    
	}

    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：命令卡片进入休眠状态
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_HALT;
    ucComMF522Buf[1] = 0;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥 
//          addr[IN]：块地址
//          pKey[IN]：密码
//          pSnr[IN]：卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////               
char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = auth_mode;
    ucComMF522Buf[1] = addr;
	memcpy(&ucComMF522Buf[2], pKey, 6); 
	memcpy(&ucComMF522Buf[8], pSnr, 6); 
    
    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    if ((status != MI_OK) || (!(I_SI522A_IO_Read(Status2Reg) & 0x08)))
    {
		status = MI_ERR;   
	}
    
    return status;
}



/////////////////////////////////////////////////////////////////////
//功    能：读取M1卡一块数据
//参数说明: addr[IN]：块地址
//          pData[OUT]：读出的数据，16字节
//返    回: 成功返回MI_OK
///////////////////////////////////////////////////////////////////// 
char PcdRead(unsigned char addr,unsigned char *pData)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 

    ucComMF522Buf[0] = PICC_READ;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
   
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    if ((status == MI_OK) && (unLen == 0x90))
   	{   
		memcpy(pData, ucComMF522Buf, 16);   
	}
    else
    {   
		status = MI_ERR;   
	}
    
    return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：写数据到M1卡一块
//参数说明: addr[IN]：块地址
//          pData[IN]：写入的数据，16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////                  
char PcdWrite(unsigned char addr,unsigned char *pData)
{
    char status;
    unsigned int unLen;
    unsigned char ucComMF522Buf[MAXRLEN]; 
    
    ucComMF522Buf[0] = PICC_WRITE;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
 
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   
		status = MI_ERR;   
	}
        
    if (status == MI_OK)
    {
        memcpy(ucComMF522Buf, pData, 16);
        CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);

        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        {   
			status = MI_ERR;   
		}
    }
    
    return status;
}

void PCD_SI522A_TypeA_Init(void)
{
	PcdReset();
	PcdAntennaOff();
//	PcdAntennaOn();
	M500PcdConfigISOTypeA();
}

void M500PcdConfigISOTypeA(void)   //ISO1443A//A:NXP,B:MOTO
{
//	I_SI522A_ClearBitMask(Status2Reg,0x08); //清MFCrypto1On
//	I_SI522A_IO_Write(ModeReg, 0x3D);	//3F 选择模式
//	I_SI522A_IO_Write(RxSelReg,0x86); //84 内部接收设置
//	I_SI522A_IO_Write(RFCfgReg,0x58); //4F 接收增益
//	
//	I_SI522A_IO_Write(TReloadRegL, 30);	//重装定时器值低位
//	I_SI522A_IO_Write(TReloadRegH, 0);	//重装定时器值高位 
//	I_SI522A_IO_Write(TModeReg, 0x8D);	//跟随协议启动和停止
//	I_SI522A_IO_Write(TPrescalerReg, 0x3E);	 //6.78/3390=0.002Mhz,(1/2)*30=15ms产生中断
	
			  I_SI522A_ClearBitMask(Status2Reg,BIT3); //清MFCrypto1On
			I_SI522A_SetBitMask(ComIEnReg,BIT7); //低电平触发中断
			I_SI522A_IO_Write(ModeReg, 0x3D);	 //和Mifare卡通讯，CRC初始值0x6363
			I_SI522A_IO_Write(RxSelReg,0x86);  //RxWait,延迟RxWait个比特时间后激活接收机
			I_SI522A_IO_Write(RFCfgReg,0x68);  //接收增益,0x38 - 0x78,最大0x7F
			I_SI522A_IO_Write(TxASKReg,0x40);  // typeA
			I_SI522A_IO_Write(TxModeReg,0x00); //Tx Framing A
		  I_SI522A_IO_Write(RxModeReg,0x00);  //Rx framing A
			I_SI522A_IO_Write(ControlReg,0x10);

			PcdAntennaOn();
			delay_us(400);
}

void PcdConfigISOType(unsigned char type)
{
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 1);
	}
	delay_ms (5);
	
		I_SI522A_IO_Write(ControlReg, 0x10);  			//设为发起者
	
		I_SI522A_ClearBitMask(Status2Reg, 0x08);  
	// Reset baud rates
	I_SI522A_IO_Write(TxModeReg, 0x00);
	I_SI522A_IO_Write(RxModeReg, 0x00);
	// Reset ModWidthReg
	I_SI522A_IO_Write(ModWidthReg, 0x26);
	// RxGain:110,43dB by default;
	I_SI522A_IO_Write(RFCfgReg, RFCfgReg_Val);
	// When communicating with a PICC we need a timeout if something goes wrong.
	// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
	// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
	I_SI522A_IO_Write(TModeReg, 0x80);// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
	I_SI522A_IO_Write(TPrescalerReg, 0xa9);// TPreScaler = TModeReg[3..0]:TPrescalerReg
	I_SI522A_IO_Write(TReloadRegH, 0x03); // Reload timer 
	I_SI522A_IO_Write(TReloadRegL, 0xe8); // Reload timer 
	I_SI522A_IO_Write(TxASKReg, 0x40);	// Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
	I_SI522A_IO_Write(ModeReg, 0x3D);	// Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)

	PcdAntennaOn();
	
	
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 0);
	}

	msleep(50);
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 1);
	}

	msleep(5);
	PcdAntennaOff();
	msleep(5);
	
	if ('A' == type)
	{
		  I_SI522A_ClearBitMask(Status2Reg,BIT3); //清MFCrypto1On
			I_SI522A_SetBitMask(ComIEnReg,BIT7); //低电平触发中断
			I_SI522A_IO_Write(ModeReg, 0x3D);	 //和Mifare卡通讯，CRC初始值0x6363
			I_SI522A_IO_Write(RxSelReg,0x86);  //RxWait,延迟RxWait个比特时间后激活接收机
			I_SI522A_IO_Write(RFCfgReg,0x68);  //接收增益,0x38 - 0x78,最大0x7F
			I_SI522A_IO_Write(TxASKReg,0x40);  // typeA
			I_SI522A_IO_Write(TxModeReg,0x00); //Tx Framing A
		  I_SI522A_IO_Write(RxModeReg,0x00);  //Rx framing A
			I_SI522A_IO_Write(ControlReg,0x10);
		I_SI522A_SiModifyReg(0x01, 0, 0x20);	// Turn on the analog part of receiver 
		
//			I_SI522A_IO_Write(RxSelReg,0x88); //延迟RxWait个比特，更长？
//			I_SI522A_IO_Write(ModGsPReg,0x12);  //0x0F);//调制指数 P驱动电导
		  
	}
	else if ('B' == type)
	{
			I_SI522A_ClearBitMask(Status2Reg,0X08); //清MFCrypto1On
			I_SI522A_SetBitMask(ComIEnReg,0X80); //低电平触发中断
			I_SI522A_IO_Write(ModeReg, 0x3F);	 //CRC初始值0xFFFF
			I_SI522A_IO_Write(RxSelReg,0x85);  //RxWait,延迟RxWait个比特时间后激活接收机
			I_SI522A_IO_Write(RFCfgReg,0x68);  //接收增益,0x38 - 0x78,最大0x7F
			//发射部分配置
			I_SI522A_IO_Write(GsNReg,0xF8);  //调制系数
			I_SI522A_IO_Write(CWGsPReg,0x3F); 
			I_SI522A_IO_Write(ModGsPReg,0x07);//调制系数
			I_SI522A_IO_Write(AutoTestReg,0x00); //AmpRcv为1，接收内部信号处理过程是非线性的
			I_SI522A_IO_Write(TxASKReg,0x00);  // typeB
			I_SI522A_IO_Write(TypeBReg,0x13);  
			I_SI522A_IO_Write(TxModeReg,0x83); //Tx Framing B
			I_SI522A_IO_Write(RxModeReg,0x83);  //Rx framing B
			I_SI522A_IO_Write(BitFramingReg,0x00);  ////TxLastBits=0
			I_SI522A_IO_Write(ControlReg,0x10);
			I_SI522A_SiModifyReg(0x01, 0, 0x20);	// Turn on the analog part of receiver 		

	PcdAntennaOn();
		
	}
	else if ('C' == type)
	{
			I_SI522A_ClearBitMask(Status2Reg,BIT3); //清MFCrypto1On
			I_SI522A_SetBitMask(ComIEnReg,BIT7); //低电平触发中断
			I_SI522A_IO_Write(ControlReg,0x10);  //设置为发起者
			I_SI522A_IO_Write(ModeReg, 0x38);	 //CRC初始值0x0000
			I_SI522A_IO_Write(RxSelReg,0x84);  //RxWait,延迟RxWait个比特时间后激活接收机
			I_SI522A_IO_Write(RFCfgReg,0x58);  //接收增益,0x38 - 0x78,可设置0x79,增加检测器的灵敏度,最大0x7F
			//发射部分配置
			I_SI522A_IO_Write(GsNReg,0xf8);  //调制系数
			I_SI522A_IO_Write(CWGsPReg,0x30);
			I_SI522A_IO_Write(ModGsPReg,0x0e);//调制系数
			I_SI522A_IO_Write(AutoTestReg,0x00); //AmpRcv为1，接收内部信号处理过程是非线性的
			I_SI522A_IO_Write(TxASKReg,0x00);  // typeC
			I_SI522A_IO_Write(TypeBReg,0x00);  
			I_SI522A_IO_Write(Fel1Reg,0x00);  // Fel1Reg 同步字节 B2 4D
			I_SI522A_IO_Write(MfRxReg,0x11);  //ParityDisable校验关闭，信号的频谱下至212kHz
			I_SI522A_IO_Write(DemodReg,0x41); //PLL相关
			I_SI522A_IO_Write(TxModeReg,0x92); //Tx Framing C
			I_SI522A_IO_Write(RxModeReg,0x92); //Rx framing C
		
			I_SI522A_IO_Write(RxThresholdReg, 0x65);    //55 65      // 高四位->最小信号强度，低三位->冲突最小信号强度,最大0xF7,最小0x44
	}
	PcdAntennaOn();
	delay_ms(2);
	
	
}





////////读B卡初始化////
//void	PCD_SI522A_TypeB_Init(void)
//	{
//			I_SI522A_ClearBitMask(Status2Reg, 0x08);
//	I_SI522A_IO_Write(ModeReg, 0x3F);  // For 0xFFFF crc
//	I_SI522A_IO_Write(TReloadRegL, 30);
//	I_SI522A_IO_Write(TReloadRegH, 0);
//	I_SI522A_IO_Write(TModeReg, 0x8D);
//	I_SI522A_IO_Write(TPrescalerReg, 0x3E); 
//	I_SI522A_IO_Write(TxASKReg, 0);  // Force 100ASK = 0//		delay_ms(100);
//	
//	I_SI522A_IO_Write(GsNReg, 0xf8);  // TX输出电导设置f8 fa N
//	I_SI522A_IO_Write(CWGsPReg, 0x3f);	 // P_改变1的幅度
//	I_SI522A_IO_Write(ModGsPReg, 0x0E);  // 调制指数设置RegModGsp,, TYPEB ModConductance 0x1A P_改变0的幅度
//	I_SI522A_IO_Write(TxModeReg, 0x83);  // 编码器设置,106kbps,14443B 03
//	I_SI522A_IO_Write(BitFramingReg, 0x00);   // 调制脉宽,0x13->2.95us RegTypeBFraming ,,TYPEB
//	I_SI522A_IO_Write(AutoTestReg, 0x00);   
//	// 低二位为接收增益，
//	// 00,10,20,30,40,50,60,70
//	// 18,23,18,23,33,38,43,48dB
//	I_SI522A_IO_Write(RFCfgReg, RFCfgReg_Val);          
//	I_SI522A_IO_Write(RxModeReg, 0x83);                 
//	I_SI522A_IO_Write(RxThresholdReg, 0x65);     
//	
//	I_SI522A_ClearBitMask(RxSelReg,0x3F);
//	I_SI522A_SetBitMask(RxSelReg, 0x08);
////	I_SI522A_ClearBitMask(TxModeReg, 0x80);   // 无CRC,无奇偶校验
////	I_SI522A_ClearBitMask(RxModeReg, 0x80);
//	I_SI522A_ClearBitMask(Status2Reg, 0x08);   // MFCrypto1On =0			

//	PcdAntennaOn();
//		
//	}
void PCD_SI522A_TypeA(void)
{
	//LED_OperaSuccess();	// LED indicator
	
	while(1)
	{
		PCD_SI522A_TypeA_GetUID();
		
		//PCD_SI522A_TypeA_rw_block();
	
		delay_ms(500);
	}
}

char PCD_SI522A_TypeA_GetUID(void)
{
	//unsigned char ATQA[2]={0};
	unsigned char UID[12]={0};
	unsigned char SAK = 0;
	unsigned char UID_complate1 = 0;
	unsigned char UID_complate2 = 0;

	printf("\r\nTest_Si522_GetUID");
	I_SI522A_IO_Write(RFCfgReg, RFCfgReg_Val); //复位接收增益
	
	//寻卡
	gdatalen = -1;
	memset(gdata, 0, 128);
	gdatatype = 0;
	if( PcdRequest( PICC_REQALL, ATQA) != MI_OK )  //寻天线区内未进入休眠状态的卡，返回卡片类型 2字节	
	{
		I_SI522A_IO_Write(RFCfgReg, 0x48);
		if(PcdRequest( PICC_REQALL, ATQA) != MI_OK)
		{
			I_SI522A_IO_Write(RFCfgReg, 0x58);
			if(PcdRequest( PICC_REQALL, ATQA) != MI_OK)
			{	
				printf("\r\nRequest:no find A ");
				return 2;
			}
			else
			{
				printf("\r\nRequest1:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
			}	
		}
		else
		{
			printf("\r\nRequest2:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
		}		
	}
	else
	{
		printf("\r\nRequest3:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
	}
	
	
//UID长度=4
	//Anticoll 冲突检测 level1
	if(PcdAnticoll(UID, PICC_ANTICOLL1)!= MI_OK) 
	{
		printf("\r\nAnticoll1:fail");
		return 1;		
	}
	else
	{
		if(PcdSelect1(UID,&SAK)!= MI_OK)
		{
			printf("\r\nSelect1:fail");
			return 1;		
		}
		else
		{
			printf("\r\nSelect1:ok  SAK1:%02x",SAK);
			if(SAK&0x04)                         
			{
				UID_complate1 = 0;
				
				//UID长度=7
				if(UID_complate1 == 0)    
				{
					//Anticoll 冲突检测 level2
					if(PcdAnticoll(UID+4, PICC_ANTICOLL2)!= MI_OK) 
					{
						printf("\r\nAnticoll2:fail");
						return 1;		
					}
					else
					{
						if(PcdSelect2(UID+4,&SAK)!= MI_OK)  
						{
							printf("\r\nSelect2:fail");
							return 1;		
						}
						else
						{
							printf("\r\nSelect2:ok  SAK2:%02x",SAK);
							if(SAK&0x04)                         
							{
								UID_complate2 = 0;
								
								//UID长度=10
								if(UID_complate2 == 0)     
								{
									//Anticoll 冲突检测 level3
									if(PcdAnticoll(UID+8, PICC_ANTICOLL3)!= MI_OK) 
									{
										printf("\r\nAnticoll3:fail");
										return 1;		
									}
									else
									{
										if(PcdSelect3(UID+8,&SAK)!= MI_OK)  
										{
											printf("\r\nSelect3:fail");
											return 1;		
										}
										else
										{
											printf("\r\nSelect3:ok  SAK3:%02x",SAK);
											gdatalen = 10;
											if(SAK&0x04)                          
											{
//												UID_complate3 = 0;
											}
											else 
											{
	//											UID_complate3 = 1;                   
												printf("\r\nAnticoll3:ok  UID:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
												UID[1],UID[2],UID[3],UID[5],UID[6],UID[7],UID[8],UID[9],UID[10],UID[11]);									
											}	
											memcpy(gdata, &UID[1], 3);
											memcpy(&gdata[3], &UID[5], 3);
											memcpy(&gdata[6], &UID[8], 4);
										}							
									}
								}
							}
							else 
							{
								UID_complate2 = 1;  
								gdatalen = 7;	
								memcpy(gdata, &UID[1], 7);								
								printf("\r\nAnticoll2:ok  UID:%02x %02x %02x %02x %02x %02x %02x",
								UID[1],UID[2],UID[3],UID[4],UID[5],UID[6],UID[7]);
							}	
						}			
					}
				}
			}
			else 
			{
				UID_complate1 = 1;    
				gdatalen = 4;	
				memcpy(gdata, UID, 4);					
				printf("\r\nAnticoll1:ok  UID:%02x %02x %02x %02x",UID[0],UID[1],UID[2],UID[3]);
				//LED_OperaSuccess();	// LED indicator
			}
		}		
	}
	//Halt
//	if(PcdHalt() != MI_OK)
//	{
//		printf("\r\nHalt:fail");
//		return 1;		
//	}
//	else
//	{
//		printf("\r\nHalt:ok");
//	}	
	
	return 0;
}


char PCD_SI522A_TypeA_rw_block(void)
{
	unsigned char ATQA[2];
	unsigned char UID[12];
	unsigned char SAK = 0;
	unsigned char CardReadBuf[16] = {0};
	unsigned char CardWriteBuf[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
	unsigned char DefaultKeyABuf[10] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
	unsigned char i = 0;
	
	printf("\r\n\r\nTest_Si522_GetCard");
	
	//request 寻卡
	if( PcdRequest( PICC_REQIDL, ATQA) != MI_OK )  //寻天线区内未进入休眠状态的卡，返回卡片类型 2字节	
	{
		printf("\r\nRequest:fail");
		return 1;		
	}
	else
	{
		printf("\r\nRequest:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
	}
	

	//Anticoll 冲突检测
	if(PcdAnticoll(UID, PICC_ANTICOLL1)!= MI_OK)
	{		
		printf("\r\nAnticoll:fail");
		return 1;		
	}
	else
	{	
		printf("\r\nAnticoll:ok  UID:%02x %02x %02x %02x",UID[0],UID[1],UID[2],UID[3]);
	}
	
	//Select 选卡
	if(PcdSelect1(UID,&SAK)!= MI_OK)
	{
		printf("\r\nSelect:fail");
		return 1;		
	}
	else
	{
		printf("\r\nSelect:ok  SAK:%02x",SAK);
	}

	//Authenticate 验证密码
	if(PcdAuthState( PICC_AUTHENT1A, 4, DefaultKeyABuf, UID ) != MI_OK )
	{
		printf("\r\nAuthenticate:fail");
		return 1;		
	}
	else
	{
		printf("\r\nAuthenticate:ok");
	}

	//读BLOCK原始数据
	if( PcdRead( 4, CardReadBuf ) != MI_OK )
	{
		printf("\r\nPcdRead:fail");
		return 1;		
	}
	else
	{
		printf("\r\nPcdRead:ok  ");
		for(i=0;i<16;i++)
		{
			printf(" %02x",CardReadBuf[i]);
		}
	}
	//产生随机数
	for(i=0;i<16;i++) {
		unsigned char data;
		get_random_bytes(&data, 1);//rand();
		CardWriteBuf[i] = data;
	}

	//写BLOCK 写入新的数据
	if( PcdWrite( 4, CardWriteBuf ) != MI_OK )
	{
		printf("\r\nPcdWrite:fail");
		return 1;	
	}
	else
	{
		printf("\r\nPcdWrite:ok  ");
		for(i=0;i<16;i++)
		{
			printf(" %02x",CardWriteBuf[i]);
		}
	}
		
	//读BLOCK 读出新写入的数据
	if( PcdRead( 4, CardReadBuf ) != MI_OK )
	{
		printf("\r\nPcdRead:fail");
		return 1;		
	}
	else
	{
		printf("\r\nPcdRead:ok  ");
		for(i=0;i<16;i++)
		{
			printf(" %02x",CardReadBuf[i]);
		}
	}
		
//	//Halt
//	if(PcdHalt() != MI_OK)
//	{
//		printf("\r\nHalt:fail");
//		return 1;		
//	}
//	else
//	{
//		printf("\r\nHalt:ok");
//	}	
	
	return 0;
}





/////////////////////读普通B卡///////////////
char PCD_SI522A_TypeB_GetUID(void)
{
	//printf("\r\n\r\nTest_B_GetUID");
	
	//I_CI523_IO_Write(0x02, 0xa0); //打开接收中断,则读卡会产生中断
	// Enable external interrupt
	//EXTI->IMR |= 0x00000008;
	
	//request 寻B卡;返回卡号
	uint32_t 		len1;
//	unsigned char 	buf1[18] = {0x05,0x00,0x00,0x71,0xFF};
	
		unsigned char 	buf1[18] = {0x05,0x00,0x00};
	if(PcdComMF522(PCD_TRANSCEIVE, buf1, 3, buf1, &len1) != MI_OK)
	{
		printf("\r\nRequest:no find B ");
	//	printf("\r\nRequest:here");
		return 1;		
	}
	else
	{	
		if( buf1[0] == 0x50 ) //判断是不是ATQB
		printf("\r\nRequest:ok  UID:%02x %02x %02x %02x",
								buf1[1],buf1[2],buf1[3],buf1[4]);
	}	
	
	return 0;
}



char PCD_CI523_IdentityCard_GetUID(void)
{
	//printf("\r\n\r\nTest_identitycard");
	
	//request 寻B卡
	uint32_t 		len1;
	unsigned char 	buf1[18] = {0x05,0x00,0x00,0x71,0xFF};
	uint32_t 		len2;
	unsigned char 	buf2[18] = {0x1D,   0x00,0x00,0x00,0x00,   0x00,  0x08,  0x01,  0x08,  0xF3,  0x10};		
	uint32_t 		len3;
	unsigned char 	buf3[18] = {0x00,0x36,0x00,0x00, 0x08,0x57,0x44};	

	if(PcdComMF522(PCD_TRANSCEIVE, buf1, 5, buf1, &len1) != MI_OK)
	{
//		printf("\r\n\r\nRequest:fail");
//		printf("\r\n\r\nRequest:to	here");
		return 1;
	}
	
	//I_CI523_IO_Write(0x02, 0xa0); //打开接收中断,则读卡会产生中断
	// Enable external interrupt
	//EXTI->IMR |= 0x00000008;
	
	//发送二代证非标ATTRIB指令
	if(PcdComMF522(PCD_TRANSCEIVE, buf2, 11, buf2, &len2) != MI_OK)
	{
		printf("\r\nATTRIB:no find ID_card");
		return 1;		
	}	
		
	//获取UID	

	if(PcdComMF522(PCD_TRANSCEIVE, buf3, 7, buf3, &len3) != MI_OK)
	{
		printf("\r\nUID:fail");
		return 1;		
	}	
	else
	{	
		if( buf3[8] == 0x90||buf3[9] == 0x00 ) //判断是不是identitycard
		printf("\r\nUID:ok  UID:%02x %02x %02x %02x %02x %02x %02x %02x ",
								buf3[0],buf3[1],buf3[2],buf3[3],buf3[4],buf3[5],buf3[6],buf3[7]);
		//LED_OperaSuccess();	// LED indicator
	}
	
	return 0;
}


//***********************************//修改新增内容

/*
 * 函数名：PcdReset
 * 描述  ：复位RC522 
 * 输入  ：无
 * 返回  : 无
 * 调用  ：外部调用
 */
void PcdReset ( void )
{
		delay_us(50);
#if 1
//	SET_NFC_RST;    //RST拉高
		CLR_NFC_RST;    //RST拉低
	delay_ms(10);

//	delay_ms(2);
	SET_NFC_RST;    //RST拉高
	delay_ms(2);
#endif
		
	delay_us(500);  //需要与客户确认delayus函数延时准确。
	
	I_SI522A_IO_Write(CommandReg, 0x0f);			//向CommandReg 写入 0x0f	作用是使Si522复位
	delay_ms(1);
	I_SI522A_IO_Write(ModeReg, 0x3D);	 //和Mifare卡通讯，CRC初始值0x6363
	
	I_SI522A_IO_Write(TReloadRegL, 30);	//重装定时器值低位
	I_SI522A_IO_Write(TReloadRegH, 0);	//重装定时器值高位 
	I_SI522A_IO_Write(TModeReg, 0x8D);	//跟随协议启动和停止
	I_SI522A_IO_Write(TPrescalerReg, 0x3E);	 //6.78/3390=0.002Mhz,(1/2)*30=15ms产生中断
	
	I_SI522A_IO_Write(TxASKReg, 0x40);	 //必须要
}

void Pcd_Hard_Reset(void)
{
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 0);
	}

	delay_ms(50);
	if (g_nfc != NULL) {
		gpiod_direction_output(g_nfc->rst_gpio, 1);
	}
	delay_ms(5);
}

unsigned char Si5XX_SoftReset(void)
{
		unsigned char reg_data;
		I_SI522A_IO_Write(CommandReg,PCD_RESETPHASE);  
		delay_ms(1); //复位需要1ms
		reg_data=I_SI522A_IO_Read(CommandReg);
		if( 0x20 == reg_data)
			return SUCCESS;
		else
			return ERROR;
}


void I_SI522A_ClearBitMask(unsigned char reg,unsigned char mask)  
{
	char tmp = 0x00;
	tmp = I_SI522A_IO_Read(reg);
	I_SI522A_IO_Write(reg, tmp & ~mask);  // clear bit mask
} 

void I_SI522A_SetBitMask(unsigned char reg,unsigned char mask)  
{
	char tmp = 0x00;
	tmp = I_SI522A_IO_Read(reg);
	I_SI522A_IO_Write(reg,tmp | mask);  // set bit mask
}

void I_SI522A_SiModifyReg(unsigned char RegAddr, unsigned char ModifyVal, unsigned char MaskByte)
{
	unsigned char RegVal;
	RegVal = I_SI522A_IO_Read(RegAddr);
	if(ModifyVal)
	{
			RegVal |= MaskByte;
	}
	else
	{
			RegVal &= (~MaskByte);
	}
	I_SI522A_IO_Write(RegAddr, RegVal);
}

//
void ACD_init_Fun(void)
{
	PCD_SI522A_TypeA_Init();	//Reader模式的初始化
	
	PCD_ACD_AutoCalc(); //自动获取阈值
	
	PCD_ACD_Start();   //初始化ACD配置寄存器，并且进入ACD模式
}


//acd 应用函数
void PCD_ACD_Application(void)
{
	
}

void ACD_Fun(void)
{
	uint8_t i = 0;
	//EXTI->IMR |= 0x00000008;	// Enable external interrupt
	PCD_IRQ_flagA = 0;	//clear IRQ flag
	//LED_OperaSuccess();	// LED indicator
	
	while(1)
	{	
		if(PCD_IRQ_flagA)
		{
			printf("\r\n\r\n\r\n PCD_IRQ_flagA");
			//EXTI->IMR &= 0xFFFFFFF7;		// Disable external interrupt			

			switch( PCD_IRQ() )
			{
				case 0:	//Other_IRQ 			
					printf("Other IRQ Occur\r\n");
				PcdAntennaOn();  //打开天线，防止静电干扰产生中断后，天线场强被异常关掉
				PcdReset();    //修改复位函数，增加硬掉电操作，防止芯片被静电异常操作导致无法工作。
				PcdConfigISOType('A');
				for(i=0;i<3;i++)
				{
					uint8_t ret=0;
					ret=PCD_SI522A_TypeA_GetUID(); //读卡
					if(!ret)
					{
							flag_read_ic_ok=1;
						  break;
					}
				}
				PcdConfigISOType('A'); //初始化默认配置
	
//									PCD_SI522A_TypeA_GetUID();
//					PcdReset();			//软复位				
//					//PcdReset();				//硬复位
//					PCD_SI522A_TypeA_Init();
//					PCD_ACD_Init();
					break;
						
				case 1:	//ACD_IRQ
				/*********************************旧版********************************
					I_SI522A_SiModifyReg(0x01, 0, 0x20);	// Turn on the analog part of receiver 	
					PcdConfigISOType('A');				
					PCD_SI522A_TypeA_GetUID();
					I_SI522A_IO_Write(ComIEnReg, 0x80);		//复位02寄存器,在读卡函数中被改动
					I_SI522A_IO_Write(CommandReg, 0xb0);	 	//进入软掉电,重新进入ACD（ALPPL）
				*************************************************************/
				/***********************新版建议使用（修复误触发后的异常丢失寄存器）******
				***add 2022/04/15
				** 1.防止异常产生中断后，由于芯片配置丢失，芯片再进入ACD模式异常
				** 2.用户可以将case0和case1都执行为case1的程序即可。
				**********************************************************************/
				PcdAntennaOn();  //打开天线，防止静电干扰产生中断后，天线场强被异常关掉
				PcdReset();    //修改复位函数，增加硬掉电操作，防止芯片被静电异常操作导致无法工作。
				PcdConfigISOType('A');
				for(i=0;i<3;i++)          //三次读卡
				{
					uint8_t ret=0;
					ret=PCD_SI522A_TypeA_GetUID(); 
					if(!ret)
					{
							flag_read_ic_ok=1;
						  break;
					}
				}
				I_SI522A_IO_Write(ComIEnReg, 0x80);		//复位02寄存器,在读卡函数中被改动
				PcdConfigISOType('A'); //初始化默认配置
		//		PCD_ACD_Init();       //初始化ACD寄存器配置，进入ACD低功耗探测模式
				break;
				
				case 2:	//ACDTIMER_IRQ			
					printf("ACDTIMER_IRQ:Reconfigure the register \r\n");
					//PcdReset();			//软复位
					Pcd_Hard_Reset();		//硬复位
					PcdConfigISOType('A');
			//		PCD_ACD_Init();
				
					break;
				
			}		
			
			//EXTI->IMR |= 0x00000008;		// Enable external interrupt
			PCD_IRQ_flagA = 0;	
		}
		else
		{
			delay_ms(500);
		}
	}
}



//冒泡排序，从小到大
void bubbleSort(uint8_t *arr, uint8_t n)
{
    uint8_t i, j, temp;
    // 外层循环控制所有元素
    for (i = 0; i < n - 1; i++)
    {
        // 内层循环比较相邻元素并交换
        for (j = 0; j < n - 1 - i; j++)
        {
            // 比较当前元素和下一个元素，如果当前元素大于下一个元素，则交换
            if (arr[j] > arr[j + 1])
            {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}


//根据获取的ACD_K值写入寄存器，采样验证获取C值并处理
void ACD_Cval_Calc(void)
{
    uint32_t temp_Compare = 0;
    uint8_t C_Val_temp[8] = {0};
	uint8_t j = 0;
	
    I_SI522A_IO_Write(TxControlReg, 0x83);	 //打开天线,注意此处打开天线端与寻卡时保持一致
    delay_ms(1);
    printf("TxControlReg = %02x\r\n", I_SI522A_IO_Read(TxControlReg));  //读取天线是否打开
    I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK<<2) | 0x40);
    I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegK_Val );
		delay_us(10);
    I_SI522A_IO_Write(CommandReg,0x06);  //开启ACD测量场强
	I_SI522A_IO_Read(CommandReg);
		delay_us(130);
     for(j=0; j<6;j++)
     {
         I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);
         C_Val_temp[j] = I_SI522A_IO_Read(ACDConfigReg);
         delay_us(10);
     }
     I_SI522A_IO_Write(CommandReg, 0x06);  //关闭ACD测量

     printf(" C_Val_temp = \r\n");
     for(j=0; j<6;j++)
     {
         printf(" %x, ",C_Val_temp[j]);
     }
     printf(" \r\n");
     bubbleSort(C_Val_temp, 6);  //获取场强值排序
     printf(" C_Val_temp = \r\n");
     for(j=0; j<6;j++)
     {
         printf(" %x, ",C_Val_temp[j]);
     }
     printf(" \r\n");
     for(j=1; j<5;j++)
     {
         temp_Compare += C_Val_temp[j];
     }
     temp_Compare = temp_Compare /4;      //去除最大最小值并取平均值(4次值平均)
     ACDConfigRegC_Val = temp_Compare;
     printf("ACDConfigRegC_Val:%02x\r\n",ACDConfigRegC_Val);  //打印最终C值
}




/********************************************************
*PCD_ACD_AutoCalc(void) 函数主要为了上电后，自动计算并选择ADC的基准电压和合适的增益放大。
*1.第一个VOCN数组是为了从最大基准电压开始轮询查，并将VCON值写入0F_K寄存器的bit[3:0],然后读取0F_G寄存器，计算100次的平均值，直到找到非0的最小值。
*2. 0F_K寄存器在第一步获取的VCON值bit[2:0]基础上，或上TR增益控制位bit[6:5]，然后将换算的值写入0F_K寄存器，读取0F_G,获取最大非超7F阈值的增益控制位
*3. 将获取的VCON和TR，写入0F_G。
*4. 关于0F_K寄存器的定义请参考 《ACD初始化代码解析》文档
*5. V1.3版本将0F_K寄存器的TIbit[4:3]从01修改为10  VCON数组进行了更新，TR计算时进行了更新。1016行，1094行代码！！！
********************************************************/
void PCD_ACD_AutoCalc(void)
{
	unsigned char temp; 
	unsigned short temp_Compare=0; 
	//unsigned char VCON_TR[8]={ 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08};//VCON值，检波斜率优先选择1倍斜率，8种参考电压档位
	unsigned char VCON_TR[8]={ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//VCON值，检波斜率优先选择1倍斜率，8种参考电压档位
	unsigned char TR_Compare[4]={ 0x00, 0x00, 0x00, 0x00};
	unsigned char	ACDConfigRegK_RealVal = 0;
	int i = 0, m=0, j=0, n=0, z=0;
	
	ACDConfigRegC_Val = 0x7f;
	I_SI522A_IO_Write(TxControlReg, 0x83);	//打开天线，0x81或者0x82都是开启单通道检测，需用户确定开启单端还是双端
//	I_SI522A_SetBitMask(CommandReg, 0x06);	//开启ACD测量场强
//	delay_us(130);

	for(i=7; i>0; i--)
	{	
		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK << 2) | 0x40);		//写入ACD_K值
		I_SI522A_IO_Write(ACDConfigReg, VCON_TR[i]);
		
		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);   //采样ACD_G值
		temp_Compare = I_SI522A_IO_Read(ACDConfigReg);
		
		I_SI522A_SetBitMask(CommandReg, 0x06);	//开启ACD测量场强
		I_SI522A_IO_Read(CommandReg);
	  delay_us(130);
		
		for(m=0;m<100;m++)
		{
			I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);		
			temp = I_SI522A_IO_Read(ACDConfigReg);
			
			if(	temp	==	0) 	continue;          //处在接近的VCON值附近值，如果偶合出现0值，均有概率误触发，应舍弃该值。
				
			temp_Compare = (temp_Compare+temp)/2;		
			delay_us(100);
		}		
		I_SI522A_SetBitMask(CommandReg, 0x06);		//关闭ADC_EXCUTE
		
		printf(" i = %d,  temp_Compare: %02x \r\n",i,temp_Compare);	 //打印不同参考电压下的G值
		if(temp_Compare == 0 || temp_Compare == 0x7f) //比较当前值和所存值
		{

		}
		else
		{
			if(temp_Compare < ACDConfigRegC_Val)
			{
				ACDConfigRegC_Val = temp_Compare;
				ACDConfigRegK_Val = VCON_TR[i];
			}
		}
	}
	ACDConfigRegK_RealVal	=	ACDConfigRegK_Val;     //取得最接近的参考电压VCON

	//修改增益档位，优先使用7倍增益
	for(j=0; j<4; j++)
	{
		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK << 2) | 0x40);		//修改ACD_K增益档位并写入
		I_SI522A_IO_Write(ACDConfigReg, j*32+ACDConfigRegK_Val);
		
		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);   //采样无卡场强G值
		temp_Compare = I_SI522A_IO_Read(ACDConfigReg);
		
		I_SI522A_SetBitMask(CommandReg, 0x06);	//开启ACD测量场强
		I_SI522A_IO_Read(CommandReg);
	  delay_us(130);
		
		for(n=0;n<100;n++)
		{
			I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);		
			temp = I_SI522A_IO_Read(ACDConfigReg);
			if(	temp	==	0) 	continue;
			temp_Compare=(temp_Compare+temp)/2;		
			delay_us(100);
		}
		I_SI522A_SetBitMask(CommandReg, 0x06);		//关闭ADC_EXCUTE
		
		TR_Compare[j] = temp_Compare;
		printf(" j = %d,  ACD_G: %02x \r\n",j,TR_Compare[j]);	 //打印不同增益下的G值
	}//再调TR的档位，将采集值填入TR_Compare[]

	for(z=2; z>0; z--)                   //TR有四档可调，但是最大档的时候，电源有抖动，可能会导致ADC的值抖动较大，造成误触发
	{
		if(TR_Compare[z] ==0x7F)         
		{
			
		}
		else
		{
			ACDConfigRegC_Val = TR_Compare[z];//最终选择的配置
			ACDConfigRegK_Val = ACDConfigRegK_RealVal + z*32;  // 确定最终的K值
			break;
		}
	}//再选出一个非7f大值
	
	//I_SI522A_SetBitMask(CommandReg, 0x06);		//关闭ADC_EXCUTE
	
	printf(" ACDConfigRegK_Val: %02x,  ACD_C: %02x \r\n",ACDConfigRegK_Val,ACDConfigRegC_Val);	
	
	delay_ms(3);
	ACD_Cval_Calc();
	
}










///********************************************************
//*PCD_ACD_AutoCalc(void) 函数主要为了上电后，自动计算并选择ADC的基准电压和合适的增益放大。
//*1.第一个VOCN数组是为了从最大基准电压开始轮询查，并将VCON值写入0F_K寄存器的bit[3:0],然后读取0F_G寄存器，计算100次的平均值，直到找到非0的最小值。
//*2. 0F_K寄存器在第一步获取的VCON值bit[2:0]基础上，或上TR增益控制位bit[6:5]，然后将换算的值写入0F_K寄存器，读取0F_G,获取最大非超7F阈值的增益控制位
//*3. 将获取的VCON和TR，写入0F_G。
//*4. 关于0F_K寄存器的定义请参考 《ACD初始化代码解析》文档
//*5. V1.3版本将0F_K寄存器的TIbit[4:3]从01修改为10  VCON数组进行了更新，TR计算时进行了更新。1016行，1094行代码！！！
//********************************************************/
//void PCD_ACD_AutoCalc(void)
//{
//	unsigned char temp; 
//	unsigned char temp_Compare=0; 
//	unsigned char VCON_TR[8]={ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};//acd灵敏度调节 V1.3版本修改VCON值，
//	//	unsigned char VCON_TR[8]={ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//acd灵敏度调节 V1.3版本修改VCON值，
//	unsigned char TR_Compare[4]={ 0x00, 0x00, 0x00, 0x00};
//	ACDConfigRegC_Val = 0x7f;
//	unsigned char	ACDConfigRegK_RealVal = 0;
//	I_SI522A_IO_Write(TxControlReg, 0x81);	//打开天线，0x81或者0x82都是开启单通道检测，主要看RX端从哪里采集的信号就选择哪个
//	I_SI522A_SetBitMask(CommandReg, 0x06);	//开启ADC_EXCUTE
//	delay_us(200);

//	for(int i=7; i>0; i--)
//	{	
//		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK << 2) | 0x40);		
//		I_SI522A_IO_Write(ACDConfigReg, VCON_TR[i]);
//		
//		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);
//		temp_Compare = I_SI522A_IO_Read(ACDConfigReg);
//		for(int m=0;m<100;m++)
//		{
//			I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);		
//			temp = I_SI522A_IO_Read(ACDConfigReg);
//			
//			if(	temp	==	0) 	break;          //处在接近的VCON值附近值，如果偶合出现0值，均有概率误触发，应舍弃该值。
//				
//			temp_Compare=(temp_Compare+temp)/2;		
//			delay_us(100);
//		}		
//		
//		if(temp_Compare == 0 || temp_Compare == 0x7f) //比较当前值和所存值
//		{

//		}
//		else
//		{
//			if(temp_Compare < ACDConfigRegC_Val)
//			{
//				ACDConfigRegC_Val = temp_Compare;
//				ACDConfigRegK_Val = VCON_TR[i];
//			}
//		}
//	}
//	ACDConfigRegK_RealVal	=	ACDConfigRegK_Val;     //取得最接近的参考电压VCON

//	for(int j=0; j<4; j++)
//	{
//		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK << 2) | 0x40);		
//		I_SI522A_IO_Write(ACDConfigReg, j*32+ACDConfigRegK_Val);
//		
//		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);
//		temp_Compare = I_SI522A_IO_Read(ACDConfigReg);
//		for(int n=0;n<100;n++)
//		{
//			I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);		
//			temp = I_SI522A_IO_Read(ACDConfigReg);
//			temp_Compare=(temp_Compare+temp)/2;		
//			delay_us(100);
//		}		
//		TR_Compare[j] = temp_Compare;
//	}//再调TR的档位，将采集值填入TR_Compare[]

//	for(int z=0; z<3; z++)                   //TR有四档可调，但是最大档的时候，电源有抖动，可能会导致ADC的值抖动较大，造成误触发
//	{
//		if(TR_Compare[z] ==0x7F)         
//		{
//			
//		}
//		else
//		{
//			ACDConfigRegC_Val = TR_Compare[z];//最终选择的配置
//			ACDConfigRegK_Val = ACDConfigRegK_RealVal + z*32;  // V1.3版本将斜率修改，bit[4:3]修改为10
//		}
//	}//再选出一个非7f大值
//	
//	
//	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK << 2) | 0x40);
//	printf("\r\n ACDConfigRegK_Val:%02x ",ACDConfigRegK_Val);	
//	
//	I_SI522A_SetBitMask(CommandReg, 0x06);		//关闭ADC_EXCUTE
//}

void TestADC_G(void)
{
	while(1)
	{
		unsigned char test=0; 
		I_SI522A_SetBitMask(CommandReg, 0x06);	//开启ADC_EXCUTE
		I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);
		test = I_SI522A_IO_Read(ACDConfigReg);
	printf("\r\n ACDConfigG_Val:%02x ",test);
		delay_ms(100);
	}
}

void PCD_ACD_Start(void)
{
	I_SI522A_IO_Write(DivIrqReg, 0x60);	//清中断，该处不清中断，进入ACD模式后会异常产生有卡中断。
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigJ << 2) | 0x40);		
	I_SI522A_IO_Write(ACDConfigReg, 0x55);	//Clear ACC_IRQ
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigA << 2) | 0x40);          //设置轮询时间
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegA_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigB << 2) | 0x40);					//设置相对模式或者绝对模式
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegB_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigC << 2) | 0x40);					//设置无卡场强值
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegC_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigD << 2) | 0x40);					//设置灵敏度，一般建议为4，在调试时，可以适当降低验证该值，验证ACD功能
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegD_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigH << 2) | 0x40);					//设置看门狗定时器时间
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegH_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigI << 2) | 0x40);         //设置ARI功能，在天线场强打开前1us产生ARI电平控制触摸芯片Si12T的硬件屏蔽引脚SCT
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegI_Val );	
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigK << 2) | 0x40);					//设置ADC的基准电压和放大增益
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegK_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigM << 2) | 0x40);					//设置监测ACD功能是否产生场强，意外产生可能导致读卡芯片复位或者寄存器丢失
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegM_Val );
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigO << 2) | 0x40);					//设置ACD模式下相关功能的标志位传导到IRQ引脚
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegO_Val );
	
	I_SI522A_IO_Write(ComIEnReg, ComIEnReg_Val);												//ComIEnReg，DivIEnReg   设置IRQ选择上升沿或者下降沿
	I_SI522A_IO_Write(DivIEnReg, DivIEnReg_Val);												
	
	I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigJ << 2) | 0x40);				//设置监测ACD功能下的重要寄存器的配置值，寄存器丢失后会立即产生中断
	I_SI522A_IO_Write(ACDConfigReg, ACDConfigRegJ_Val );								// 写非0x55的值即开启功能，写0x55清除使能停止功能。
	I_SI522A_IO_Write(CommandReg, 0xb0);	//进入ACD
}



char PCD_IRQ(void)
{
	unsigned char status_Si522ACD_IRQ;  
	unsigned char temp_Si522ACD_IRQ; 
	
	temp_Si522ACD_IRQ = I_SI522A_IO_Read(DivIrqReg);
	if	( temp_Si522ACD_IRQ & 0x40)	//ACD中断
	{
		I_SI522A_IO_Write(DivIrqReg, 0x40);		//Clear ACDIRq
		
		status_Si522ACD_IRQ =1;
		return status_Si522ACD_IRQ;
	}
	
	if ( temp_Si522ACD_IRQ & 0x20)	//ACD看门狗中断
	{
		I_SI522A_IO_Write(DivIrqReg, 0x20);		//Clear ACDTIMER_IRQ
		
		status_Si522ACD_IRQ = 2;
		return status_Si522ACD_IRQ;
	}
	
	I_SI522A_IO_Write(DivIrqReg, 0x40);		//Clear ACDIRq
	I_SI522A_IO_Write(DivIrqReg, 0x20);		//Clear ACDTIMER_IRQ
	I_SI522A_IO_Write(0x20, (0x0f << 2) | 0x40);		
	I_SI522A_IO_Write(0x0f, 0x0a);	//Clear OSCMon_IRQ,RFLowDetect_IRQ
	I_SI522A_IO_Write(0x20, (0x09 << 2) | 0x40);		
	I_SI522A_IO_Write(0x0f, 0x55);	//Clear ACC_IRQ

	return status_Si522ACD_IRQ = 0;

}
void pcd_acd_application(void)
{
		uint8_t RFlow_IRQ=0;
		uint8_t ACD_IRQ=0;
		uint8_t temp_G = 0;
		uint8_t i=0;
	
		//I_SI522A_IO_Write(0x20, (0x0f << 2) | 0x40);		
		RFlow_IRQ=I_SI522A_IO_Read(0x0f);	//RFLowDetect_IRQ
		ACD_IRQ=I_SI522A_IO_Read(DivIrqReg);
			pcd_acd_end();  //清除中断
	
	
	
		if((ACD_IRQ & 0x40)|(RFlow_IRQ & 0x01))
		{
		
			I_SI522A_SetBitMask(CommandReg, 0x06);	//开启ACD测量场强
			I_SI522A_IO_Read(CommandReg);
		  delay_us(130);
			I_SI522A_IO_Write(ACDConfigSelReg, (ACDConfigG << 2) | 0x40);   //采样ACD_G值
			temp_G = I_SI522A_IO_Read(ACDConfigReg);
			I_SI522A_SetBitMask(CommandReg, 0x06);
			printf(" ACD_G: %02x \r\n",temp_G);
			
				PcdReset();
			
		//		Pcd_Hard_Reset();
				
				PCD_SI522A_TypeA_Init();	//Reader模式的初始化
			#if 1
			
			
			PcdConfigISOType('A');
			I_SI522A_SiModifyReg(0x01, 0, 0x20);	// Turn on the analog part of receiver 
			for(i=0;i<3;i++)          //三次读卡
				{
					uint8_t ret=0;
					ret=PCD_SI522A_TypeA_GetUID(); 
					if(!ret)
					{
							flag_read_ic_ok=1;
						  break;
					}
				}
	

				
/////////////没有读到A卡就去读普通B卡///////////
//				PCD_SI522A_TypeB_Init();
//				PCD_SI522A_TypeB_GetUID();
//	
//		////////////读身份证///////////////		
//				PCD_SI522A_TypeB_Init();
//				PCD_CI523_IdentityCard_GetUID();
			#endif
			#if 0
			Card_Check();
			#endif
				PcdAntennaOff();
				delay_ms(200); //模拟读卡片后手拿开过程
				//LED1_Off;
				//LED2_Off;
		}
		else
		{
	//		pcd_acd_end();

	//		PCD_ACD_AutoCalc(); //自动获取0F_K寄存器和0F_C的阈值
			#if 0
			LED1_On;
			printf("this is a error!!!");
		//	delay_ms(200);
			LED1_Off;
			#endif
		}

}

void pcd_acd_end(void)
{
		I_SI522A_IO_Write(DivIrqReg, 0x40);		//Clear ACDIRq
		I_SI522A_IO_Write(DivIrqReg, 0x20);		//Clear ACDTIMER_IRQ
		I_SI522A_IO_Write(0x20, (0x0f << 2) | 0x40);		
		I_SI522A_IO_Write(0x0f, 0x0a);	//Clear OSCMon_IRQ,RFLowDetect_IRQ
		I_SI522A_IO_Write(0x20, (0x09 << 2) | 0x40);		
		I_SI522A_IO_Write(0x0f, 0x55);	//Clear ACC_IRQ
		
	//	I_SI522A_IO_Write(CommandReg,PCD_RESETPHASE);   //复位
}

void Card_Check(void)
{
		unsigned	char i;
		unsigned char statusA,statusB;//StatusC;
		unsigned char Block = 0x05;
//		statusA = ComReqA(WRITE,Block);
//		PcdHalt();
				for(i=0;i<3;i++)          //三次读卡
				{
		//			uint8_t ret=0;
					statusA = ComReqA(READ,Block);
					if(!statusA)
					{
							flag_read_ic_ok=1;
						  break;
					}
				}
	//	statusA = ComReqA(READ,Block);
		
		if( statusA == MI_OK)
		{
			//unsigned char i=0;
			//LED2_On;
			printf("\r\nUIDA:%02x %02x %02x %02x",UIDA[0],UIDA[1],UIDA[2],UIDA[3]);	
			#if 0
			printf("\r\n Block Read %2x: ",Block);
			for(i=0;i<16;i++)
			{
			printf(" %02x",CardReadBuf[i]);
			}
		#endif
			
		}
		else
		{
				statusB=ComReqB();
				if(statusB == MI_OK&&UIDB[0]==0x50)
				{
					

						//LED1_On;
						printf("\r\nUIDB:");
						for(i=1;i<5;i++)
						{
							
							printf(" %02x",UIDB[i]);
						}

				}
		}
		
		
				
			
		
}


unsigned char ComReqA(unsigned char rw, unsigned char Block)
{
		unsigned char status=0;
		PcdConfigISOType('A');
		if((status=PcdRequest(PICC_REQALL,ATQA)) != MI_OK)
		{
			
			return MI_ERR;
		}
		else
		{
			//	printf("\r\nRequest:ok  ATQA:%02x %02x",ATQA[0],ATQA[1]);
		}
		if((status=PcdAnticoll(UIDA, PICC_ANTICOLL1))!= MI_OK)
			return MI_ERR;

		
		#if 0    // 操作扇区
			if(PcdSelect(UIDA,&SAK)!=MI_OK)
				return MI_ERR;
			if(PcdAuthState(PICC_AUTHENT1A,Block,DefaultKeyABuf,UIDA)!= MI_OK)
				return MI_ERR;
			switch(rw)
			{
				case 0:status=PcdRead(Block,CardReadBuf);break;
				case 1:status=PcdWrite(Block,CardWriteBuf);break;
				default:break;
			}
		
		#endif
			
			return status;
		
}

unsigned char ComReqB(void)
{
		uint8_t status=MI_ERR;
		//uint8_t	i;
		uint8_t cnt;

		
		PcdConfigISOType('B');
		
		cnt = 3 ;  //多次轮询N次
		while(cnt--)
		{
			status = PcdRequestB(0x00, 0, 0, UIDB);
			if(status == MI_OK)
			{
				
						break;
//					ATQB[0] = 0x50; //恢复默认值
//					GetIdcardNum(UIDB); //获取卡号
			}
			
//			if(status == MI_COLLERR)   //有冲突，超过一张卡
//			{
//					if((status == PcdRequestB(0x08, 0, 2,ATQB)) != MI_OK)
//					{
//							for(i=1; i< 4; i++)
//							{	
//								if((status = PcdSlotMarker(i, ATQB)) == MI_OK)
//									{
//									break;
//									}
//							}
//							if(status == MI_OK)
//							{
//								break;
//							}
//					}
//					else
//					{
//						break;
//					}
//			}
//		}
//		if(status == MI_OK)
//		{
//			//typeB 106kbps
//			status = PcdAttriB(&ATQB[1], 0, ATQB[10]&0x0f, PICC_CID, ATQB);
//			
//			if(status == MI_OK)
//			{
//				
//					ATQB[0] = 0x50; //恢复默认值
//					GetIdcardNum(UIDB); //获取卡号
//			}
//		}
//		


}

	return 0;
}
#endif 

static int nfc_write_reg(struct nfc_data *nfc, u8 reg, u8 val) {
    u8 buf[2];
    buf[0] = reg; // 
    buf[1] = val;
    return i2c_master_send(nfc->client, buf, 2);
}

static int nfc_read_reg(struct nfc_data *nfc, u8 reg, u8 *val) {
    u8 buf[1];
    int ret;
    buf[0] = reg; // 
    ret = i2c_master_send(nfc->client, buf, 1);
    if (ret < 0) return ret;
    return i2c_master_recv(nfc->client, val, 1);
}


#if 0
static void nfc_read_data(struct nfc_data *nfc) {
    #if 0
	I_SI522A_IO_Write(CommandReg, 0x00);	
	PCD_IRQ_flagA = 0;	

	PcdAntennaOn();
	pcd_acd_application();

	PCD_SI522A_TypeA_Init();	
	PcdReset();
	PcdAntennaOff();
	delay_ms(2);
	//PcdReset();

	I_SI522A_IO_Write(TxControlReg,I_SI522A_IO_Read(TxControlReg) | 0x03);	
	//I_SI522A_IO_Write(TxControlReg,0x81);	
	delay_ms(5);     

	PCD_ACD_Start();  
	#endif
    dev_err(&nfc->client->dev, "NFC nfc_read_data\n");

    if (gdatalen <= 0) {
        nfc->card_present = false;
		nfc->status = -1;
        return;
    }
    dev_err(&nfc->client->dev, "NFC nfc_read_data 00\n");

	memcpy(nfc->data, gdata,gdatalen);
    nfc->data_len = gdatalen;
	nfc->datatype = gdatatype;
	nfc->status = 0;
    nfc->card_present = true;
    
    dev_err(&nfc->client->dev, "NFC: Card Found! data: %02X%02X%02X%02X%02X\n", 
           nfc->data[0], nfc->data[1], nfc->data[2], nfc->data[3], nfc->data[4]);
}
#endif

static int task_fn(void *data)
{
	struct nfc_data *nfc = (struct nfc_data *)data;
	unsigned char ret = 0;
	
    while (nfc->taskrunn) {	
	//printf(">>>sjl nfc ver=0x%x\n", I_SI522_IO_Read(VersionReg));		
		ret=PCD_SI522_TypeA_GetUID(); 
		
		mutex_lock(&nfc->lock);
		if (!ret){
			
			memcpy(nfc->data, gdata,gdatalen);
			nfc->data_len = gdatalen;
			nfc->datatype = gdatatype;
			nfc->status = 1;
			nfc->card_present = true;
			
			dev_err(&nfc->client->dev, "NFC: Card Found! data: %02X%02X%02X%02X%02X\n", 
				   nfc->data[0], nfc->data[1], nfc->data[2], nfc->data[3], nfc->data[4]);
			
		} else {
			nfc->card_present = false;
			nfc->status = 0;
		}	
		
		if (nfc->card_present) {
			wake_up_interruptible(&nfc->read_wait);			
			if (nfc->async_queue) {
				kill_fasync(&nfc->async_queue, SIGIO, POLL_IN);
			}
		}
		mutex_unlock(&nfc->lock);	
		msleep(100);
    }
	printf("sjl Thread:task_fn exit\n");
    return 0;
}
#if 0
static irqreturn_t nfc_irq_handler(int irq, void *dev_id) {
    struct nfc_data *nfc = (struct nfc_data *)dev_id;
    dev_err(&nfc->client->dev, "NFC nfc_irq_handler\n");
    mutex_lock(&nfc->lock);
    
    nfc_read_data(nfc);
    
    wake_up_interruptible(&nfc->read_wait);
    
    if (nfc->async_queue) {
        kill_fasync(&nfc->async_queue, SIGIO, POLL_IN);
    }
    
    mutex_unlock(&nfc->lock);
    
    return IRQ_HANDLED;
}
#endif 
static int nfc_open(struct inode *inode, struct file *filp) {
    filp->private_data = g_nfc;
    return 0;
}

static int nfc_fasync(int fd, struct file *filp, int mode) {
    struct nfc_data *nfc = filp->private_data;
    return fasync_helper(fd, filp, mode, &nfc->async_queue);
}

static ssize_t nfc_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) {
    struct nfc_data *nfc = filp->private_data;
    int ret;
    char info[132];
    
    if (filp->f_flags & O_NONBLOCK) {
        if (!nfc->card_present) return -EAGAIN;
    } else {
        wait_event_interruptible(nfc->read_wait, nfc->card_present);
    }
    
    mutex_lock(&nfc->lock);
	if (count < nfc->data_len + 4) {
		printf(">>>>nfc buffer too small error\n");
		ret = -EFAULT;
		goto out_unlock;
	}
	info[0] = nfc->datatype;
	info[1] = nfc->status;
	info[2] = (u8)(nfc->data_len >> 8);
	info[3] = (u8)(nfc->data_len);
	memcpy(&info[4], nfc->data, nfc->data_len);  
	ret = nfc->data_len + 4;
    if (copy_to_user(buf, info, nfc->data_len+4)) ret = -EFAULT;
    
    nfc->card_present = false; 
out_unlock:
    mutex_unlock(&nfc->lock);
    
    return ret;
}

static ssize_t nfc_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
    char write_buffer[128];
	int i = 0;
	
    if (count > sizeof(write_buffer))
        count = sizeof(write_buffer);
    
    printf(">>>nfc_write len=%d \n", (int)count);
	if (count > 128) {
		printf(">>>>nfc_write lengh overrange error\n");
		return -EFAULT;
	}
    if (copy_from_user(write_buffer, buf, count))
        return -EFAULT;
    
    for (i = 0; i < count; i++) {
		printf(">>>>nfc_write i=%d, data=0x%x\n", i, write_buffer[i]);
	}
    return count;
}

static const struct file_operations nfc_fops = {
    .owner = THIS_MODULE,
    .open = nfc_open,
    .read = nfc_read,
	.write = nfc_write,
    .fasync = nfc_fasync,
};

static int nfc_probe(struct i2c_client *client, const struct i2c_device_id *id) {
    int ret;
	int error;
    struct nfc_data *nfc;
	struct device *dev = &client->dev;
	struct device_node *np = client->dev.of_node;
    dev_err(&client->dev, "NFC Driver enter\n");
    nfc = devm_kzalloc(&client->dev, sizeof(struct nfc_data), GFP_KERNEL);
    if (!nfc) return -ENOMEM;
    
    nfc->client = client;
    g_nfc = nfc;
    i2c_set_clientdata(client, nfc);
    mutex_init(&nfc->lock);
    init_waitqueue_head(&nfc->read_wait);
    
    ret = alloc_chrdev_region(&nfc->devno, 0, 1, NFC_DEVICE_NAME);
    if (ret) return ret;
    
    cdev_init(&nfc->cdev, &nfc_fops);
    ret = cdev_add(&nfc->cdev, nfc->devno, 1);
    if (ret) goto err_cdev;
    
    nfc->cls = class_create(THIS_MODULE, NFC_DRIVER_NAME);
    device_create(nfc->cls, NULL, nfc->devno, NULL, NFC_DEVICE_NAME);
        
	nfc->irq_gpio = devm_gpiod_get_optional(dev, "irq", GPIOD_IN);
	if (IS_ERR(nfc->irq_gpio)) {
		error = PTR_ERR(nfc->irq_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(dev, "Failed to get %s GPIO: %d\n",
				"irq", error);
		goto err_irq;
	}
	gpiod_direction_input(nfc->irq_gpio);	

	nfc->pwr_gpio = devm_gpiod_get_optional(dev, "power", GPIOD_IN);
	if (IS_ERR(nfc->pwr_gpio)) {
		error = PTR_ERR(nfc->pwr_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(dev, "Failed to get %s GPIO: %d\n",
				"rst", error);
		goto err_irq;
	}
	gpiod_direction_output(nfc->pwr_gpio, 1);

	nfc->rst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_IN);
	if (IS_ERR(nfc->rst_gpio)) {
		error = PTR_ERR(nfc->rst_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(dev, "Failed to get %s GPIO: %d\n",
				"power", error);
		goto err_irq;
	}
	gpiod_direction_output(nfc->rst_gpio, 0);
	ret = of_property_read_u32(np, "irq-flags", &nfc->irq_flags);
	if (ret) {
		dev_info(dev,
			 "Failed get int-trigger-type from dts,set default\n");
		nfc->irq_flags = 2;
	}

   /* ret = devm_request_threaded_irq(&nfc->client->dev, nfc->client->irq,
					 NULL, nfc_irq_handler,
					 nfc->irq_flags | IRQF_ONESHOT , nfc->client->name, nfc);
	if (ret < 0) {
		dev_err(&client->dev, "Failed create work thread");
		goto err_irq;
	}	*/
	msleep(50);
    gpiod_direction_output(nfc->rst_gpio, 1);
	msleep(10);
	PCD_SI522_TypeA_Init();
	msleep(2);
	printk(KERN_ERR ">>>sjl NFC probe: ver=0x%x TxCtrl=0x%x RxSel=0x%x\n",
		I_SI522_IO_Read(VersionReg),
		I_SI522_IO_Read(TxControlReg),
		I_SI522_IO_Read(RxSelReg));
	nfc->taskrunn = 1;
	nfc->task = kthread_run(task_fn, nfc, "task_nfc_fn");
    if (IS_ERR(nfc->task)) {
		dev_err(&client->dev, "NFC nfc->task error \n");
		ret = -1;
        goto err_irq;
    }
	/*
	PcdReset();
	PcdAntennaOff();
	PcdAntennaOn();
	I_SI522A_IO_Write(TxControlReg,0X83);
	PCD_ACD_AutoCalc(); //自动获取0F_K寄存器和0F_C的阈值
	

	PCD_ACD_Start();   //初始化ACD配置寄存器，并且进入ACD模式
	PCD_IRQ_flagA = 0;
	*/
	dev_err(&nfc->client->dev, "NFC Driver Loaded\n");
    return 0;
err_irq:
    device_destroy(nfc->cls, nfc->devno);
    cdev_del(&nfc->cdev);
err_cdev:
    unregister_chrdev_region(nfc->devno, 1);
	i2c_set_clientdata(client, NULL);
	    dev_err(&client->dev, "NFC Driver failed\n");
    return ret;
}

static int nfc_remove(struct i2c_client *client) {
    struct nfc_data *nfc = i2c_get_clientdata(client);
    
    if (nfc->client->irq)
		free_irq(client->irq, nfc);
	if (nfc->task != NULL) {
		nfc->taskrunn = 0;
		kthread_stop(nfc->task);
	}
    cdev_del(&nfc->cdev);
    device_destroy(nfc->cls, nfc->devno);
    class_destroy(nfc->cls);
    unregister_chrdev_region(nfc->devno, 1);
	i2c_set_clientdata(client, NULL);
	mutex_destroy(&nfc->lock);
	devm_kfree(&client->dev, nfc);
    
    printk(KERN_INFO "NFC Driver Removed\n");
    return 0;
}

static int nfc_pm_suspend(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct nfc_data *nfc = i2c_get_clientdata(client);

	if (nfc) {
		dev_dbg(&nfc->client->dev, "Suspend by i2c pm.");
		gpiod_direction_output(nfc->rst_gpio, 0);
	}

	return 0;
}

static int nfc_pm_resume(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct nfc_data *nfc = i2c_get_clientdata(client);
	msleep(10);
	if (nfc) {
		dev_dbg(&nfc->client->dev, "Resume by i2c pm.");
		gpiod_direction_output(nfc->rst_gpio, 1);
	}
    msleep(5);
	PCD_SI522_TypeA_Init();
	printf(">>>sjl nfc_pm_resume nfc ver=0x%x\n", I_SI522_IO_Read(VersionReg));
	/*
	PcdReset();
	PcdAntennaOff();
	PcdAntennaOn();
	I_SI522A_IO_Write(TxControlReg,0X83);
	PCD_ACD_AutoCalc(); //自动获取0F_K寄存器和0F_C的阈值
	

	PCD_ACD_Start();   //初始化ACD配置寄存器，并且进入ACD模式
	PCD_IRQ_flagA = 0;	
	*/
	return 0;
}

static const struct dev_pm_ops nfc_pm_ops = {
	.suspend = nfc_pm_suspend,
	.resume  = nfc_pm_resume,
};

static const struct i2c_device_id nfc_device_id[] = { { NFC_DRIVER_NAME, 0 }, {} };
#ifdef CONFIG_OF
static const struct of_device_id nfc_match_ids[] = {
	{.compatible = "nfc,si522a",},
	{ },
};
#endif


static struct i2c_driver nfc_driver = {
	.probe		= nfc_probe,
	.remove		= nfc_remove,
	.id_table	= nfc_device_id,
	.driver = {
		.name	  = NFC_DRIVER_NAME,
		.owner	  = THIS_MODULE,
#ifdef CONFIG_OF
		.of_match_table = nfc_match_ids,
#endif
#if !defined(CONFIG_FB) && defined(CONFIG_PM)
		.pm		  = &nfc_pm_ops,
#endif
	},
};

static int __init nfc_init(void)
{
	s32 ret;

	pr_info("NFC driver installing..\n");
	ret = i2c_add_driver(&nfc_driver);

	return ret;
}

static void __exit nfc_exit(void)
{
	pr_info("NFC driver exited\n");
	i2c_del_driver(&nfc_driver);
}

module_init(nfc_init);
module_exit(nfc_exit);

MODULE_LICENSE("GPL");

