- 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
This commit is contained in:
frankmorgner
2010-01-30 00:04:10 +00:00
parent 7b5be6ccd9
commit 8372d0a7db

View File

@@ -87,26 +87,37 @@ debug_sc_result(const char *func, int sc_result)
error("%s: %s", func, sc_strerror(sc_result)); error("%s: %s", func, sc_strerror(sc_result));
} }
void int
cleanup_card(int flags, __u8 bSlot) detect_card_presence(int slot)
{ {
if (bSlot < sizeof *card_in_slot) { int sc_result;
if (flags & SC_SLOT_CARD_CHANGED) {
sc_disconnect_card(card_in_slot[bSlot], 0); if (slot >= sizeof *card_in_slot)
debug("Card exchanged in slot %d", bSlot); return SC_ERROR_INVALID_ARGUMENTS;
}
if (flags == 0 if (card_in_slot[slot] && sc_card_valid(card_in_slot[slot])) {
&& card_in_slot[bSlot] sc_result = SC_SLOT_CARD_PRESENT;
&& sc_card_valid(card_in_slot[bSlot])) { } else {
sc_disconnect_card(card_in_slot[bSlot], 0); sc_result = sc_detect_card_presence(reader, slot);
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);
}
} }
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; 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; sc_result = SC_ERROR_INVALID_ARGUMENTS;
goto err; goto err;
} }
@@ -315,51 +326,28 @@ __u8 get_bStatus(int sc_result, __u8 bSlot)
int flags; int flags;
__u8 result = 0; __u8 result = 0;
if (bSlot < sizeof *card_in_slot) { flags = detect_card_presence(bSlot);
/* FIXME testing for the presence of a card yields a segmentation fault:
* opensc-0.11.4/src/libopensc/reader-pcsc.c:291 calls if (flags >= 0) {
* SCardGetStatusChange, which crashes. This could be a bug in libpcsc if (sc_result < 0) {
* if (flags & SC_SLOT_CARD_PRESENT) {
* To avoid this always assume, that the card is (still) present when if (flags & SC_SLOT_CARD_CHANGED)
* the context is valid. result = CCID_BSTATUS_ERROR_INACTIVE;
*/ else
#if 0 result = CCID_BSTATUS_ERROR_ACTIVE;
flags = sc_detect_card_presence(reader, bSlot); } else
#else result = CCID_BSTATUS_ERROR_NOICC;
if (card_in_slot[bSlot] && sc_card_valid(card_in_slot[bSlot])) {
flags = SC_SLOT_CARD_PRESENT;
} else { } 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 { } 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); DEBUG_SC_RESULT(flags);
flags = 0;
} }
return result; return result;
@@ -457,6 +445,7 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, __u8 **out, size_t *outlen)
if (!out || !outlen) if (!out || !outlen)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
printf("%s:%d\n", __FILE__, __LINE__);
*outlen = 0; *outlen = 0;
if (request->bSlot <= sizeof *card_in_slot) { if (request->bSlot <= sizeof *card_in_slot) {
sc_result = sc_connect_card(reader, request->bSlot, 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 { } else {
sc_result = SC_ERROR_INVALID_DATA; 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); r = get_RDR_to_PC_SlotStatus(request->bSlot, request->bSeq, sc_result, &result);
printf("%s:%d\n", __FILE__, __LINE__);
if (r >= 0) { if (r >= 0) {
printf("%s:%d\n", __FILE__, __LINE__);
if (sc_result >= 0) { if (sc_result >= 0) {
result->dwLength = __cpu_to_le32(card_in_slot[request->bSlot]->atr_len); result->dwLength = __cpu_to_le32(card_in_slot[request->bSlot]->atr_len);
*outlen = sizeof *result + 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); memcpy(*out + sizeof *result, card_in_slot[request->bSlot]->atr, card_in_slot[request->bSlot]->atr_len);
} else { } else {
printf("%s:%d\n", __FILE__, __LINE__);
DEBUG_SC_RESULT(sc_result); DEBUG_SC_RESULT(sc_result);
*outlen = sizeof *result; *outlen = sizeof *result;
*out = (__u8 *) result; *out = (__u8 *) result;
} }
} }
printf("%s:%d\n", __FILE__, __LINE__);
return r; return r;
} }
@@ -1054,8 +1048,7 @@ get_RDR_to_PC_NotifySlotChange(RDR_to_PC_NotifySlotChange_t **out)
result->bmSlotICCState = CCID_SLOTS_UNCHANGED; result->bmSlotICCState = CCID_SLOTS_UNCHANGED;
for (i = 0; i < reader->slot_count; i++) { for (i = 0; i < reader->slot_count; i++) {
sc_result = sc_detect_card_presence(reader, i); sc_result = detect_card_presence(i);
cleanup_card(sc_result, i);
if (sc_result < 0) { if (sc_result < 0) {
DEBUG_SC_RESULT(sc_result); DEBUG_SC_RESULT(sc_result);
continue; continue;