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

📄 ds8007.c.bak

📁 DS8007 双智能卡读卡DEMO源代码。
💻 BAK
📖 第 1 页 / 共 2 页
字号:
	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
	{
		val = dssc_readregister(USR);
	}
	while (!(val & USR_TOL3_MASK));

	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);
  	}

	// Release reset
	val = dssc_readregister(PCR);
	dssc_writeregister(PCR,val | PCR_RSTIN_MASK);

	while (1)
	{
		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))
		{
			dssc_powerdown();
			return ERR_POWERUP_ATR_INVALID; 
		}
		if (val & USR_TOL3_MASK)
		{
			dssc_powerdown();
			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);
	}

	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 ((curByte != 0x3f) && (curByte != 0x3b))
					{
						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 (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:
						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);

				// Start timer
				dssc_writeregister(TOC,0x65);
        	}
      	}
    }

	// Read Timer status
	if (USRval & USR_TOL3_MASK)
	{
		dssc_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)
		{
			dssc_powerdown();
			return ERR_POWERUP_ATR_TIMEOUT;
		}
	}
	}

	// If we are in T=1 protocol, we get a LRC (xor checksum) at the end
	if (T==1)
	{
		if (check != 0)
		{
			dssc_powerdown();
			return ERR_POWERUP_ATR_CRC_FAILURE;
		}
	}

	// Set ATR length for the ATR received
	ATRLength[currentSlot] = index;
	// Set T protocol mode
	TMode[currentSlot] = T;

	// Set the DS8007 UCR1.PROT mode according to T value
	val = dssc_readregister(UCR1);
	if (T == 0)
		dssc_writeregister(UCR1,val & ~UCR1_PROT_MASK);
	else
		dssc_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)
    	dssc_writeregister(GTR,lastATR[currentSlot].TC[1]);
	else
		dssc_writeregister(GTR,0x00);

	// Set the EDC type (either LRC or CRC)
  	EDCtype[currentSlot] = EDC_TYPE_LRC;  // Default to LRC if not told otherwise.
	for (i = 3;i < 8;i++)
	{
		if (lastATR[currentSlot].TC[3] != -1)
	    { 
			EDCtype[currentSlot] = (lastATR[currentSlot].TC[3] & 0x01)?EDC_TYPE_CRC:EDC_TYPE_LRC;
		}
	}

	// Set IFSC (max segment size of card) if TA3 present (only used for T=1 protocol)
	if (lastATR[currentSlot].TA[3] != -1)
	{
		val = lastATR[currentSlot].TA[3];
		if ((val < 0x10) || (val == 0xFF))
		{
			dssc_powerdown();
			return ERR_POWERUP_ATR_INVALID;
		}
		IFSC[currentSlot] = val;
	}
	else
		IFSC[currentSlot] = 0x20;  // Default for IFSC is 0x20 according to EMV 4.1 8.3.3.9 and ISO7816 9.5.2.1

	// 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;

	if (mode == POWERUP_EMV)
	{
		if (lastATR[currentSlot].TB[3] == -1)
		{
			dssc_powerdown();
			return ERR_POWERUP_ATR_INVALID;
		}
    	else
		{
			val = lastATR[currentSlot].TB[i] & 0x0F;
			// Fail if CWI is out of range
			if (val > 5)
			{
				dssc_powerdown();
				return ERR_POWERUP_ATR_INVALID;
			}
			val = (lastATR[currentSlot].TB[i] & 0x0F) >> 4;
			// Fail if BWI is out of range
			if (val > 4)
			{
			dssc_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);
	BWT[currentSlot] = 11 + (1 << 4) * 960;
	for (i = 3;i < 8;i++)
	{
		// Set CWT and BWT if present in TBi
	    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)
			{
				dssc_powerdown();
				return ERR_POWERUP_ATR_INVALID;
			}
			BWT[currentSlot] = 11 + (1 << val) * 960;
			break;
		}
	}
	return 0;
}

int16_t dssc_powerdown()
{
	uint8_t val;

	// Power down the card
	val = dssc_readregister(PCR);
	dssc_writeregister(PCR,val & ~PCR_START_MASK);

	return 0;
}

int16_t dssc_selectcard(uint8_t slot)
{
	uint8_t val;

	val = dssc_readregister(CSR);
	switch (slot) 
	{
    case 1:
		// Select appropriate smartcard and clear other card selects
		dssc_writeregister(CSR,val & ~(CSR_SC3_MASK|CSR_SC2_MASK) | CSR_SC1_MASK);
		break;
	case 2:
		// Select appropriate smartcard and clear other card selects
		dssc_writeregister(CSR,val & ~(CSR_SC3_MASK|CSR_SC1_MASK) | CSR_SC2_MASK);
		break;
	case 3:
		// Select appropriate smartcard and clear other card selects
		dssc_writeregister(CSR,val & ~(CSR_SC2_MASK|CSR_SC1_MASK) | CSR_SC3_MASK);
		break;
	default:
		return ERR_INVALID_SLOT;
	}

	// Set global slot identifier value
	currentSlot = slot-1;

	return 0;
}

