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:
parent
40e6c491ed
commit
8be396fee3
|
@ -249,6 +249,33 @@ int sc_disconnect_card(sc_card_t *card, int action)
|
||||||
SC_FUNC_RETURN(ctx, 1, 0);
|
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 sc_lock(sc_card_t *card)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
|
@ -394,6 +394,7 @@ struct sc_reader_operations {
|
||||||
int *reader_index,
|
int *reader_index,
|
||||||
unsigned int *event,
|
unsigned int *event,
|
||||||
int timeout);
|
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,
|
unsigned int event_mask,
|
||||||
int *reader, unsigned int *event, int timeout);
|
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.
|
* Locks the card against modification from other threads.
|
||||||
* After the initial call to sc_lock, the card is protected from
|
* After the initial call to sc_lock, the card is protected from
|
||||||
|
|
|
@ -93,6 +93,7 @@ struct pcsc_slot_data {
|
||||||
SCARD_READERSTATE_A reader_state;
|
SCARD_READERSTATE_A reader_state;
|
||||||
DWORD verify_ioctl;
|
DWORD verify_ioctl;
|
||||||
DWORD modify_ioctl;
|
DWORD modify_ioctl;
|
||||||
|
int locked;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pcsc_detect_card_presence(sc_reader_t *reader, sc_slot_info_t *slot);
|
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;
|
DWORD active_proto, protocol;
|
||||||
LONG rv;
|
LONG rv;
|
||||||
|
@ -476,9 +477,12 @@ static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot)
|
||||||
protocol = slot->active_protocol;
|
protocol = slot->active_protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reconnect always unlocks transaction */
|
||||||
|
pslot->locked = 0;
|
||||||
|
|
||||||
rv = SCardReconnect(pslot->pcsc_card,
|
rv = SCardReconnect(pslot->pcsc_card,
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED, protocol,
|
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) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
||||||
return pcsc_ret_to_error(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);
|
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
|
||||||
pslot->pcsc_card = card_handle;
|
pslot->pcsc_card = card_handle;
|
||||||
|
|
||||||
|
/* after connect reader is not locked yet */
|
||||||
|
pslot->locked = 0;
|
||||||
|
|
||||||
/* check for pinpad support */
|
/* check for pinpad support */
|
||||||
#ifdef PINPAD_ENABLED
|
#ifdef PINPAD_ENABLED
|
||||||
sc_debug(reader->ctx, "Requesting reader features ... ");
|
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) {
|
if ((unsigned int)rv == SCARD_W_RESET_CARD) {
|
||||||
/* try to reconnect if the card was reset by some other application */
|
/* 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) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
|
||||||
return pcsc_ret_to_error(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);
|
PCSC_ERROR(reader->ctx, "SCardBeginTransaction failed", rv);
|
||||||
return pcsc_ret_to_error(rv);
|
return pcsc_ret_to_error(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pslot->locked = 1;
|
||||||
|
|
||||||
return SC_SUCCESS;
|
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);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
|
||||||
assert(pslot != NULL);
|
assert(pslot != NULL);
|
||||||
|
|
||||||
rv = SCardEndTransaction(pslot->pcsc_card, priv->gpriv->transaction_reset ?
|
rv = SCardEndTransaction(pslot->pcsc_card, priv->gpriv->transaction_reset ?
|
||||||
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
|
SCARD_RESET_CARD : SCARD_LEAVE_CARD);
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardEndTransaction failed", rv);
|
PCSC_ERROR(reader->ctx, "SCardEndTransaction failed", rv);
|
||||||
return pcsc_ret_to_error(rv);
|
return pcsc_ret_to_error(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pslot->locked = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,6 +649,23 @@ static int pcsc_release(sc_reader_t *reader)
|
||||||
return 0;
|
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_operations pcsc_ops;
|
||||||
|
|
||||||
static struct sc_reader_driver pcsc_drv = {
|
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.disconnect = pcsc_disconnect;
|
||||||
pcsc_ops.perform_verify = pcsc_pin_cmd;
|
pcsc_ops.perform_verify = pcsc_pin_cmd;
|
||||||
pcsc_ops.wait_for_event = pcsc_wait_for_event;
|
pcsc_ops.wait_for_event = pcsc_wait_for_event;
|
||||||
|
pcsc_ops.reset = pcsc_reset;
|
||||||
|
|
||||||
return &pcsc_drv;
|
return &pcsc_drv;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue