From 4631e16a2666b8a868b3eb0c0baa4040b002c3b6 Mon Sep 17 00:00:00 2001
From: Philipp Claves <pclaves@web.de>
Date: Sun, 6 Nov 2011 00:19:01 +0100
Subject: [PATCH] CardReader: Handle card removal during ATR read.

---
 CardReader/ISO7816-reader.c | 66 +++++++++++++++++++++++++++++--------
 CardReader/ISO7816-reader.h | 12 ++++---
 2 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/CardReader/ISO7816-reader.c b/CardReader/ISO7816-reader.c
index 6113cf7..8b59cae 100644
--- a/CardReader/ISO7816-reader.c
+++ b/CardReader/ISO7816-reader.c
@@ -19,8 +19,10 @@ uint16_t rate_adjustment_di[16] = {DI_RFU, 1,2,4,8,16,32,64, 12,20, DI_RFU, DI_R
 #define STOPBITS 2
 #include "../common/serial.h"
 
-uint16_t char_guard_time;
-uint16_t block_guard_time;
+uint16_t ISO7816_read_byte(void);
+
+// uint16_t char_guard_time;
+// uint16_t block_guard_time;
 
 uint8_t seq_number = 0;
 
@@ -82,15 +84,20 @@ uint8_t ISO7816_readATR(ISO7816_ATR* atr){
 	
 	while (c != 0x3B){
 		timeout = 2000;
-		while (!CARD_data_available() && timeout != 0) {timeout--; _delay_ms(1);}
+		while (!CARD_data_available() && ISO7816_is_card_present() && timeout != 0) {timeout--; _delay_ms(1);}
+		if (!ISO7816_is_card_present()) return ERR_ATR_CARD_REMOVED;
 		if (timeout == 0) return ERR_ATR_TIMEOUT;
 		c = CARD_read_char();
-		printf("%02X ", c);
 	}
 	atr->initial_char = c;
 	
+	uint16_t ret;
+	
 	//Read T0
-	c = CARD_read_char();
+	ret = ISO7816_read_byte();
+	if (!ISO7816_is_card_present()) return ERR_ATR_CARD_REMOVED;
+	if (ret & 0xFF00) return ERR_ATR_TIMEOUT;
+	c = ret & 0xFF;
 	checksum ^= c;
 	atr->t0 = c;
 	
@@ -100,11 +107,33 @@ uint8_t ISO7816_readATR(ISO7816_ATR* atr){
 	while (next_interface_bytes){
 		if (i >= ATR_MAX_INTERFACE_BYTE_SETS) return ERR_TOO_MANY_ATR_INTERFACE_BYTES;
 		
-		if (next_interface_bytes & 0x01) {c = CARD_read_char(); checksum ^= c; atr->interface_bytes[i].ta = c;}
-		if (next_interface_bytes & 0x02) {c = CARD_read_char(); checksum ^= c; atr->interface_bytes[i].tb = c;}
-		if (next_interface_bytes & 0x04) {c = CARD_read_char(); checksum ^= c; atr->interface_bytes[i].tc = c;}
+		if (next_interface_bytes & 0x01) {
+			ret = ISO7816_read_byte();
+			if (ret & 0xFF00) return ret;
+			c = ret & 0xFF;
+			checksum ^= c;
+			atr->interface_bytes[i].ta = c;
+		}
+		
+		if (next_interface_bytes & 0x02) {
+			ret = ISO7816_read_byte();
+			if (ret & 0xFF00) return ret;
+			c = ret & 0xFF;
+			checksum ^= c;
+			atr->interface_bytes[i].tb = c;
+		}
+		
+		if (next_interface_bytes & 0x04) {
+			ret = ISO7816_read_byte();
+			if (ret & 0xFF00) return ret;
+			c = ret & 0xFF;
+			checksum ^= c;
+			atr->interface_bytes[i].tc = c;
+		}
 		if (next_interface_bytes & 0x08) {
-			c = CARD_read_char();
+			ret = ISO7816_read_byte();
+			if (ret & 0xFF00) return ret;
+			c = ret & 0xFF;
 			checksum ^= c;
 			atr->interface_bytes[i].td = c;
 			next_interface_bytes = c >> 4;
@@ -114,11 +143,20 @@ uint8_t ISO7816_readATR(ISO7816_ATR* atr){
 		i++;
 	}
 	for (i = 0; i < num_hist_bytes; i++){
-		c = CARD_read_char();
+		ret = ISO7816_read_byte();
+		if (!ISO7816_is_card_present()) return ERR_ATR_CARD_REMOVED;
+		if (ret & 0xFF00) return ERR_ATR_TIMEOUT;
+		c = ret & 0xFF;
+		
 		checksum ^= c;
 		atr->historical_bytes[i] = c;
 	}
-	c = CARD_read_char();
+	
+	ret = ISO7816_read_byte();
+	if (!ISO7816_is_card_present()) return ERR_ATR_CARD_REMOVED;
+	if (ret & 0xFF00) return ERR_ATR_TIMEOUT;
+	c = ret & 0xFF;
+	
 	atr->checksum = c;
 	if (checksum != c) return ERR_ATR_CHECKSUM_FAIL;
 	
@@ -211,8 +249,10 @@ uint8_t ISO7816_readATR(ISO7816_ATR* atr){
 
 uint16_t ISO7816_read_byte(void){
 	uint16_t timeout = 30000; //3 sec
-	while(!CARD_data_available() && timeout) {timeout--; _delay_us(100);}
-	if (timeout > 0){
+	while(!CARD_data_available() && (ISO7816_is_card_present()) && timeout) {timeout--; _delay_us(100);}
+	if (! ISO7816_is_card_present()){
+		return ISO7816_ERR_CARD_REMOVED;
+	} else if (CARD_data_available()){
 		uint8_t c = CARD_read_char();
 		return c;
 	} else {
diff --git a/CardReader/ISO7816-reader.h b/CardReader/ISO7816-reader.h
index 40908a8..5f556cb 100644
--- a/CardReader/ISO7816-reader.h
+++ b/CardReader/ISO7816-reader.h
@@ -23,12 +23,13 @@
 	#define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
 
-#define ATR_READ_SUCCESS 0x00
 #define ATR_IS_ERROR(x) (((x) & 0x80) == 0x80)
-#define ERR_ATR_TIMEOUT 0x81
+#define ATR_READ_SUCCESS                 0x00
+#define ERR_ATR_TIMEOUT                  0x81
 #define ERR_TOO_MANY_ATR_INTERFACE_BYTES 0x82
-#define ERR_ATR_CHECKSUM_FAIL 0x83
-#define ERR_PROTOCOL_NOT_SUPPORTED 0x84
+#define ERR_ATR_CHECKSUM_FAIL            0x83
+#define ERR_PROTOCOL_NOT_SUPPORTED       0x84
+#define ERR_ATR_CARD_REMOVED             0x85
 
 #ifdef CARD_PRESENCE_INTERUPT
 	#include <avr/interrupt.h>
@@ -36,8 +37,9 @@
 #endif
 
 #define ISO7816_IS_ERROR(ret) (((ret) & 0xFF) == 0xFF)
-#define ISO7816_ERR_TIMEOUT 0xFFFF
+#define ISO7816_ERR_TIMEOUT       0xFFFF
 #define ISO7816_ERR_CHECKSUM_FAIL 0xFFFE
+#define ISO7816_ERR_CARD_REMOVED  0xFFFD
 	
 void ISO7816_init(void);
 
-- 
GitLab