agent: Stop scdaemon after reload when disable_scdaemon.
[gnupg.git] / scd / ccid-driver.c
index 5046da5..657766e 100644 (file)
 
 /* CCID command timeout.  */
 #define CCID_CMD_TIMEOUT (5*1000)
-/* OpenPGPcard v2.1 requires huge timeout for key generation.  */
-#define CCID_CMD_TIMEOUT_LONGER (60*1000)
 
 /* Depending on how this source is used we either define our error
-   output to go to stderr or to the GnuPG based logging functions.  We
-   use the latter when GNUPG_MAJOR_VERSION or GNUPG_SCD_MAIN_HEADER
-   are defined.  */
-#if defined(GNUPG_MAJOR_VERSION) || defined(GNUPG_SCD_MAIN_HEADER)
-
+ * output to go to stderr or to the GnuPG based logging functions.  We
+ * use the latter when GNUPG_SCD_MAIN_HEADER is defined.  */
 #if defined(GNUPG_SCD_MAIN_HEADER)
-#  include GNUPG_SCD_MAIN_HEADER
-#elif GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */
-#  include "options.h"
-#  include "util.h"
-#  include "memory.h"
-#  include "cardglue.h"
-# else /* This is the modularized GnuPG 1.9 or later. */
-#  include "scdaemon.h"
-#endif
-
+# include GNUPG_SCD_MAIN_HEADER
 
 # define DEBUGOUT(t)         do { if (debug_level) \
                                   log_debug (DRVNAME t); } while (0)
 # define DEBUGOUT_LF()        do { if (debug_level) \
                      putc ('\n', stderr); } while (0)
 
-#endif /* This source not used by scdaemon. */
+#endif /* This source is not used by scdaemon. */
 
 
 #ifndef EAGAIN
@@ -255,6 +241,9 @@ struct ccid_driver_s
   void (*progress_cb)(void *, const char *, int, int, int);
   void *progress_cb_arg;
 
+  void (*prompt_cb)(void *, int);
+  void *prompt_cb_arg;
+
   unsigned char intr_buf[64];
   struct libusb_transfer *transfer;
 };
@@ -1650,15 +1639,13 @@ ccid_open_usb_reader (const char *spec_reader_name,
       goto leave;
     }
 
-  if (set_no != 0)
+  /* Submit SET_INTERFACE control transfer which can reset the device.  */
+  rc = libusb_set_interface_alt_setting (idev, ifc_no, set_no);
+  if (rc)
     {
-      rc = libusb_set_interface_alt_setting (idev, ifc_no, set_no);
-      if (rc)
-        {
-          DEBUGOUT_1 ("usb_set_interface_alt_setting failed: %d\n", rc);
-          rc = CCID_DRIVER_ERR_CARD_IO_ERROR;
-          goto leave;
-        }
+      DEBUGOUT_1 ("usb_set_interface_alt_setting failed: %d\n", rc);
+      rc = CCID_DRIVER_ERR_CARD_IO_ERROR;
+      goto leave;
     }
 
   rc = ccid_vendor_specific_init (*handle);
@@ -1801,6 +1788,19 @@ ccid_set_progress_cb (ccid_driver_t handle,
 }
 
 
+int
+ccid_set_prompt_cb (ccid_driver_t handle,
+                   void (*cb)(void *, int), void *cb_arg)
+{
+  if (!handle)
+    return CCID_DRIVER_ERR_INV_VALUE;
+
+  handle->prompt_cb = cb;
+  handle->prompt_cb_arg = cb_arg;
+  return 0;
+}
+
+
 /* Close the reader HANDLE. */
 int
 ccid_close_reader (ccid_driver_t handle)
@@ -1920,7 +1920,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
    is the sequence number used to send the request and EXPECTED_TYPE
    the type of message we expect. Does checks on the ccid
    header. TIMEOUT is the timeout value in ms. NO_DEBUG may be set to
