⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tda8007.c

📁 TDA8007接口驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
			return 0;			
		}			
	}
}
/*************************************************************************
	功能:热复位
	参数:
			
	返回值:-1: error
			     0: OK		   			
**************************************************************************/
int tda_warmreset(uchar mode, unsigned char *rec_buf,
			int  * rec_len,
			int cardname)
{
  uchar val;

  // Check for power status
  val = tda_readregister(PCR);
  if (!(val & PCR_START_MASK))
    return ERR_POWERUP_VOLTAGE_INVALID;

  // Apply reset
  val = tda_readregister(PCR);
  tda_writeregister(PCR,val & ~PCR_RSTIN_MASK);

  // Call common getATR routine
  return tda_ATRsequence(mode, rec_buf, rec_len);
}
/*************************************************************************
	功能:复位应答
	参数:
			
	返回值:-1: error
			     0: OK		   			
**************************************************************************/
static int tda_ATRsequence(uchar mode, uchar *rec_buf, int  *rec_len)
{
	  volatile u8 val;
	  volatile u16 count;
	  uchar USRval;
	  uchar index;
	  	  
	  uchar historicalBytes = 0;
	  uchar expectedCharacters = 0;
	  uchar etucount = 0;
	  uchar interfaceIteration = 1;
	  uchar done = 0;
	  uchar check = 0;
	  uchar i = 0;
	  // Default to T=0 mode
	  uchar T = 0;
	  uint curByte;
	  //printk("tda_ATRsequence L1125\n");
	  clearATRStruct(&lastATR[currentSlot]);	
	  // Reset the UART
	  val = tda_readregister(CSR);
	  tda_writeregister(CSR,val & ~CSR_nRIU_MASK);
	  // Remove UART reset
	  val = tda_readregister(CSR);
	  tda_writeregister(CSR,val | CSR_nRIU_MASK);
	  // Set FIFO to 1 byte; parity Error Count 3 byte
	  tda_writeregister(FCR,0x00);
	  tda_writeregister(FCR,FCR_PEC0_MASK | FCR_PEC1_MASK);
	  // Set divisor
	  tda_writeregister(PDR,12);
	  // Set prescaler
	  tda_writeregister(UCR2,0x00);	
	  // Enable auto convention
	  val = tda_readregister(UCR2);
	  tda_writeregister(UCR2,val & ~UCR2_nAUTOCONV_MASK);
	
	  // Set SS bit
	  tda_writeregister(UCR1,UCR1_SS_MASK);
	
	  // Wait 40000 to 45000 cycles to release reset
	  //printk("wait counters for reset\n");
	  tda_writeregister(TOC, 0x00);
	  delay_us(5);
	  tda_writeregister(TOR3, 0x00);
	  delay_us(5);
	  tda_writeregister(TOR2, 0x6C);
	  delay_us(5);
	  tda_writeregister(TOR1, 0x00);
	  delay_us(5);
	  tda_writeregister(TOC, 0x61);
	  //delay_us(5);
	  count = 0;
	  printk("TOC = %x\n",tda_readregister(TOC));	
	  do
	  {
	    if(++count > 5000)
	    {
	    	printk("Time 2 not end!\n");
	    	break;
	    }
	    val = tda_readregister(USR);
	  }while (!(val & USR_TOL3_MASK));
	
	  printk("Set up counters for reset\n");
	
	  if (mode == POWERUP_ISO)
	  {
	    // Wait up to 40000 cycles for ATR to start
	    tda_writeregister(TOC,0x00);
	    delay_us(5);
	    tda_writeregister(TOR3,0x00);
	    delay_us(5);
	    tda_writeregister(TOR2,0x78);
	    delay_us(5);
	    tda_writeregister(TOR1,0x00);
	    delay_us(5);
	    tda_writeregister(TOC,0x61);
	  }
	  else  // power up EMV
	  {
	    // Wait up to 40000 cycles for ATR to start and 19200 etu counter after first byte
	    tda_writeregister(TOC,0x00);
	    tda_writeregister(TOR3,0x00);
	    tda_writeregister(TOR2,0x78);
	    tda_writeregister(TOR1,0xC0);
	    tda_writeregister(TOC,0x65);
	  }
	
	  //printk("Release reset\n");
	  val = tda_readregister(PCR);
	  tda_writeregister(PCR,val | PCR_RSTIN_MASK);
	
	  while (1)
	  {
	    val = tda_readregister(MSR);
	    // If we see the first character come in, break.
	    if (val & MSR_TBE_RBF_MASK)break;
	      	
	    val = tda_readregister(USR);	
	  	if (val & (USR_PE_MASK|USR_FER_MASK|USR_OVR_MASK|USR_EA_MASK))
	    {
	       tda_powerdown();
	       if(val & USR_PE_MASK)
	       {
	       		printk("ATR error: PARITY1_ERR\n");
	       		return PARITY1_ERR;
	       }
	       else
	       {
	       		printk("ATR error: USR=0x%2x\n", val);          
	          return ERR_POWERUP_ATR_INVALID;
	       }
	        
	  	}
	    if (val & USR_TOL3_MASK)
	    {
	      tda_powerdown();
	      printk("No ATR within timeout\n");
	      return ERR_POWERUP_ATR_TIMEOUT;
	    }
	  }//end 1	
	  if (mode == POWERUP_ISO)
	  {
	    // Set up timer for 9600 etu between characters in ATR
	    tda_writeregister(TOC,0x00);
	    delay_us(5);
	    tda_writeregister(TOR3,0x25);
	    delay_us(5);
	    tda_writeregister(TOR2,0x80);
	    delay_us(5);
	    tda_writeregister(TOR1,0x00);
	    delay_us(5);
	    // Start timer
	    tda_writeregister(TOC,0x61);
	  }
	  else  // mode is EMV
	  {
	    // Set up timer for 9600 etu between characters in ATR, and
	    // maximum of 19200 etu for whole ATR
	    tda_writeregister(TOC,0x05);
	    tda_writeregister(TOR3,0x25);
	    tda_writeregister(TOR2,0x80);
	    tda_writeregister(TOR1,0xC0);
	    // Start timer
	    tda_writeregister(TOC,0x65);
	  }//end if
	
	  //printk("Getting ATR\n");
	
	  index = 0;
	  	
	  while (!done)
	  {
	    // Read UART status
	    USRval = tda_readregister(USR);
	    {
	      // If receive buffer full
	      if (USRval & USR_TBE_RBF_MASK)
	      {
	        // Read and store ATR byte
	        val = tda_readregister(URR);
	        curByte = val;
	        rec_buf[index++] = val;
	        if (index == 1)
	        {
	          lastATR[currentSlot].TS = curByte;
			      if ((curByte != 0x3f) && (curByte != 0x3b))
				    {
		            tda_powerdown();
		            return ERR_POWERUP_ATR_INVALID;
				    }
				    check = 0;
	        }
		    	else
			      check ^= curByte;
	        if (index == 2)
	        {
	          historicalBytes = curByte & 0x0F;
	          expectedCharacters = curByte & 0xF0;
	          lastATR[currentSlot].T0 = curByte;
	        }
	        if (index > 2)
	        {
	          switch(expectedCharacters)
	          {
	            case 0x00:
	              // Historical characters
	              historicalBytes--;

	              lastATR[currentSlot].Historical[lastATR[currentSlot].HistoricalLength++] = curByte;
	              if (historicalBytes == 0)
	              {
	                if (T == 0)
	                {
	                  done = 1;
	                }
	                else
	                  expectedCharacters = 0x01;  // Go to checksum state
	              }
	            break;
	            case 0x01:
	              // TCK case                
	              lastATR[currentSlot].TCK = curByte;
	              done = 1;
	              break;
	
	            case 0x10:
	            case 0x30:
	            case 0x50:
	            case 0x70:
	            case 0x90:
	            case 0xB0:
	            case 0xD0:
	            case 0xF0:
	              // TA case
	              expectedCharacters &= 0xE0;
	              lastATR[currentSlot].TA[interfaceIteration] = curByte;
	              break;
	
	            case 0x20:
	            case 0x60:
	            case 0xA0:
	            case 0xE0:
	              // TB case
	              expectedCharacters &= 0xD0;
	              lastATR[currentSlot].TB[interfaceIteration] = curByte;
	              break;
	
	            case 0x40:
	            case 0xC0:
	              // TC case
	              expectedCharacters &= 0xB0;
	              lastATR[currentSlot].TC[interfaceIteration] = curByte;
	              break;
	
	            case 0x80:
	              // TD case
	              expectedCharacters=(curByte&0xF0);
	              // Handle zero historical characters
	              if ((expectedCharacters == 0x00) && (historicalBytes == 0))
	              {
	                if (T == 0)
	                {
	                  done = 1;
	                }
	                else
	                  expectedCharacters = 0x01;
	              }

	              lastATR[currentSlot].TD[interfaceIteration] = curByte;
	              // If we get TD1, we have the first protocol selection
	              if ((interfaceIteration==1))
	              {
	                T = curByte & 0x0F;
	              }
	              else
	              {
	                // Changing protocols is only valid under ISO (not allowed in EMV)
	                if (mode == POWERUP_ISO)
	                {
	                  if ((curByte & 0x0F) != T)
	                  {
	                    T = curByte & 0x0F;
	                  }
	                }
	                else
	                  return ERR_POWERUP_ATR_INVALID;  // You cannot change T protocol under EMV
	              }
	              interfaceIteration++;
	              break;
	            default:
	              tda_powerdown();
	              return ERR_POWERUP_ATR_INVALID;
	              break;
	          }
	        }	
	        if (mode == POWERUP_ISO)
	        {
	          // Reset timer for 9600 etu between characters in ATR
	          tda_writeregister(TOC,0x00);
	          delay_us(5);
	          tda_writeregister(TOR3,0x25);
	          delay_us(5);
	          tda_writeregister(TOR2,0x80);
	          delay_us(5);
	          tda_writeregister(TOR1,0x00);
	          delay_us(5);
	          // Start timer
	          tda_writeregister(TOC,0x61);
	        }
	        else  // mode is EMV
	        {
	          // Set up timer for 9600 etu between characters in ATR
	          // Don't modify TOR1 as it is in auto-reload mode.
	          tda_writeregister(TOC,0x05);
	          tda_writeregister(TOR3,0x25);
	          tda_writeregister(TOR2,0x80);	
	          // Start timer
	          tda_writeregister(TOC,0x65);
	        }
	      }
	    }
	
	    // Read Timer status
	    if (USRval & USR_TOL3_MASK)
	    {
	      printk("Character waiting timeout\n");
	      
	      tda_powerdown();
	      return ERR_POWERUP_ATR_TIMEOUT;
	    }
	    if ((mode == POWERUP_EMV) && (USRval & USR_TOL1_MASK))
	    {
	      // If 192 ETU rollover, increment total count
	      etucount++;
	      // If we exceed 192 * 100 or 19200 etu, we fail as the whole ATR has not come
	      if (etucount > 100)
	      {
	        printk("ATR waiting timeout\n");	        
	        tda_powerdown();
	        return ERR_POWERUP_ATR_TIMEOUT;
	      }
	    }
	  }//end !done
	  	
	  // If we are in T=1 protocol, we get a LRC (xor checksum) at the end
	  if (T == 1)
	  {
	    if (check != 0)
	    {
	      printk("LRC failed: 0x%2x\n",check);
	      tda_powerdown();
	      return ERR_POWERUP_ATR_CRC_FAILURE;
	    }
	  }
	
	  // Set ATR length for the ATR received
	  *rec_len = index;
	  // Set T protocol mode
	  TMode[currentSlot] = T;
	
	  // Set the 8007 UCR1.PROT mode according to T value
	  val = tda_readregister(UCR1);
	  if (T == 0)
	    tda_writeregister(UCR1,val & ~UCR1_PROT_MASK);
	  else
	    tda_writeregister(UCR1,val | UCR1_PROT_MASK);
	
	  // Set extra guard time if present in TC1, else use guard time of 0
	  if (lastATR[currentSlot].TC[1] != -1)
	    tda_writeregister(GTR,lastATR[currentSlot].TC[1]);
	  else
	    tda_writeregister(GTR,0xff);
	  // Set WWT if present in TC2 (only used for T=0), ISO7816 8.2
	  if (lastATR[currentSlot].TC[2] != -1)
	    WWT[currentSlot] = lastATR[currentSlot].TC[2] * 960;
	  else
	    WWT[currentSlot] = 960 * 10;
	

	  printk("WWT: %ld\n",WWT[currentSlot]);

	
	  if (mode == POWERUP_EMV)
	  {
	    if (lastATR[currentSlot].TB[3] == -1)
	    {
	      // FIXME: Should we power down here?  It is an EMV violation
	      tda_powerdown();
	      return ERR_POWERUP_ATR_INVALID;
	    }
	    else
	    {
	      val = lastATR[currentSlot].TB[i] & 0x0F;
	      // Fail if CWI is out of range
	      if (val > 5)
	      {
	        // FIXME: Should we power down here?  It is an EMV violation
	        tda_powerdown();
	        return ERR_POWERUP_ATR_INVALID;
	      }
	      val = (lastATR[currentSlot].TB[i] & 0x0F) >> 4;
	      // Fail if BWI is out of range
	      if (val > 4)
	      {
	        // FIXME: Should we power down here?  It is an EMV violation
	        tda_powerdown();
	        return ERR_POWERUP_ATR_INVALID;
	      }
	    }
	  }
	
	  // Set default values for CWT and BWT, ISO7816 9.5.3.1 and 9.5.3.2
	  CWT[currentSlot] = 11 + (1 << 13);
	  for (i = 3;i < 8;i++)
	  {
	    // Set CWT and BWT if present in TBi
	    // FIXME: Check this algorithm again!
	    if (lastATR[currentSlot].TB[i] != -1)
	    {
	      val = lastATR[currentSlot].TB[i] & 0x0F;
	      CWT[currentSlot] = 11 + (1 << val);
	      val = (lastATR[currentSlot].TB[i] & 0x0F) >> 4;
	      if (val > 9)
	      {
	        // FIXME: Should we power down here?  It is an ISO7816 violation.
	        tda_powerdown();
	        return ERR_POWERUP_ATR_INVALID;
	      }
	      break;
	    }
	  }

	  printk("CWT: %ld\n",CWT[currentSlot]);
	  	
	  return 0;
}
/*************************************************************************
	功能:
	参数:
			
	返回值:-1: error
			     0: OK		   			
**************************************************************************/
static int tda_powerdown(void)
{
  u8 val;

  // Power down the card
  val = tda_readregister(PCR);
  tda_writeregister(PCR,val & ~PCR_START_MASK);

  return 0;
}
/*************************************************************************
	功能:check card
	参数:
			
	返回值:-1: error
			     0: OK		   			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -