add function sc_reset() to reset a card; patch supplied by Josep Monés Teixidor <jmt@c3po.es>

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2877 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
nils 2006-03-22 21:44:09 +00:00
parent 40e6c491ed
commit 8be396fee3
3 changed files with 71 additions and 3 deletions

View File

@ -249,6 +249,33 @@ int sc_disconnect_card(sc_card_t *card, int action)
SC_FUNC_RETURN(ctx, 1, 0);
}
int sc_reset(sc_card_t *card)
{
int r, r2;
if (card == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
if (card->reader->ops->reset == NULL)
return SC_ERROR_NOT_SUPPORTED;
r = sc_mutex_lock(card->ctx, card->mutex);
if (r != SC_SUCCESS)
return r;
r = card->reader->ops->reset(card->reader, card->slot);
/* invalidate cache */
memset(&card->cache, 0, sizeof(card->cache));
card->cache_valid = 0;
r2 = sc_mutex_unlock(card->ctx, card->mutex);
if (r2 != SC_SUCCESS) {
sc_error(card->ctx, "unable to release lock\n");
r = r != SC_SUCCESS ? r : r2;
}
return r;
}
int sc_lock(sc_card_t *card)
{
int r = 0;

View File

@ -394,6 +394,7 @@ struct sc_reader_operations {
int *reader_index,
unsigned int *event,
int timeout);
int (*reset)(struct sc_reader *, struct sc_slot_info *);
};
/*
@ -805,6 +806,14 @@ int sc_wait_for_event(sc_reader_t **readers, int *slots, size_t nslots,
unsigned int event_mask,
int *reader, unsigned int *event, int timeout);
/**
* Resets the card.
* NOTE: only PC/SC backend implements this function at this moment.
* @param card The card to reset.
* @retval SC_SUCCESS on success
*/
int sc_reset(sc_card_t *card);
/**
* Locks the card against modification from other threads.
* After the initial call to sc_lock, the card is protected from

View File

@ -93,6 +93,7 @@ struct pcsc_slot_data {
SCARD_READERSTATE_A reader_state;
DWORD verify_ioctl;
DWORD modify_ioctl;
int locked;
};
static int pcsc_detect_card_presence(sc_reader_t *reader, sc_slot_info_t *slot);
@ -452,7 +453,7 @@ static int pcsc_wait_for_event(sc_reader_t **readers,
}
}
static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot)
static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot, int reset)
{
DWORD active_proto, protocol;
LONG rv;
@ -476,9 +477,12 @@ static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot)
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,
SCARD_LEAVE_CARD, &active_proto);
reset ? SCARD_RESET_CARD : SCARD_LEAVE_CARD, &active_proto);
if (rv != SCARD_S_SUCCESS) {
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
return pcsc_ret_to_error(rv);
@ -524,6 +528,9 @@ static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot)
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
pslot->pcsc_card = card_handle;
/* after connect reader is not locked yet */
pslot->locked = 0;
/* check for pinpad support */
#ifdef PINPAD_ENABLED
sc_debug(reader->ctx, "Requesting reader features ... ");
@ -586,7 +593,7 @@ static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
if ((unsigned int)rv == SCARD_W_RESET_CARD) {
/* try to reconnect if the card was reset by some other application */
rv = pcsc_reconnect(reader, slot);
rv = pcsc_reconnect(reader, slot, 0);
if (rv != SCARD_S_SUCCESS) {
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
return pcsc_ret_to_error(rv);
@ -600,6 +607,9 @@ static int pcsc_lock(sc_reader_t *reader, sc_slot_info_t *slot)
PCSC_ERROR(reader->ctx, "SCardBeginTransaction failed", rv);
return pcsc_ret_to_error(rv);
}
pslot->locked = 1;
return SC_SUCCESS;
}
@ -610,12 +620,16 @@ static int pcsc_unlock(sc_reader_t *reader, sc_slot_info_t *slot)
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
assert(pslot != NULL);
rv = SCardEndTransaction(pslot->pcsc_card, priv->gpriv->transaction_reset ?
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
if (rv != SCARD_S_SUCCESS) {
PCSC_ERROR(reader->ctx, "SCardEndTransaction failed", rv);
return pcsc_ret_to_error(rv);
}
pslot->locked = 0;
return 0;
}
@ -635,6 +649,23 @@ static int pcsc_release(sc_reader_t *reader)
return 0;
}
static int pcsc_reset(sc_reader_t *reader, sc_slot_info_t *slot)
{
int r;
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
int old_locked = pslot->locked;
r = pcsc_reconnect(reader, slot, 1);
if(r != SC_SUCCESS)
return r;
/* pcsc_reconnect unlocks card... try to lock it again if it was locked */
if(old_locked)
r = pcsc_lock(reader, slot);
return r;
}
static struct sc_reader_operations pcsc_ops;
static struct sc_reader_driver pcsc_drv = {
@ -784,6 +815,7 @@ struct sc_reader_driver * sc_get_pcsc_driver(void)
pcsc_ops.disconnect = pcsc_disconnect;
pcsc_ops.perform_verify = pcsc_pin_cmd;
pcsc_ops.wait_for_event = pcsc_wait_for_event;
pcsc_ops.reset = pcsc_reset;
return &pcsc_drv;
}