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

📄 tda8007.c

📁 tda8007驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
          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                    
**************************************************************************/   
static int tda_checkpresence(uchar slot)   
{   
  u8 val;   
   
  val = tda_readregister(MSR);   
   
  switch(slot)   
  {   
    case 1:   
      if (val & MSR_PR1_MASK) return 1;   
      break;   
    case 2:   
      if (val & MSR_PR2_MASK) return 1;   
      break;   
    default:   
      return ERR_INVALID_SLOT;   
      break;   
  }   
  return 0;   
}   
/*************************************************************************  
    功能:select card  
    参数:  
              
    返回值:-1: error  
                 0: OK                    
**************************************************************************/   
static int tda_selectcard(uchar slot)   
{   
      u8 val;   
       
      val = tda_readregister(CSR);   
      switch (slot)    
      {   
        case 1:   
          // Select appropriate smartcard and clear other card selects    
          tda_writeregister(CSR, (val & ~(CSR_SC3_MASK | CSR_SC2_MASK))|CSR_SC1_MASK);   
             
          if(tda_checkpresence(slot) < 0) return NO_CARD_ERR;    
          break;   
        case 2:   
          // Select appropriate smartcard and clear other card selects    
          tda_writeregister(CSR,(val & ~(CSR_SC3_MASK|CSR_SC1_MASK))|CSR_SC2_MASK);   

⌨️ 快捷键说明

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