1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

Fix detection of card removal and insertion.

* scd/apdu.c (apdu_connect): Return status codes for no card available
and inactive card.
* scd/command.c (TEST_CARD_REMOVAL): Also test for GPG_ERR_CARD_RESET.
(open_card): Map apdu_connect status to GPG_ERR_CARD_RESET.
This commit is contained in:
Werner Koch 2011-12-12 20:34:12 +01:00
parent ea0a21410b
commit cd29dc0f1c
2 changed files with 18 additions and 5 deletions

View File

@ -3051,11 +3051,14 @@ apdu_enum_reader (int slot, int *used)
/* Connect a card. This is used to power up the card and make sure /* Connect a card. This is used to power up the card and make sure
that an ATR is available. */ that an ATR is available. Depending on the reader backend it may
return an error for an inactive card or if no card is
available. */
int int
apdu_connect (int slot) apdu_connect (int slot)
{ {
int sw; int sw;
unsigned int status;
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER; return SW_HOST_NO_DRIVER;
@ -3080,7 +3083,15 @@ apdu_connect (int slot)
scdaemon is fired up and apdu_get_status has not yet been called. scdaemon is fired up and apdu_get_status has not yet been called.
Without that we would force a reset of the card with the next Without that we would force a reset of the card with the next
call to apdu_get_status. */ call to apdu_get_status. */
apdu_get_status_internal (slot, 1, 1, NULL, NULL); apdu_get_status_internal (slot, 1, 1, &status, NULL);
if (sw)
;
else if (!(status & APDU_CARD_PRESENT))
sw = SW_HOST_NO_CARD;
else if (((status & APDU_CARD_PRESENT) && !(status & APDU_CARD_ACTIVE))
|| !reader_table[slot].atrlen)
sw = SW_HOST_CARD_INACTIVE;
return sw; return sw;
} }

View File

@ -60,6 +60,7 @@
int _r = (r); \ int _r = (r); \
if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \ if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \
|| gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \ || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED \
|| gpg_err_code (_r) == GPG_ERR_CARD_RESET \
|| gpg_err_code (_r) == GPG_ERR_ENODEV ) \ || gpg_err_code (_r) == GPG_ERR_ENODEV ) \
update_card_removed ((c)->reader_slot, 1); \ update_card_removed ((c)->reader_slot, 1); \
} while (0) } while (0)
@ -420,9 +421,8 @@ get_reader_slot (void)
return 0; return 0;
} }
/* If the card has not yet been opened, do it. Note that this
function returns an Assuan error, so don't map the error a second /* If the card has not yet been opened, do it. */
time. */
static gpg_error_t static gpg_error_t
open_card (ctrl_t ctrl, const char *apptype) open_card (ctrl_t ctrl, const char *apptype)
{ {
@ -477,6 +477,8 @@ open_card (ctrl_t ctrl, const char *apptype)
{ {
if (sw == SW_HOST_NO_CARD) if (sw == SW_HOST_NO_CARD)
err = gpg_error (GPG_ERR_CARD_NOT_PRESENT); err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
else if (sw == SW_HOST_CARD_INACTIVE)
err = gpg_error (GPG_ERR_CARD_RESET);
else else
err = gpg_error (GPG_ERR_CARD); err = gpg_error (GPG_ERR_CARD);
} }