int16_t dssc_checkpresence(uint8_t slot)
{
	uint8_t val;

	val = dssc_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;
}

/*
Library initialization
*/
int16_t dssc_init()
{
	uint8_t val;

	// Reset the UART
	dssc_writeregister(CSR,0x00);

	// Select smart card slot 1
	dssc_writeregister(CSR,CSR_SC1_MASK);

	// Make sure card is powered down
	val = dssc_readregister(PCR);
	dssc_writeregister(PCR,val & ~PCR_START_MASK);

	// Select smart card slot 2
	dssc_writeregister(CSR,CSR_SC2_MASK);

	// Make sure card is powered down
	val = dssc_readregister(PCR);
	dssc_writeregister(PCR,val & ~PCR_START_MASK);

	// Select smart card slot 3
	dssc_writeregister(CSR,CSR_SC3_MASK);

	// Deselect all cards
	dssc_writeregister(CSR,0x00);

	return 0;
}

int16_t dssc_getATRbuffer(uint8_t *buff, int16_t length)
{
	memcpy(buff,workingBuffer,(length<ATRLength[currentSlot])?length:ATRLength[currentSlot]);
	return ATRLength[currentSlot];
}

void dssc_getATR(struct ATR *userATR)
{
	memcpy(userATR,&lastATR[currentSlot],sizeof(struct ATR));
}

#pragma REGPARMS
uint8_t dssc_readregister(uint8_t address)
{
	idata uint8_t rAddress, toReturn;
#ifdef DEBUG_CRED
	idata uint8_t count = 0;
#endif
	rAddress = address;

	//ds5250 DMOS |= 0x01;
	RPCTL |= 0x20;
	P1 &= 0xEF;        // Happy CS for DS8007 on Eval Refrence Design
	switch (rAddress)
	{
    case URR:
		// If reading URR, check the CRED bit in MSR so that
		// we don't overrun the DS8007.  See MSR.CRED bit description on page
		// 18 of DS8007 spec.
#ifdef DEBUG_CRED
		while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK))
		{
        	// If card de-powers exit with zero return value.
	        if ((BASE_ADDRESS[PCR] & 0x01) == 0)
			{
				//ds5250 DMOS &= 0xFE;
				P1 |= 0x10;        // Happy CS for DS8007 on Eval Refrence Design

				RPCTL &= 0xDF;
		        return 0;
			}

			count++;
			if (count == 30000)
			{
				printf("CRED read locked up on: %02bx\n",rAddress);
				printf("PCR: %02bx\n",BASE_ADDRESS[PCR]);
				printf("HSR: %02bx\n",BASE_ADDRESS[HSR]);
				count = 0;
			}
		}
#else
		while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK))
		{
			// If card de-powers exit with zero return value.
			if ((BASE_ADDRESS[PCR] & 0x01) == 0)
	        {
				//ds5250 DMOS &= 0xFE;
				P1 |= 0x10;        // Happy CS for DS8007 on Eval Refrence Design

				RPCTL &= 0xDF;
          		return 0;
			}
		}
#endif
			break;
		default:
			break;
	}

	toReturn = BASE_ADDRESS[rAddress];
	//ds5250 DMOS &= 0xFE;
	P1 |= 0x10;        // Happy CS for DS8007 on Eval Refrence Design

  	RPCTL &= 0xDF;
	return toReturn;

}

void dssc_writeregister(uint8_t address,uint8_t value)
{
	idata uint8_t rAddress, rValue ;
#ifdef DEBUG_CRED
  	idata int count = 0;
#endif
	rAddress = address;
	rValue = value;

	//ds5250 DMOS |= 0x01;
  	RPCTL |= 0x20;
	P1 &= 0xEF;        // Happy CS for DS8007 on Eval Refrence Design
  	switch (rAddress)
  	{
	case TOC:
    case UTR:
		// If writing TOC or UTR, check the CRED bit in MSR so that
		// we don't overrun the DS8007.  See MSR.CRED bit description on page
		// 18 of DS8007 spec.
#ifdef DEBUG_CRED
		while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK))
		{
			// If card de-powers exit with zero return value.
	        if ((BASE_ADDRESS[PCR] & 0x01) == 0)
        	{
				//ds5250 DMOS &= 0xFE;
				P1 |= 0x10;        // Happy CS for DS8007 on Eval Refrence Design

				RPCTL &= 0xDF;
				return;
			}
        	count++;
			if (count == 30000)
			{
				printf("CRED write locked up on: %02bx\n",rAddress);
				printf("PCR: %02bx\n",BASE_ADDRESS[PCR]);
				printf("HSR: %02bx\n",BASE_ADDRESS[HSR]);
				count = 0;
			}
		}
#else
		while (!(BASE_ADDRESS[MSR] & MSR_CRED_MASK));
#endif
		break;
	    default:
      		break;
	}
	BASE_ADDRESS[rAddress] = rValue;

	//ds5250 DMOS &= 0xFE;
	P1 |= 0x10;        // Happy CS for DS8007 on Eval Refrence Design
	RPCTL &= 0xDF;

}

⌨️ 快捷键说明

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