-   avoid debug messages in case of no error; this can be overriden
+   avoid debug messages in case of no error; this can be overridden
    with a glibal debug level of at least 3. Returns 0 on success. */
 static int
 bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
@@ -1929,6 +1929,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
 {
   int rc;
   int msglen;
+  int notified = 0;
 
   /* Fixme: The next line for the current Valgrind without support
      for USB IOCTLs. */
@@ -1981,14 +1982,25 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
      we got the expected message type.  This is in particular required
      for the Cherry keyboard which sends a time extension request for
      each key hit.  */
-  if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
+  if (!(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
     {
       /* Card present and active, time extension requested. */
       DEBUGOUT_2 ("time extension requested (%02X,%02X)\n",
                   buffer[7], buffer[8]);
+
+      /* Gnuk enhancement to prompt user input by ack button */
+      if (buffer[8] == 0xff && !notified)
+        {
+          notified = 1;
+         handle->prompt_cb (handle->prompt_cb_arg, 1);
+        }
+
       goto retry;
     }
 
+  if (notified)
+    handle->prompt_cb (handle->prompt_cb_arg, 0);
+
   if (buffer[0] != expected_type && buffer[0] != RDR_to_PC_SlotStatus)
     {
       DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
@@ -2927,7 +2939,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
    bit 3     unused
    bit 2..0  Source Node Address (SAD)
 
-   If node adresses are not used, SAD and DAD should be set to 0 on
+   If node addresses are not used, SAD and DAD should be set to 0 on
    the first block sent to the card.  If they are used they should
    have different values (0 for one is okay); that first block sets up
    the addresses of the nodes.
@@ -3068,7 +3080,7 @@ ccid_transceive (ccid_driver_t handle,
           msg[0] = PC_to_RDR_XfrBlock;
           msg[5] = 0; /* slot */
           msg[6] = seqno = handle->seqno++;
-          msg[7] = 4; /* bBWI */
+          msg[7] = (wait_more ? wait_more : 1); /* bBWI */
           msg[8] = 0; /* RFU */
           msg[9] = 0; /* RFU */
           set_msg_len (msg, tpdulen);
@@ -3094,7 +3106,7 @@ ccid_transceive (ccid_driver_t handle,
       msg = recv_buffer;
       rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
                     via_escape? RDR_to_PC_Escape : RDR_to_PC_DataBlock, seqno,
-                    wait_more? CCID_CMD_TIMEOUT_LONGER: CCID_CMD_TIMEOUT, 0);
+                    (wait_more ? wait_more : 1) * CCID_CMD_TIMEOUT, 0);
       if (rc)
         return rc;
 
@@ -3124,6 +3136,7 @@ ccid_transceive (ccid_driver_t handle,
                     (!(msg[pcboff] & 0x80) && (msg[pcboff] & 0x20)?
                      " [more]":""));
 
+      wait_more = 0;
       if (!(tpdu[1] & 0x80))
         { /* This is an I-block. */
           retries = 0;
@@ -3269,9 +3282,7 @@ ccid_transceive (ccid_driver_t handle,
               /* Wait time extension request. */
               unsigned char bwi = tpdu[3];
 
-              /* Check if it's unsual value which can't be expressed in ATR.  */
-              if (bwi > 15)
-                wait_more = 1;
+             wait_more = bwi;
 
               msg = send_buffer;
               tpdu = msg + hdrlen;
@@ -3386,6 +3397,12 @@ ccid_transceive_secure (ccid_driver_t handle,
       if (handle->id_product != CHERRY_ST2000)
         cherry_mode = 1;
       break;
+    case VENDOR_NXP:
+      if (handle->id_product == CRYPTOUCAN){
+        pininfo->maxlen = 25;
+        enable_varlen = 1;
+      }
+      break;
     default:
       if ((handle->id_vendor == VENDOR_GEMPC &&
            handle->id_product == GEMPC_PINPAD)