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

📄 tda8007.c

📁 单片机读写TDA8007
💻 C
📖 第 1 页 / 共 3 页
字号:

  // Write 5 byte command header
  for (index = 0;index < 4;)
    writeByte(buffer[index++]);
  writeLastByte(buffer[index++]);//index=5?

  while (1)
  {
    // Get procedure byte
    retval = readByte();
    if (retval < 0)
    {
      return retval;
    }
    val = retval;

#if DEBUG > 2
    printf("proc byte: %02bx\n",val);
#endif
    if ((val & 0xFE) == INS)//shield the B0
    {
      // ACK, send/receive all remaining bytes
      if (index < length)//if length > 5
      {

#if DEBUG > 2
        printf("write %d bytes\n",length-index);
#endif
        for (;index < (length-1);index++)
          	writeByte(buffer[index]);
        if (index < length)
          	writeLastByte(buffer[index++]);
        // NOTE: Does not support VPP state change
      }
      else
      {
#if DEBUG > 2
        printf("read bytes\n");
#endif
        // Read bytes up to Lc/P3 + 2
        rindex = 0;
        while ( (rindex < (buffer[4] + 2)) && ((retval = readByte()) >= 0) )
        {
          rbuffer[rindex++] = retval;
        }
        // return any error.
        if (retval < 0)
          return retval;
        break;
      }
    }
    else if ((val & 0xFE) == ~INS)
    {
      if (index < length)
      {
        // ACK, send/receive one remaining byte
        if (index < length)
          writeLastByte(buffer[index++]);
        // NOTE: Does not support VPP state change
      }
      else
      {
        // Read one byte or timeout????
        retval = readByte();
        if (retval < 0)
        {
          // If we get anything other than a timeout, return the error.
          if (retval != ERR_RECEIVE_TIMEOUT)
            return retval;
          break;
        }
        else
          rbuffer[rindex++] = retval;
      }
    }
    else if (val == 0x60)
    {
      // NULL
    }
    else if (((val & 0xF0) == 0x60) || ((val & 0xF0) == 0x90))
    {
      // SW1, get SW2
      rbuffer[rindex++]=val;
      val = readByte();
      if (retval < 0) return retval;
      rbuffer[rindex++]=val;
      break;
    }

  }

  return rindex;
}

/*
Send a message using T=0 or T=1 protocol
*/
int16_t dssc_sendAPDU(uint8_t *buffer,int16_t length,uint8_t *rbuffer)
{
  switch (TMode[currentSlot])
  {
    case 0:
#if DEBUG > 1
      printf("Mode T=%bd\n",TMode[currentSlot]);
#endif
      return dssc_sendAPDUT0(buffer,length,rbuffer);
      break;
    case 1:
#if DEBUG > 1
      printf("Mode T=%bd\n",TMode[currentSlot]);
#endif
      return dssc_sendAPDUT1(buffer,length,rbuffer);
      break;
    default:
#if DEBUG > 0
      printf("Invalid mode T=%bd\n",TMode[currentSlot]);
#endif
      return ERR_PROTOCOL_UNSUPPORTED;
      break;
  }
}

int16_t dssc_warmreset(uint8_t mode)
{
  uint8_t val;

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

  // Apply reset
  val = dssc_readregister(PCR);
  dssc_writeregister(PCR,val & ~PCR_RSTIN_MASK);

  // Call common getATR routine
  return dssc_ATRsequence(mode);
}

