* Fix protocol forcing. Whenever connecting, use whatever protocol is available / currently set on card and only force the protocol with a cold reset when different

This fixes pcsc_lock->pcsc_reconnect->protocol mismatch error escaping from reader-pcsc.c if some other application has set the card to a different protocol.
 * pcsc_reconnect uses PC/SC return values, pcsc_reset uses OpenSC; 0 -> SC_SUCCESS
 * CCID driver with OmniKey 1021 returns SCARD_W_UNPOWERED_CARD when a card is inserted upside-down. Translate the currently unknown error into 'Unresponsive card'.


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3386 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
martin 2008-02-10 16:13:55 +00:00
parent a4bad4452e
commit 8db7c8c124
1 changed files with 25 additions and 17 deletions

View File

@ -118,6 +118,8 @@ static int pcsc_ret_to_error(long rv)
return SC_ERROR_TRANSMIT_FAILED;
case SCARD_W_UNRESPONSIVE_CARD:
return SC_ERROR_CARD_UNRESPONSIVE;
case SCARD_W_UNPOWERED_CARD:
return SC_ERROR_CARD_UNRESPONSIVE;
case SCARD_E_SHARING_VIOLATION:
return SC_ERROR_READER;
#ifdef SCARD_E_NO_READERS_AVAILABLE /* Older pcsc-lite does not have it */
@ -484,26 +486,32 @@ static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot, int reset
if (!(slot->flags & SC_SLOT_CARD_PRESENT))
return SC_ERROR_CARD_NOT_PRESENT;
if (_sc_check_forced_protocol
(reader->ctx, slot->atr, slot->atr_len,
(unsigned int *)&protocol)) {
protocol = opensc_proto_to_pcsc(protocol);
} else {
protocol = slot->active_protocol;
}
/* reconnect always unlocks transaction */
pslot->locked = 0;
rv = SCardReconnect(pslot->pcsc_card,
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED, protocol,
reset ? SCARD_UNPOWER_CARD : SCARD_LEAVE_CARD, &active_proto);
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
SCARD_PROTOCOL_ANY, reset ? SCARD_UNPOWER_CARD : SCARD_LEAVE_CARD, &active_proto);
/* Check for protocol difference */
if (rv == SCARD_S_SUCCESS && _sc_check_forced_protocol
(reader->ctx, slot->atr, slot->atr_len,
(unsigned int *)&protocol)) {
protocol = opensc_proto_to_pcsc(protocol);
if (pcsc_proto_to_opensc(active_proto) != protocol) {
rv = SCardReconnect(pslot->pcsc_card,
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
protocol, SCARD_UNPOWER_CARD, &active_proto);
}
}
if (rv != SCARD_S_SUCCESS) {
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
return pcsc_ret_to_error(rv);
return rv;
}
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
return SC_SUCCESS;
return rv;
}
static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
@ -626,7 +634,7 @@ static int pcsc_disconnect(sc_reader_t * reader, sc_slot_info_t * slot)
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
memset(pslot, 0, sizeof(*pslot));
slot->flags = 0;
return 0;
return SC_SUCCESS;
}
static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
@ -678,7 +686,7 @@ static int pcsc_unlock(sc_reader_t *reader, sc_slot_info_t *slot)
PCSC_ERROR(reader->ctx, "SCardEndTransaction failed", rv);
return pcsc_ret_to_error(rv);
}
return 0;
return SC_SUCCESS;
}
static int pcsc_release(sc_reader_t *reader)
@ -694,7 +702,7 @@ static int pcsc_release(sc_reader_t *reader)
reader->slot[i].drv_data = NULL;
}
}
return 0;
return SC_SUCCESS;
}
static int pcsc_reset(sc_reader_t *reader, sc_slot_info_t *slot)
@ -704,8 +712,8 @@ static int pcsc_reset(sc_reader_t *reader, sc_slot_info_t *slot)
int old_locked = pslot->locked;
r = pcsc_reconnect(reader, slot, 1);
if(r != SC_SUCCESS)
return r;
if(r != SCARD_S_SUCCESS)
return pcsc_ret_to_error(r);
/* pcsc_reconnect unlocks card... try to lock it again if it was locked */
if(old_locked)