Fix detection of card removal and insertion.
authorWerner Koch <wk@gnupg.org>
Mon, 12 Dec 2011 19:34:12 +0000 (20:34 +0100)
committerNIIBE Yutaka <gniibe@fsij.org>
Mon, 25 Jun 2012 01:04:22 +0000 (10:04 +0900)
* 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.

scd/apdu.c
scd/command.c

index b68cd71..b8bfcec 100644 (file)
@@ -2596,11 +2596,14 @@ apdu_enum_reader (int slot, int *used)
 
 
 /* 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
 apdu_connect (int slot)
 {
   int sw;
+  unsigned int status;
 
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -2625,7 +2628,15 @@ apdu_connect (int slot)
      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
      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;
 }
index 52b22c6..0a1f785 100644 (file)
@@ -60,6 +60,7 @@
           int _r = (r);                                     \
           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_RESET    \
               || gpg_err_code (_r) == GPG_ERR_ENODEV )      \
             update_card_removed ((c)->reader_slot, 1);      \
        } while (0)
@@ -420,9 +421,8 @@ get_reader_slot (void)
   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
-   time.  */
+
+/* If the card has not yet been opened, do it.  */
 static gpg_error_t
 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)
             err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
+          else if (sw == SW_HOST_CARD_INACTIVE)
+            err = gpg_error (GPG_ERR_CARD_RESET);
           else
             err = gpg_error (GPG_ERR_CARD);
        }