int16_t dssc_powerup(uint8_t mode, uint8_t voltage)
{
  uint8_t val;

  // Compile time setting of operating crystal frequency
#if ((CRYSTAL_FREQUENCY_8007 >= 1000000L) && (CRYSTAL_FREQUENCY_8007 <= 5000000L))
  // Set smartcard clock to 1/1 crystal
  dssc_writeregister(CCR,0x00);
#elif ((CRYSTAL_FREQUENCY_8007 >= 2000000L) && (CRYSTAL_FREQUENCY_8007 <= 10000000L))
  // Set smartcard clock to 1/2 crystal
  dssc_writeregister(CCR,0x01);
#elif ((CRYSTAL_FREQUENCY_8007 >= 4000000L) && (CRYSTAL_FREQUENCY_8007 <= 20000000L))
  // Set smartcard clock to 1/4 crystal
  dssc_writeregister(CCR,0x02);
#elif ((CRYSTAL_FREQUENCY_8007 >= 8000000L) && (CRYSTAL_FREQUENCY_8007 <= 40000000L))
  // Set smartcard clock to 1/8 crystal
  dssc_writeregister(CCR,0x03);
#else
  // Set smartcard clock to 1/2 internal oscillator (about 1.44MHz)
  // NOTE: Can only change CCR.2 when shifting to internal oscillator
  dssc_writeregister(CCR,0x01);
  dssc_writeregister(CCR,0x05);
  // Wait for internal oscillator to engage (check the MSR.CLKSW bit on page 18)

if ( DEBUG > 2 )
  printf("Waiting for Clock to switch\n");
  
  do
  {
    val = dssc_readregister(MSR);
  }
  while (!(val & MSR_CLKSW_MASK));
#endif

if ( DEBUG > 2)
  printf("Preparing to Apply Power1\n");

  // Set the power supply voltage
  val = dssc_readregister(PCR);
  // Clear 1.8V and 3V bits
  dssc_writeregister(PCR,val & ~(PCR_3V_5V_MASK|PCR_1V8_MASK));
  switch(voltage)
  {
    case POWERUP_5V:
      // Do nothing
      break;
    case POWERUP_3V:
      val = dssc_readregister(PCR);
      // Set 3V bit
      dssc_writeregister(PCR,val | PCR_3V_5V_MASK);
      break;
    case POWERUP_1p8V:
      val = dssc_readregister(PCR);
      // Set 1.8V bit
      dssc_writeregister(PCR,val | PCR_1V8_MASK);
      break;
    default:
      return ERR_POWERUP_VOLTAGE_INVALID;
      break;
  }

  // Apply reset
  val = dssc_readregister(PCR);
  dssc_writeregister(PCR,val & ~PCR_RSTIN_MASK);

if ( DEBUG > 2)
  printf("Preparing to Apply Power1\n");

  val = dssc_readregister(HSR);
  do
  {
    // Power the card, RST low, C4 and C8 high
    val = dssc_readregister(PCR);
    dssc_writeregister(PCR,val | (PCR_C8_MASK|PCR_C4_MASK|PCR_START_MASK));
    val = dssc_readregister(HSR);
    if (val & (HSR_PRTL2_MASK|HSR_PRTL1_MASK|HSR_PRL2_MASK|HSR_PRL1_MASK|HSR_PTL_MASK))
    {
#if DEBUG > 0
      printf("Power problem detected %02bx\n",val);
#endif
      dssc_powerdown();
      return ERR_POWERUP_INTERRUPTED;
    }
    val = dssc_readregister(PCR);
if ( DEBUG > 2 )
  printf(".");
  }
  while (!(val & PCR_START_MASK));

#if DEBUG > 1
  printf("Power is on\n");
#endif

//return 1;

  // Call common getATR routine
  return dssc_ATRsequence(mode);
}

