From 8372d0a7db1ffaf7ce0541e54d9cf7d61fe5bac0 Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Sat, 30 Jan 2010 00:04:10 +0000 Subject: [PATCH] - created detect_card_presence to avoid limitations of sc_detect_card_presence git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@32 96b47cad-a561-4643-ad3b-153ac7d7599c --- ccid/ccid.c | 117 ++++++++++++++++++++++++---------------------------- 1 file changed, 55 insertions(+), 62 deletions(-) diff --git a/ccid/ccid.c b/ccid/ccid.c index 19ec460..82c8e9d 100644 --- a/ccid/ccid.c +++ b/ccid/ccid.c @@ -87,26 +87,37 @@ debug_sc_result(const char *func, int sc_result) error("%s: %s", func, sc_strerror(sc_result)); } -void -cleanup_card(int flags, __u8 bSlot) +int +detect_card_presence(int slot) { - if (bSlot < sizeof *card_in_slot) { - if (flags & SC_SLOT_CARD_CHANGED) { - sc_disconnect_card(card_in_slot[bSlot], 0); - debug("Card exchanged in slot %d", bSlot); - } - if (flags == 0 - && card_in_slot[bSlot] - && sc_card_valid(card_in_slot[bSlot])) { - sc_disconnect_card(card_in_slot[bSlot], 0); - debug("Card removed from slot %d", bSlot); - } - if (flags & SC_SLOT_CARD_PRESENT - && (!card_in_slot[bSlot] - || !sc_card_valid(card_in_slot[bSlot]))) { - debug("Unused card in slot %d", bSlot); - } + int sc_result; + + if (slot >= sizeof *card_in_slot) + return SC_ERROR_INVALID_ARGUMENTS; + + if (card_in_slot[slot] && sc_card_valid(card_in_slot[slot])) { + sc_result = SC_SLOT_CARD_PRESENT; + } else { + sc_result = sc_detect_card_presence(reader, slot); } + + if (sc_result == 0 + && card_in_slot[slot] + && sc_card_valid(card_in_slot[slot])) { + sc_disconnect_card(card_in_slot[slot], 0); + debug("Card removed from slot %d", slot); + } + if (sc_result & SC_SLOT_CARD_CHANGED) { + sc_disconnect_card(card_in_slot[slot], 0); + debug("Card exchanged in slot %d", slot); + } + if (sc_result & SC_SLOT_CARD_PRESENT + && (!card_in_slot[slot] + || !sc_card_valid(card_in_slot[slot]))) { + debug("Unused card in slot %d", slot); + } + + return sc_result; } @@ -242,7 +253,7 @@ int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen) { int sc_result; - if (!apdu || !buf || !resplen || slot > sizeof *card_in_slot) { + if (!apdu || !buf || !resplen || slot >= sizeof *card_in_slot) { sc_result = SC_ERROR_INVALID_ARGUMENTS; goto err; } @@ -315,51 +326,28 @@ __u8 get_bStatus(int sc_result, __u8 bSlot) int flags; __u8 result = 0; - if (bSlot < sizeof *card_in_slot) { - /* FIXME testing for the presence of a card yields a segmentation fault: - * opensc-0.11.4/src/libopensc/reader-pcsc.c:291 calls - * SCardGetStatusChange, which crashes. This could be a bug in libpcsc - * - * To avoid this always assume, that the card is (still) present when - * the context is valid. - */ -#if 0 - flags = sc_detect_card_presence(reader, bSlot); -#else - if (card_in_slot[bSlot] && sc_card_valid(card_in_slot[bSlot])) { - flags = SC_SLOT_CARD_PRESENT; + flags = detect_card_presence(bSlot); + + if (flags >= 0) { + if (sc_result < 0) { + if (flags & SC_SLOT_CARD_PRESENT) { + if (flags & SC_SLOT_CARD_CHANGED) + result = CCID_BSTATUS_ERROR_INACTIVE; + else + result = CCID_BSTATUS_ERROR_ACTIVE; + } else + result = CCID_BSTATUS_ERROR_NOICC; } else { - flags = sc_detect_card_presence(reader, bSlot); + if (flags & SC_SLOT_CARD_PRESENT) { + if (flags & SC_SLOT_CARD_CHANGED) + result = CCID_BSTATUS_OK_INACTIVE; + else + result = CCID_BSTATUS_OK_ACTIVE; + } else + result = CCID_BSTATUS_OK_NOICC; } -#endif - cleanup_card(flags, bSlot); } else { - flags = SC_ERROR_INVALID_DATA; - goto err; - } - - if (sc_result < 0) { - if (flags & SC_SLOT_CARD_PRESENT) { - if (flags & SC_SLOT_CARD_CHANGED) - result = CCID_BSTATUS_ERROR_INACTIVE; - else - result = CCID_BSTATUS_ERROR_ACTIVE; - } else - result = CCID_BSTATUS_ERROR_NOICC; - } else { - if (flags & SC_SLOT_CARD_PRESENT) { - if (flags & SC_SLOT_CARD_CHANGED) - result = CCID_BSTATUS_OK_INACTIVE; - else - result = CCID_BSTATUS_OK_ACTIVE; - } else - result = CCID_BSTATUS_OK_NOICC; - } - -err: - if (flags < 0) { DEBUG_SC_RESULT(flags); - flags = 0; } return result; @@ -457,6 +445,7 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen) if (!out || !outlen) return SC_ERROR_INVALID_ARGUMENTS; + printf("%s:%d\n", __FILE__, __LINE__); *outlen = 0; if (request->bSlot <= sizeof *card_in_slot) { sc_result = sc_connect_card(reader, request->bSlot, @@ -464,10 +453,13 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen) } else { sc_result = SC_ERROR_INVALID_DATA; } + printf("%s:%d\n", __FILE__, __LINE__); r = get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result, &result); + printf("%s:%d\n", __FILE__, __LINE__); if (r >= 0) { + printf("%s:%d\n", __FILE__, __LINE__); if (sc_result >= 0) { result->dwLength = __cpu_to_le32(card_in_slot[request->bSlot]->atr_len); *outlen = sizeof *result + card_in_slot[request->bSlot]->atr_len; @@ -478,11 +470,13 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen) } memcpy(*out + sizeof *result, card_in_slot[request->bSlot]->atr, card_in_slot[request->bSlot]->atr_len); } else { + printf("%s:%d\n", __FILE__, __LINE__); DEBUG_SC_RESULT(sc_result); *outlen = sizeof *result; *out = (__u8 *) result; } } + printf("%s:%d\n", __FILE__, __LINE__); return r; } @@ -1054,8 +1048,7 @@ get_RDR_to_PC_NotifySlotChange(RDR_to_PC_NotifySlotChange_t **out) result->bmSlotICCState = CCID_SLOTS_UNCHANGED; for (i = 0; i < reader->slot_count; i++) { - sc_result = sc_detect_card_presence(reader, i); - cleanup_card(sc_result, i); + sc_result = detect_card_presence(i); if (sc_result < 0) { DEBUG_SC_RESULT(sc_result); continue;