scd: call update_card_removed only when detecting removal.
[gnupg.git] / scd / ccid-driver.c
index e9f39f4..8c91767 100644 (file)
@@ -303,6 +303,9 @@ static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
                     size_t *nread, int expected_type, int seqno, int timeout,
                     int no_debug);
 static int abort_cmd (ccid_driver_t handle, int seqno);
+static int send_escape_cmd (ccid_driver_t handle, const unsigned char *data,
+                            size_t datalen, unsigned char *result,
+                            size_t resultmax, size_t *resultlen);
 
 /* Convert a little endian stored 4 byte value into an unsigned
    integer. */
@@ -1525,6 +1528,29 @@ ccid_get_reader_list (void)
 }
 
 
+/* Vendor specific custom initialization.  */
+static int
+ccid_vendor_specific_init (ccid_driver_t handle)
+{
+  if (handle->id_vendor == VENDOR_VEGA && handle->id_product == VEGA_ALPHA)
+    {
+      /*
+       * Vega alpha has a feature to show retry counter on the pinpad
+       * display.  But it assumes that the card returns the value of
+       * retry counter by VERIFY with empty data (return code of
+       * 63Cx).  Unfortunately, existing OpenPGP cards don't support
+       * VERIFY command with empty data.  This vendor specific command
+       * sequence is to disable the feature.
+       */
+      const unsigned char cmd[] = "\xb5\x01\x00\x03\x00";
+
+      return send_escape_cmd (handle, cmd, sizeof (cmd), NULL, 0, NULL);
+    }
+
+  return 0;
+}
+
+
 /* Open the reader with the internal number READERNO and return a
    pointer to be used as handle in HANDLE.  Returns 0 on success. */
 int
@@ -1633,6 +1659,8 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
         }
     }
 
+  rc = ccid_vendor_specific_init (*handle);
+
  leave:
   free (ifcdesc_extra);
   if (rc)
@@ -2811,7 +2839,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
   /* The maximum length for a short APDU T=1 block is 261.  For an
      extended APDU T=1 block the maximum length 65544; however
      extended APDU exchange level is not fully supported yet.  */
-  if (apdulen > 289)
+  if (apdulen > sizeof (send_buffer) - 10)
     return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
 
   msg[0] = PC_to_RDR_XfrBlock;
@@ -3324,12 +3352,12 @@ ccid_transceive_secure (ccid_driver_t handle,
   else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
     ;
   else
-    return CCID_DRIVER_ERR_NO_KEYPAD;
+    return CCID_DRIVER_ERR_NO_PINPAD;
 
   if (!pininfo->minlen)
     pininfo->minlen = 1;
   if (!pininfo->maxlen)
-    pininfo->maxlen = 25;
+    pininfo->maxlen = 15;
 
   /* Note that the 25 is the maximum value the SPR532 allows.  */
   if (pininfo->minlen < 1 || pininfo->minlen > 25
@@ -3343,14 +3371,15 @@ ccid_transceive_secure (ccid_driver_t handle,
     {
     case VENDOR_SCM:  /* Tested with SPR 532. */
     case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
-    case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05).  */
+    case VENDOR_FSIJ: /* Tested with Gnuk (0.21). */
+      pininfo->maxlen = 25;
       enable_varlen = 1;
       break;
     case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
       enable_varlen = 1;
-      pininfo->maxlen = 15;
       break;
     case VENDOR_CHERRY:
+      pininfo->maxlen = 25;
       enable_varlen = 1;
       /* The CHERRY XX44 keyboard echos an asterisk for each entered
          character on the keyboard channel.  We use a special variant