int16_t dssc_ATRsequence(uint8_t mode)
{
	  uint8_t val;
	  uint8_t USRval;
	  uint8_t index;
	  uint8_t etucount = 0;
	  int16_t i;
	  uint8_t historicalBytes;
	  uint8_t expectedCharacters;
	  uint8_t interfaceIteration = 1;
	  uint8_t done = 0;
	  uint8_t check;
	  // Default to T=0 mode
	  uint8_t T = 0;
	  uint8_t curByte;
	
	  clearATRStruct(&lastATR[currentSlot]);
	  NAD[currentSlot] = 0;
	
	  // Reset the UART
	  val = dssc_readregister(CSR);
	  dssc_writeregister(CSR,val & ~CSR_nRIU_MASK);
	  // Remove UART reset
	  val = dssc_readregister(CSR);
	  dssc_writeregister(CSR,val | CSR_nRIU_MASK);
	  // Set FIFO to 1 byte
	  dssc_writeregister(FCR,0x00);
	  // Set divisor
	  dssc_writeregister(PDR,12);
	  // Set prescaler
	  dssc_writeregister(UCR2,0x00);
	
	  // Enable auto convention
	  val = dssc_readregister(UCR2);
	  dssc_writeregister(UCR2,val & ~UCR2_nAUTOCONV_MASK);
	
	  // Set SS bit
	  dssc_writeregister(UCR1,UCR1_SS_MASK);
	
	  // Wait 40000 to 45000 cycles to release reset
	  dssc_writeregister(TOC,0x00);
	  dssc_writeregister(TOR3,0x00);
	  dssc_writeregister(TOR2,0x6C);
	  dssc_writeregister(TOR1,0x00);
	  dssc_writeregister(TOC,0x61);
	
	  do
	  {
	/*
	    for (i=0;i<10000;i++)
	      {}
	    putchar('*');
	*/
	    val = dssc_readregister(USR);
	  }
	  while (!(val & USR_TOL3_MASK));
	
#if DEBUG > 2
	  printf("Set up counters for reset\n");
#endif
	
	  if (mode == POWERUP_ISO)
	  {
	    // Wait up to 40000 cycles for ATR to start
	    dssc_writeregister(TOC,0x00);
	    dssc_writeregister(TOR3,0x00);
	    dssc_writeregister(TOR2,0x78);
	    dssc_writeregister(TOR1,0x00);
	    dssc_writeregister(TOC,0x61);
	  }
	  else  // power up EMV
	  {
	    // Wait up to 40000 cycles for ATR to start and 19200 etu counter after first byte
	    dssc_writeregister(TOC,0x00);
	    dssc_writeregister(TOR3,0x00);
	    dssc_writeregister(TOR2,0x78);
	    dssc_writeregister(TOR1,0xC0);
	    dssc_writeregister(TOC,0x65);
	  }
	
#if DEBUG > 1
	  printf("Release reset\n");
#endif
	
	  // Release reset
	  val = dssc_readregister(PCR);
	  dssc_writeregister(PCR,val | PCR_RSTIN_MASK);
	
	  while (1)
	  {
#if DEBUG > 2
	    printf(".");
#endif
	    val = dssc_readregister(MSR);
	    // If we see the first character come in, break.
	    if (val & MSR_TBE_RBF_MASK)
	      break;
	
	    val = dssc_readregister(USR);
	
	  	if (val & (USR_PE_MASK|USR_FER_MASK|USR_OVR_MASK|USR_EA_MASK))
	    {
#if DEBUG > 0
	        printf("ATR error: USR=%02bx\n", val);
#endif
	        dssc_powerdown();
	        return ERR_POWERUP_ATR_INVALID; 
	  	}
	    if (val & USR_TOL3_MASK)
	    {
	      dssc_powerdown();
#if DEBUG > 0
	      printf("No ATR within timeout\n");
#endif
	      return ERR_POWERUP_ATR_TIMEOUT;
	    }
	  }
	
	  if (mode == POWERUP_ISO)
	  {
	    // Set up timer for 9600 etu between characters in ATR
	    dssc_writeregister(TOC,0x00);
	    dssc_writeregister(TOR3,0x25);
	    dssc_writeregister(TOR2,0x80);
	    dssc_writeregister(TOR1,0x00);
	    // Start timer
	    dssc_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
	    dssc_writeregister(TOC,0x05);
	    dssc_writeregister(TOR3,0x25);
	    dssc_writeregister(TOR2,0x80);
	    dssc_writeregister(TOR1,0xC0);
	    // Start timer
	    dssc_writeregister(TOC,0x65);
	  }
	
#if DEBUG > 1
	  printf("Getting ATR\n");
#endif
	
	  index = 0;
	
	  while (!done)
	  {
	    // Read UART status
	    USRval = dssc_readregister(USR);
	    {
	      // If receive buffer full
	      if (USRval & USR_TBE_RBF_MASK)
	      {
	        // Read and store ATR byte
	        val = dssc_readregister(URR);
	        curByte = val;
	        workingBuffer[index++] = val;
	        if (index == 1)
	        {
	          lastATR[currentSlot].TS = curByte;
#if DEBUG > 3
	          printf("TS: %02bx\n",curByte);
#endif
		      if ((curByte != 0x3f) && (curByte != 0x3b))
			  {
#if DEBUG > 0
	            printf("Invalid TS: %02bx\n",curByte);
#endif
	            dssc_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 DEBUG > 3
	          printf("TO: %02bx\n",curByte);
#endif
	        }
	        if (index > 2)
	        {
	          switch(expectedCharacters)
	          {
	            case 0x00:
	              // Historical characters
	              historicalBytes--;
#if DEBUG > 3
	              printf("hb: %02bx [%c] -%bd\n",curByte,curByte,historicalBytes);
#endif
	              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
#if DEBUG > 3
	              printf("TCK: %02bx\n",curByte);
#endif
	              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;
#if DEBUG > 3
	              printf("Got TA%bd %02bx\n",interfaceIteration,curByte);
#endif
	              lastATR[currentSlot].TA[interfaceIteration] = curByte;
	              break;
	
	            case 0x20:
	            case 0x60:
	            case 0xA0:
	            case 0xE0:
	              // TB case
	              expectedCharacters &= 0xD0;
#if DEBUG > 3
	              printf("Got TB%bd %02bx\n",interfaceIteration,curByte);
#endif
	              lastATR[currentSlot].TB[interfaceIteration] = curByte;
	              break;
	
	            case 0x40:
	            case 0xC0:
	              // TC case
	              expectedCharacters &= 0xB0;
#if DEBUG > 3
	              printf("Got TC%bd %02bx\n",interfaceIteration,curByte);
#endif
	              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;
	              }
#if DEBUG > 3
	              printf("Got TD%bd %02bx\n",interfaceIteration,curByte);
#endif
	              lastATR[currentSlot].TD[interfaceIteration] = curByte;
	              // If we get TD1, we have the first protocol selection
	              if ((interfaceIteration==1))
	              {
	                T=curByte & 0x0F;
#if DEBUG > 3
	                printf("T=%bd\n",T);
#endif
	              }
	              else
	              {
	                // Changing protocols is only valid under ISO (not allowed in EMV)
	                if (mode == POWERUP_ISO)
	                {
	                  if ((curByte & 0x0F) != T)
	                  {
	                    T=curByte & 0x0F;
#if DEBUG > 3
	                    printf("New T=%bd\n",T);
#endif
	                  }
	                }
	                else
	                  return ERR_POWERUP_ATR_INVALID;  // You cannot change T protocol under EMV
	              }
	              interfaceIteration++;
	              break;
	            default:
#if DEBUG > 0
	              printf("Bad expected chars %02bx\n",expectedCharacters);
#endif
	              dssc_powerdown();
	              return ERR_POWERUP_ATR_INVALID;
	              break;
	          }
	        }
	
	        if (mode == POWERUP_ISO)
	        {
	          // Reset timer for 9600 etu between characters in ATR
	          dssc_writeregister(TOC,0x00);
	          dssc_writeregister(TOR3,0x25);
	          dssc_writeregister(TOR2,0x80);
	          dssc_writeregister(TOR1,0x00);
	          // Start timer
	          dssc_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.
	          dssc_writeregister(TOC,0x05);
	          dssc_writeregister(TOR3,0x25);
	          dssc_writeregister(TOR2,0x80);
	

⌨️ 快捷键说明

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