po: Update Russian translation
[gnupg.git] / scd / apdu.c
index f752284..c50afbd 100644 (file)
 /* This is used with GnuPG version < 1.9.  The code has been source
    copied from the current GnuPG >= 1.9  and is maintained over
    there. */
-#include "options.h"
+#include "../common/options.h"
 #include "errors.h"
 #include "memory.h"
-#include "util.h"
-#include "i18n.h"
+#include "../common/util.h"
+#include "../common/i18n.h"
 #include "dynload.h"
 #include "cardglue.h"
 #else /* GNUPG_MAJOR_VERSION != 1 */
 #include "scdaemon.h"
-#include "exechelp.h"
+#include "../common/exechelp.h"
 #endif /* GNUPG_MAJOR_VERSION != 1 */
-#include "host2net.h"
+#include "../common/host2net.h"
 
 #include "iso7816.h"
 #include "apdu.h"
@@ -73,16 +73,6 @@ struct dev_list {
   int idx_max;
 };
 
-/* Due to conflicting use of threading libraries we usually can't link
-   against libpcsclite if we are using Pth.  Instead we use a wrapper
-   program.  Note that with nPth there is no need for a wrapper. */
-#ifdef USE_PTH  /* Right, plain old Pth.  */
-#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__)
-#define NEED_PCSC_WRAPPER 1
-#endif
-#endif
-
-
 #define MAX_READER 4 /* Number of readers we support concurrently. */
 
 
@@ -104,12 +94,12 @@ struct reader_table_s {
   int used;            /* True if slot is used. */
   unsigned short port; /* Port number:  0 = unused, 1 - dev/tty */
 
-  /* Function pointers intialized to the various backends.  */
+  /* Function pointers initialized to the various backends.  */
   int (*connect_card)(int);
   int (*disconnect_card)(int);
   int (*close_reader)(int);
   int (*reset_reader)(int);
-  int (*get_status_reader)(int, unsigned int *);
+  int (*get_status_reader)(int, unsigned int *, int);
   int (*send_apdu_reader)(int,unsigned char *,size_t,
                           unsigned char *, size_t *, pininfo_t *);
   int (*check_pinpad)(int, int, pininfo_t *);
@@ -129,11 +119,6 @@ struct reader_table_s {
     pcsc_dword_t modify_ioctl;
     int pinmin;
     int pinmax;
-#ifdef NEED_PCSC_WRAPPER
-    int req_fd;
-    int rsp_fd;
-    pid_t pid;
-#endif /*NEED_PCSC_WRAPPER*/
   } pcsc;
 #ifdef USE_G10CODE_RAPDU
   struct {
@@ -165,14 +150,6 @@ static npth_mutex_t reader_table_lock;
 #endif
 
 
-/* ct API function pointer. */
-static char (* DLSTDCALL CT_init) (unsigned short ctn, unsigned short Pn);
-static char (* DLSTDCALL CT_data) (unsigned short ctn, unsigned char *dad,
-                                   unsigned char *sad, unsigned short lc,
-                                   unsigned char *cmd, unsigned short *lr,
-                                   unsigned char *rsp);
-static char (* DLSTDCALL CT_close) (unsigned short ctn);
-
 /* PC/SC constants and function pointer. */
 #define PCSC_SCOPE_USER      0
 #define PCSC_SCOPE_TERMINAL  1
@@ -253,7 +230,7 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn);
 #define PCSC_E_SERVICE_STOPPED         0x8010001E
 #define PCSC_W_REMOVED_CARD            0x80100069
 
-/* Fix pcsc-lite ABI incompatibilty.  */
+/* Fix pcsc-lite ABI incompatibility.  */
 #ifndef SCARD_CTL_CODE
 #ifdef _WIN32
 #include <winioctl.h>
@@ -365,7 +342,7 @@ long (* DLSTDCALL pcsc_control) (long card,
 
 /*  Prototypes.  */
 static int pcsc_vendor_specific_init (int slot);
-static int pcsc_get_status (int slot, unsigned int *status);
+static int pcsc_get_status (int slot, unsigned int *status, int on_wire);
 static int reset_pcsc_reader (int slot);
 static int apdu_get_status_internal (int slot, int hang, unsigned int *status,
                                      int on_wire);
@@ -472,11 +449,6 @@ new_reader_slot (void)
   reader_table[reader].is_spr532 = 0;
   reader_table[reader].pinpad_varlen_supported = 0;
   reader_table[reader].require_get_status = 1;
-#ifdef NEED_PCSC_WRAPPER
-  reader_table[reader].pcsc.req_fd = -1;
-  reader_table[reader].pcsc.rsp_fd = -1;
-  reader_table[reader].pcsc.pid = (pid_t)(-1);
-#endif
   reader_table[reader].pcsc.verify_ioctl = 0;
   reader_table[reader].pcsc.modify_ioctl = 0;
   reader_table[reader].pcsc.pinmin = -1;
@@ -562,267 +534,11 @@ apdu_strerror (int rc)
       return "unknown status error";
     }
 }
-
-
-\f
-/*
-       ct API Interface
- */
-
-static const char *
-ct_error_string (long err)
-{
-  switch (err)
-    {
-    case 0: return "okay";
-    case -1: return "invalid data";
-    case -8: return "ct error";
-    case -10: return "transmission error";
-    case -11: return "memory allocation error";
-    case -128: return "HTSI error";
-    default: return "unknown CT-API error";
-    }
-}
-
-
-/* Wait for the card in SLOT and activate it.  Return a status word
-   error or 0 on success. */
-static int
-ct_activate_card (int slot)
-{
-  int rc;
-  unsigned char dad[1], sad[1], cmd[11], buf[256];
-  unsigned short buflen;
-
-  /* Check whether card has been inserted. */
-  dad[0] = 1;     /* Destination address: CT. */
-  sad[0] = 2;     /* Source address: Host. */
-
-  cmd[0] = 0x20;  /* Class byte. */
-  cmd[1] = 0x13;  /* Request status. */
-  cmd[2] = 0x00;  /* From kernel. */
-  cmd[3] = 0x80;  /* Return card's DO. */
-  cmd[4] = 0x00;
-
-  buflen = DIM(buf);
-
-  rc = CT_data (slot, dad, sad, 5, cmd, &buflen, buf);
-  if (rc || buflen < 2 || buf[buflen-2] != 0x90)
-    {
-      log_error ("ct_activate_card: can't get status of reader %d: %s\n",
-                 slot, ct_error_string (rc));
-      return SW_HOST_CARD_IO_ERROR;
-    }
-
-  /* Connected, now activate the card. */
-  dad[0] = 1;    /* Destination address: CT. */
-  sad[0] = 2;    /* Source address: Host. */
-
-  cmd[0] = 0x20;  /* Class byte. */
-  cmd[1] = 0x12;  /* Request ICC. */
-  cmd[2] = 0x01;  /* From first interface. */
-  cmd[3] = 0x01;  /* Return card's ATR. */
-  cmd[4] = 0x00;
-
-  buflen = DIM(buf);
-
-  rc = CT_data (slot, dad, sad, 5, cmd, &buflen, buf);
-  if (rc || buflen < 2 || buf[buflen-2] != 0x90)
-    {
-      log_error ("ct_activate_card(%d): activation failed: %s\n",
-                 slot, ct_error_string (rc));
-      if (!rc)
-        log_printhex ("  received data:", buf, buflen);
-      return SW_HOST_CARD_IO_ERROR;
-    }
-
-  /* Store the type and the ATR. */
-  if (buflen - 2 > DIM (reader_table[0].atr))
-    {
-      log_error ("ct_activate_card(%d): ATR too long\n", slot);
-      return SW_HOST_CARD_IO_ERROR;
-    }
-
-  memcpy (reader_table[slot].atr, buf, buflen - 2);
-  reader_table[slot].atrlen = buflen - 2;
-  return 0;
-}
-
-
-static int
-close_ct_reader (int slot)
-{
-  CT_close (slot);
-  return 0;
-}
-
-static int
-reset_ct_reader (int slot)
-{
-  /* FIXME: Check is this is sufficient do do a reset. */
-  return ct_activate_card (slot);
-}
-
-
-static int
-ct_get_status (int slot, unsigned int *status)
-{
-  (void)slot;
-  /* The status we returned is wrong but we don't care because ctAPI
-     is not anymore required.  */
-  *status = APDU_CARD_USABLE|APDU_CARD_PRESENT|APDU_CARD_ACTIVE;
-  return 0;
-}
-
-/* Actually send the APDU of length APDULEN to SLOT and return a
-   maximum of *BUFLEN data in BUFFER, the actual returned size will be
-   set to BUFLEN.  Returns: CT API error code. */
-static int
-ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-              unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
-{
-  int rc;
-  unsigned char dad[1], sad[1];
-  unsigned short ctbuflen;
-
-  (void)pininfo;
-
-  /* If we don't have an ATR, we need to reset the reader first. */
-  if (!reader_table[slot].atrlen
-      && (rc = reset_ct_reader (slot)))
-    return rc;
-
-  dad[0] = 0;     /* Destination address: Card. */
-  sad[0] = 2;     /* Source address: Host. */
-  ctbuflen = *buflen;
-  if (DBG_CARD_IO)
-    log_printhex ("  CT_data:", apdu, apdulen);
-  rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer);
-  *buflen = ctbuflen;
-
-  return rc? SW_HOST_CARD_IO_ERROR: 0;
-}
-
-
-
-/* Open a reader and return an internal handle for it.  PORT is a
-   non-negative value with the port number of the reader. USB readers
-   do have port numbers starting at 32769. */
-static int
-open_ct_reader (int port)
-{
-  int rc, reader;
-
-  if (port < 0 || port > 0xffff)
-    {
-      log_error ("open_ct_reader: invalid port %d requested\n", port);
-      return -1;
-    }
-  reader = new_reader_slot ();
-  if (reader == -1)
-    return reader;
-  reader_table[reader].port = port;
-
-  rc = CT_init (reader, (unsigned short)port);
-  if (rc)
-    {
-      log_error ("apdu_open_ct_reader failed on port %d: %s\n",
-                 port, ct_error_string (rc));
-      reader_table[reader].used = 0;
-      unlock_slot (reader);
-      return -1;
-    }
-
-  /* Only try to activate the card. */
-  rc = ct_activate_card (reader);
-  if (rc)
-    {
-      reader_table[reader].atrlen = 0;
-      rc = 0;
-    }
-
-  reader_table[reader].close_reader = close_ct_reader;
-  reader_table[reader].reset_reader = reset_ct_reader;
-  reader_table[reader].get_status_reader = ct_get_status;
-  reader_table[reader].send_apdu_reader = ct_send_apdu;
-  reader_table[reader].check_pinpad = NULL;
-  reader_table[reader].dump_status_reader = NULL;
-  reader_table[reader].pinpad_verify = NULL;
-  reader_table[reader].pinpad_modify = NULL;
-
-  dump_reader_status (reader);
-  unlock_slot (reader);
-  return reader;
-}
-
 \f
 /*
        PC/SC Interface
  */
 
-#ifdef NEED_PCSC_WRAPPER
-static int
-writen (int fd, const void *buf, size_t nbytes)
-{
-  size_t nleft = nbytes;
-  int nwritten;
-
-/*   log_printhex (" writen:", buf, nbytes); */
-
-  while (nleft > 0)
-    {
-#ifdef USE_NPTH
-      nwritten = npth_write (fd, buf, nleft);
-#else
-      nwritten = write (fd, buf, nleft);
-#endif
-      if (nwritten < 0 && errno == EINTR)
-        continue;
-      if (nwritten < 0)
-        return -1;
-      nleft -= nwritten;
-      buf = (const char*)buf + nwritten;
-    }
-  return 0;
-}
-
-/* Read up to BUFLEN bytes from FD and return the number of bytes
-   actually read in NREAD.  Returns -1 on error or 0 on success. */
-static int
-readn (int fd, void *buf, size_t buflen, size_t *nread)
-{
-  size_t nleft = buflen;
-  int n;
-/*   void *orig_buf = buf; */
-
-  while (nleft > 0)
-    {
-#ifdef USE_NPTH
-# ifdef HAVE_W32_SYSTEM
-#  error Cannot use npth_read here because it expects a system HANDLE.
-# endif
-      n = npth_read (fd, buf, nleft);
-#else
-      n = read (fd, buf, nleft);
-#endif
-      if (n < 0 && errno == EINTR)
-        continue;
-      if (n < 0)
-        return -1; /* read error. */
-      if (!n)
-        break; /* EOF */
-      nleft -= n;
-      buf = (char*)buf + n;
-    }
-  if (nread)
-    *nread = buflen - nleft;
-
-/*   log_printhex ("  readn:", orig_buf, *nread); */
-
-  return 0;
-}
-#endif /*NEED_PCSC_WRAPPER*/
-
 static const char *
 pcsc_error_string (long err)
 {
@@ -927,13 +643,13 @@ dump_pcsc_reader_status (int slot)
 }
 
 
-#ifndef NEED_PCSC_WRAPPER
 static int
-pcsc_get_status_direct (int slot, unsigned int *status)
+pcsc_get_status (int slot, unsigned int *status, int on_wire)
 {
   long err;
   struct pcsc_readerstate_s rdrstates[1];
 
+  (void)on_wire;
   memset (rdrstates, 0, sizeof *rdrstates);
   rdrstates[0].reader = reader_table[slot].rdrname;
   rdrstates[0].current_state = PCSC_STATE_UNAWARE;
@@ -987,135 +703,15 @@ pcsc_get_status_direct (int slot, unsigned int *status)
 
   return 0;
 }
-#endif /*!NEED_PCSC_WRAPPER*/
 
 
-#ifdef NEED_PCSC_WRAPPER
-static int
-pcsc_get_status_wrapped (int slot, unsigned int *status)
-{
-  long err;
-  reader_table_t slotp;
-  size_t len, full_len;
-  int i, n;
-  unsigned char msgbuf[9];
-  unsigned char buffer[16];
-  int sw = SW_HOST_CARD_IO_ERROR;
-
-  slotp = reader_table + slot;
-
-  if (slotp->pcsc.req_fd == -1
-      || slotp->pcsc.rsp_fd == -1
-      || slotp->pcsc.pid == (pid_t)(-1) )
-    {
-      log_error ("pcsc_get_status: pcsc-wrapper not running\n");
-      return sw;
-    }
-
-  msgbuf[0] = 0x04; /* STATUS command. */
-  len = 0;
-  msgbuf[1] = (len >> 24);
-  msgbuf[2] = (len >> 16);
-  msgbuf[3] = (len >>  8);
-  msgbuf[4] = (len      );
-  if ( writen (slotp->pcsc.req_fd, msgbuf, 5) )
-    {
-      log_error ("error sending PC/SC STATUS request: %s\n",
-                 strerror (errno));
-      goto command_failed;
-    }
-
-  /* Read the response. */
-  if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
-    {
-      log_error ("error receiving PC/SC STATUS response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  len = buf_to_size_t (msgbuf+1);
-  if (msgbuf[0] != 0x81 || len < 4)
-    {
-      log_error ("invalid response header from PC/SC received\n");
-      goto command_failed;
-    }
-  len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
-  if (err)
-    {
-      log_error ("pcsc_status failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      /* This is a proper error code, so return immediately.  */
-      return pcsc_error_to_sw (err);
-    }
-
-  full_len = len;
-
-  /* The current version returns 3 words but we allow also for old
-     versions returning only 2 words. */
-  n = 12 < len ? 12 : len;
-  if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len))
-      || (len != 8 && len != 12))
-    {
-      log_error ("error receiving PC/SC STATUS response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-
-  slotp->is_t0 = (len == 12 && !!(buffer[11] & PCSC_PROTOCOL_T0));
-
-
-  full_len -= len;
-  /* Newer versions of the wrapper might send more status bytes.
-     Read them. */
-  while (full_len)
-    {
-      unsigned char dummybuf[128];
-
-      n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf);
-      if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n)
-        {
-          log_error ("error receiving PC/SC TRANSMIT response: %s\n",
-                     i? strerror (errno) : "premature EOF");
-          goto command_failed;
-        }
-      full_len -= n;
-    }
-
-  /* We are lucky: The wrapper already returns the data in the
-     required format. */
-  *status = buffer[3];
-  return 0;
-
- command_failed:
-  close (slotp->pcsc.req_fd);
-  close (slotp->pcsc.rsp_fd);
-  slotp->pcsc.req_fd = -1;
-  slotp->pcsc.rsp_fd = -1;
-  if (slotp->pcsc.pid != -1)
-    kill (slotp->pcsc.pid, SIGTERM);
-  slotp->pcsc.pid = (pid_t)(-1);
-  slotp->used = 0;
-  return sw;
-}
-#endif /*NEED_PCSC_WRAPPER*/
-
-
-static int
-pcsc_get_status (int slot, unsigned int *status)
-{
-#ifdef NEED_PCSC_WRAPPER
-  return pcsc_get_status_wrapped (slot, status);
-#else
-  return pcsc_get_status_direct (slot, status);
-#endif
-}
-
-
-#ifndef NEED_PCSC_WRAPPER
+/* Send the APDU of length APDULEN to SLOT and return a maximum of
+   *BUFLEN data in BUFFER, the actual returned size will be stored at
+   BUFLEN.  Returns: A status word. */
 static int
-pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
-                       unsigned char *buffer, size_t *buflen,
-                       pininfo_t *pininfo)
+pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
+                unsigned char *buffer, size_t *buflen,
+                pininfo_t *pininfo)
 {
   long err;
   struct pcsc_io_request_s send_pci;
@@ -1146,270 +742,6 @@ pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
 
   return pcsc_error_to_sw (err);
 }
-#endif /*!NEED_PCSC_WRAPPER*/
-
-
-#ifdef NEED_PCSC_WRAPPER
-static int
-pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
-                        unsigned char *buffer, size_t *buflen,
-                        pininfo_t *pininfo)
-{
-  long err;
-  reader_table_t slotp;
-  size_t len, full_len;
-  int i, n;
-  unsigned char msgbuf[9];
-  int sw = SW_HOST_CARD_IO_ERROR;
-
-  (void)pininfo;
-
-  if (!reader_table[slot].atrlen
-      && (err = reset_pcsc_reader (slot)))
-    return err;
-
-  if (DBG_CARD_IO)
-    log_printhex ("  PCSC_data:", apdu, apdulen);
-
-  slotp = reader_table + slot;
-
-  if (slotp->pcsc.req_fd == -1
-      || slotp->pcsc.rsp_fd == -1
-      || slotp->pcsc.pid == (pid_t)(-1) )
-    {
-      log_error ("pcsc_send_apdu: pcsc-wrapper not running\n");
-      return sw;
-    }
-
-  msgbuf[0] = 0x03; /* TRANSMIT command. */
-  len = apdulen;
-  msgbuf[1] = (len >> 24);
-  msgbuf[2] = (len >> 16);
-  msgbuf[3] = (len >>  8);
-  msgbuf[4] = (len      );
-  if ( writen (slotp->pcsc.req_fd, msgbuf, 5)
-       || writen (slotp->pcsc.req_fd, apdu, len))
-    {
-      log_error ("error sending PC/SC TRANSMIT request: %s\n",
-                 strerror (errno));
-      goto command_failed;
-    }
-
-  /* Read the response. */
-  if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
-    {
-      log_error ("error receiving PC/SC TRANSMIT response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  len = buf_to_size_t (msgbuf+1);
-  if (msgbuf[0] != 0x81 || len < 4)
-    {
-      log_error ("invalid response header from PC/SC received\n");
-      goto command_failed;
-    }
-  len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
-  if (err)
-    {
-      log_error ("pcsc_transmit failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      return pcsc_error_to_sw (err);
-    }
-
-   full_len = len;
-
-   n = *buflen < len ? *buflen : len;
-   if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n)
-     {
-       log_error ("error receiving PC/SC TRANSMIT response: %s\n",
-                  i? strerror (errno) : "premature EOF");
-       goto command_failed;
-     }
-   *buflen = n;
-
-   full_len -= len;
-   if (full_len)
-     {
-       log_error ("pcsc_send_apdu: provided buffer too short - truncated\n");
-       err = SW_HOST_INV_VALUE;
-     }
-   /* We need to read any rest of the response, to keep the
-      protocol running.  */
-   while (full_len)
-     {
-       unsigned char dummybuf[128];
-
-       n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf);
-       if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n)
-         {
-           log_error ("error receiving PC/SC TRANSMIT response: %s\n",
-                      i? strerror (errno) : "premature EOF");
-           goto command_failed;
-         }
-       full_len -= n;
-     }
-
-   return err;
-
- command_failed:
-  close (slotp->pcsc.req_fd);
-  close (slotp->pcsc.rsp_fd);
-  slotp->pcsc.req_fd = -1;
-  slotp->pcsc.rsp_fd = -1;
-  if (slotp->pcsc.pid != -1)
-    kill (slotp->pcsc.pid, SIGTERM);
-  slotp->pcsc.pid = (pid_t)(-1);
-  slotp->used = 0;
-  return sw;
-}
-#endif /*NEED_PCSC_WRAPPER*/
-
-
-/* Send the APDU of length APDULEN to SLOT and return a maximum of
-   *BUFLEN data in BUFFER, the actual returned size will be stored at
-   BUFLEN.  Returns: A status word. */
-static int
-pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-                unsigned char *buffer, size_t *buflen,
-                pininfo_t *pininfo)
-{
-#ifdef NEED_PCSC_WRAPPER
-  return pcsc_send_apdu_wrapped (slot, apdu, apdulen, buffer, buflen, pininfo);
-#else
-  return pcsc_send_apdu_direct (slot, apdu, apdulen, buffer, buflen, pininfo);
-#endif
-}
-
-
-#ifndef NEED_PCSC_WRAPPER
-static int
-control_pcsc_direct (int slot, pcsc_dword_t ioctl_code,
-                     const unsigned char *cntlbuf, size_t len,
-                     unsigned char *buffer, pcsc_dword_t *buflen)
-{
-  long err;
-
-  err = pcsc_control (reader_table[slot].pcsc.card, ioctl_code,
-                      cntlbuf, len, buffer, buflen? *buflen:0, buflen);
-  if (err)
-    {
-      log_error ("pcsc_control failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      return pcsc_error_to_sw (err);
-    }
-
-  return 0;
-}
-#endif /*!NEED_PCSC_WRAPPER*/
-
-
-#ifdef NEED_PCSC_WRAPPER
-static int
-control_pcsc_wrapped (int slot, pcsc_dword_t ioctl_code,
-                      const unsigned char *cntlbuf, size_t len,
-                      unsigned char *buffer, pcsc_dword_t *buflen)
-{
-  long err = PCSC_E_NOT_TRANSACTED;
-  reader_table_t slotp;
-  unsigned char msgbuf[9];
-  int i, n;
-  size_t full_len;
-
-  slotp = reader_table + slot;
-
-  msgbuf[0] = 0x06; /* CONTROL command. */
-  msgbuf[1] = ((len + 4) >> 24);
-  msgbuf[2] = ((len + 4) >> 16);
-  msgbuf[3] = ((len + 4) >>  8);
-  msgbuf[4] = ((len + 4)      );
-  msgbuf[5] = (ioctl_code >> 24);
-  msgbuf[6] = (ioctl_code >> 16);
-  msgbuf[7] = (ioctl_code >>  8);
-  msgbuf[8] = (ioctl_code      );
-  if ( writen (slotp->pcsc.req_fd, msgbuf, 9)
-       || writen (slotp->pcsc.req_fd, cntlbuf, len))
-    {
-      log_error ("error sending PC/SC CONTROL request: %s\n",
-                 strerror (errno));
-      goto command_failed;
-    }
-
-  /* Read the response. */
-  if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
-    {
-      log_error ("error receiving PC/SC CONTROL response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  len = buf32_to_size_t (msgbuf+1);
-  if (msgbuf[0] != 0x81 || len < 4)
-    {
-      log_error ("invalid response header from PC/SC received\n");
-      goto command_failed;
-    }
-  len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
-  if (err)
-    {
-      log_error ("pcsc_control failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      return pcsc_error_to_sw (err);
-    }
-
-  full_len = len;
-
-  if (buflen)
-    n = *buflen < len ? *buflen : len;
-  else
-    n = 0;
-  if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n)
-    {
-      log_error ("error receiving PC/SC CONTROL response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  if (buflen)
-    *buflen = n;
-
-  full_len -= len;
-  if (full_len)
-    {
-      log_error ("pcsc_send_apdu: provided buffer too short - truncated\n");
-      err = PCSC_E_INVALID_VALUE;
-    }
-  /* We need to read any rest of the response, to keep the
-     protocol running.  */
-  while (full_len)
-    {
-      unsigned char dummybuf[128];
-
-      n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf);
-      if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n)
-        {
-          log_error ("error receiving PC/SC CONTROL response: %s\n",
-                     i? strerror (errno) : "premature EOF");
-          goto command_failed;
-        }
-      full_len -= n;
-    }
-
-  if (!err)
-    return 0;
-
- command_failed:
-  close (slotp->pcsc.req_fd);
-  close (slotp->pcsc.rsp_fd);
-  slotp->pcsc.req_fd = -1;
-  slotp->pcsc.rsp_fd = -1;
-  if (slotp->pcsc.pid != -1)
-    kill (slotp->pcsc.pid, SIGTERM);
-  slotp->pcsc.pid = (pid_t)(-1);
-  slotp->used = 0;
-  return pcsc_error_to_sw (err);
-}
-#endif /*NEED_PCSC_WRAPPER*/
-
 
 
 /* Do some control with the value of IOCTL_CODE to the card inserted
@@ -1422,106 +754,30 @@ control_pcsc (int slot, pcsc_dword_t ioctl_code,
               const unsigned char *cntlbuf, size_t len,
               unsigned char *buffer, pcsc_dword_t *buflen)
 {
-#ifdef NEED_PCSC_WRAPPER
-  return control_pcsc_wrapped (slot, ioctl_code, cntlbuf, len, buffer, buflen);
-#else
-  return control_pcsc_direct (slot, ioctl_code, cntlbuf, len, buffer, buflen);
-#endif
-}
-
-
-#ifndef NEED_PCSC_WRAPPER
-static int
-close_pcsc_reader_direct (int slot)
-{
-  pcsc_release_context (reader_table[slot].pcsc.context);
-  return 0;
-}
-#endif /*!NEED_PCSC_WRAPPER*/
-
-
-#ifdef NEED_PCSC_WRAPPER
-static int
-close_pcsc_reader_wrapped (int slot)
-{
   long err;
-  reader_table_t slotp;
-  size_t len;
-  int i;
-  unsigned char msgbuf[9];
-
-  slotp = reader_table + slot;
-
-  if (slotp->pcsc.req_fd == -1
-      || slotp->pcsc.rsp_fd == -1
-      || slotp->pcsc.pid == (pid_t)(-1) )
-    {
-      log_error ("close_pcsc_reader: pcsc-wrapper not running\n");
-      return 0;
-    }
-
-  msgbuf[0] = 0x02; /* CLOSE command. */
-  len = 0;
-  msgbuf[1] = (len >> 24);
-  msgbuf[2] = (len >> 16);
-  msgbuf[3] = (len >>  8);
-  msgbuf[4] = (len      );
-  if ( writen (slotp->pcsc.req_fd, msgbuf, 5) )
-    {
-      log_error ("error sending PC/SC CLOSE request: %s\n",
-                 strerror (errno));
-      goto command_failed;
-    }
 
-  /* Read the response. */
-  if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
-    {
-      log_error ("error receiving PC/SC CLOSE response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  len = buf32_to_size_t (msgbuf+1);
-  if (msgbuf[0] != 0x81 || len < 4)
+  err = pcsc_control (reader_table[slot].pcsc.card, ioctl_code,
+                      cntlbuf, len, buffer, buflen? *buflen:0, buflen);
+  if (err)
     {
-      log_error ("invalid response header from PC/SC received\n");
-      goto command_failed;
+      log_error ("pcsc_control failed: %s (0x%lx)\n",
+                 pcsc_error_string (err), err);
+      return pcsc_error_to_sw (err);
     }
-  len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
-  if (err)
-    log_error ("pcsc_close failed: %s (0x%lx)\n",
-               pcsc_error_string (err), err);
 
-  /* We will close the wrapper in any case - errors are merely
-     informational. */
-
- command_failed:
-  close (slotp->pcsc.req_fd);
-  close (slotp->pcsc.rsp_fd);
-  slotp->pcsc.req_fd = -1;
-  slotp->pcsc.rsp_fd = -1;
-  if (slotp->pcsc.pid != -1)
-    kill (slotp->pcsc.pid, SIGTERM);
-  slotp->pcsc.pid = (pid_t)(-1);
-  slotp->used = 0;
   return 0;
 }
-#endif /*NEED_PCSC_WRAPPER*/
 
 
 static int
 close_pcsc_reader (int slot)
 {
-#ifdef NEED_PCSC_WRAPPER
-  return close_pcsc_reader_wrapped (slot);
-#else
-  return close_pcsc_reader_direct (slot);
-#endif
+  pcsc_release_context (reader_table[slot].pcsc.context);
+  return 0;
 }
 
 
 /* Connect a PC/SC card.  */
-#ifndef NEED_PCSC_WRAPPER
 static int
 connect_pcsc_card (int slot)
 {
@@ -1577,12 +833,8 @@ connect_pcsc_card (int slot)
   dump_reader_status (slot);
   return pcsc_error_to_sw (err);
 }
-#endif /*!NEED_PCSC_WRAPPER*/
 
 
-/* Disconnect a PC/SC card.  Note that this succeeds even if the card
-   is not connected.  */
-#ifndef NEED_PCSC_WRAPPER
 static int
 disconnect_pcsc_card (int slot)
 {
@@ -1603,12 +855,12 @@ disconnect_pcsc_card (int slot)
   reader_table[slot].pcsc.card = 0;
   return 0;
 }
-#endif /*!NEED_PCSC_WRAPPER*/
 
 
-#ifndef NEED_PCSC_WRAPPER
+/* Send an PC/SC reset command and return a status word on error or 0
+   on success. */
 static int
-reset_pcsc_reader_direct (int slot)
+reset_pcsc_reader (int slot)
 {
   int sw;
 
@@ -1618,122 +870,6 @@ reset_pcsc_reader_direct (int slot)
 
   return sw;
 }
-#endif /*NEED_PCSC_WRAPPER*/
-
-
-#ifdef NEED_PCSC_WRAPPER
-static int
-reset_pcsc_reader_wrapped (int slot)
-{
-  long err;
-  reader_table_t slotp;
-  size_t len;
-  int i, n;
-  unsigned char msgbuf[9];
-  unsigned int dummy_status;
-  int sw = SW_HOST_CARD_IO_ERROR;
-
-  slotp = reader_table + slot;
-
-  if (slotp->pcsc.req_fd == -1
-      || slotp->pcsc.rsp_fd == -1
-      || slotp->pcsc.pid == (pid_t)(-1) )
-    {
-      log_error ("pcsc_get_status: pcsc-wrapper not running\n");
-      return sw;
-    }
-
-  msgbuf[0] = 0x05; /* RESET command. */
-  len = 0;
-  msgbuf[1] = (len >> 24);
-  msgbuf[2] = (len >> 16);
-  msgbuf[3] = (len >>  8);
-  msgbuf[4] = (len      );
-  if ( writen (slotp->pcsc.req_fd, msgbuf, 5) )
-    {
-      log_error ("error sending PC/SC RESET request: %s\n",
-                 strerror (errno));
-      goto command_failed;
-    }
-
-  /* Read the response. */
-  if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
-    {
-      log_error ("error receiving PC/SC RESET response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  len = buf32_to_size_t (msgbuf+1);
-  if (msgbuf[0] != 0x81 || len < 4)
-    {
-      log_error ("invalid response header from PC/SC received\n");
-      goto command_failed;
-    }
-  len -= 4; /* Already read the error code. */
-  if (len > DIM (slotp->atr))
-    {
-      log_error ("PC/SC returned a too large ATR (len=%lx)\n",
-                 (unsigned long)len);
-      sw = SW_HOST_GENERAL_ERROR;
-      goto command_failed;
-    }
-  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
-  if (err)
-    {
-      log_error ("PC/SC RESET failed: %s (0x%lx)\n",
-                 pcsc_error_string (err), err);
-      /* If the error code is no smart card, we should not considere
-         this a major error and close the wrapper.  */
-      sw = pcsc_error_to_sw (err);
-      if (err == PCSC_E_NO_SMARTCARD)
-        return sw;
-      goto command_failed;
-    }
-
-  /* The open function may return a zero for the ATR length to
-     indicate that no card is present.  */
-  n = len;
-  if (n)
-    {
-      if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n)
-        {
-          log_error ("error receiving PC/SC RESET response: %s\n",
-                     i? strerror (errno) : "premature EOF");
-          goto command_failed;
-        }
-    }
-  slotp->atrlen = len;
-
-  /* Read the status so that IS_T0 will be set. */
-  pcsc_get_status (slot, &dummy_status);
-
-  return 0;
-
- command_failed:
-  close (slotp->pcsc.req_fd);
-  close (slotp->pcsc.rsp_fd);
-  slotp->pcsc.req_fd = -1;
-  slotp->pcsc.rsp_fd = -1;
-  if (slotp->pcsc.pid != -1)
-    kill (slotp->pcsc.pid, SIGTERM);
-  slotp->pcsc.pid = (pid_t)(-1);
-  slotp->used = 0;
-  return sw;
-}
-#endif /* !NEED_PCSC_WRAPPER */
-
-
-/* Send an PC/SC reset command and return a status word on error or 0
-   on success. */
-static int
-reset_pcsc_reader (int slot)
-{
-#ifdef NEED_PCSC_WRAPPER
-  return reset_pcsc_reader_wrapped (slot);
-#else
-  return reset_pcsc_reader_direct (slot);
-#endif
-}
 
 
 /* Examine reader specific parameters and initialize.  This is mostly
@@ -1891,9 +1027,8 @@ pcsc_vendor_specific_init (int slot)
 
 /* Open the PC/SC reader without using the wrapper.  Returns -1 on
    error or a slot number for the reader.  */
-#ifndef NEED_PCSC_WRAPPER
 static int
-open_pcsc_reader_direct (const char *portstr)
+open_pcsc_reader (const char *portstr)
 {
   long err;
   int slot;
@@ -1993,229 +1128,6 @@ open_pcsc_reader_direct (const char *portstr)
   unlock_slot (slot);
   return slot;
 }
-#endif /*!NEED_PCSC_WRAPPER */
-
-
-/* Open the PC/SC reader using the pcsc_wrapper program.  This is
-   needed to cope with different thread models and other peculiarities
-   of libpcsclite. */
-#ifdef NEED_PCSC_WRAPPER
-static int
-open_pcsc_reader_wrapped (const char *portstr)
-{
-  int slot;
-  reader_table_t slotp;
-  int fd, rp[2], wp[2];
-  int n, i;
-  pid_t pid;
-  size_t len;
-  unsigned char msgbuf[9];
-  int err;
-  unsigned int dummy_status;
-
-  /* Note that we use the constant and not the function because this
-     code won't be be used under Windows.  */
-  const char *wrapperpgm = GNUPG_LIBEXECDIR "/gnupg-pcsc-wrapper";
-
-  if (access (wrapperpgm, X_OK))
-    {
-      log_error ("can't run PC/SC access module '%s': %s\n",
-                 wrapperpgm, strerror (errno));
-      return -1;
-    }
-
-  slot = new_reader_slot ();
-  if (slot == -1)
-    return -1;
-  slotp = reader_table + slot;
-
-  /* Fire up the PC/SCc wrapper.  We don't use any fork/exec code from
-     the common directy but implement it directly so that this file
-     may still be source copied. */
-
-  if (pipe (rp) == -1)
-    {
-      log_error ("error creating a pipe: %s\n", strerror (errno));
-      slotp->used = 0;
-      unlock_slot (slot);
-      return -1;
-    }
-  if (pipe (wp) == -1)
-    {
-      log_error ("error creating a pipe: %s\n", strerror (errno));
-      close (rp[0]);
-      close (rp[1]);
-      slotp->used = 0;
-      unlock_slot (slot);
-      return -1;
-    }
-
-  pid = fork ();
-  if (pid == -1)
-    {
-      log_error ("error forking process: %s\n", strerror (errno));
-      close (rp[0]);
-      close (rp[1]);
-      close (wp[0]);
-      close (wp[1]);
-      slotp->used = 0;
-      unlock_slot (slot);
-      return -1;
-    }
-  slotp->pcsc.pid = pid;
-
-  if (!pid)
-    { /*
-         === Child ===
-       */
-
-      /* Double fork. */
-      pid = fork ();
-      if (pid == -1)
-        _exit (31);
-      if (pid)
-        _exit (0); /* Immediate exit this parent, so that the child
-                      gets cleaned up by the init process. */
-
-      /* Connect our pipes. */
-      if (wp[0] != 0 && dup2 (wp[0], 0) == -1)
-        log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
-      if (rp[1] != 1 && dup2 (rp[1], 1) == -1)
-        log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
-
-      /* Send stderr to the bit bucket. */
-      fd = open ("/dev/null", O_WRONLY);
-      if (fd == -1)
-        log_fatal ("can't open '/dev/null': %s", strerror (errno));
-      if (fd != 2 && dup2 (fd, 2) == -1)
-        log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
-
-      /* Close all other files. */
-      close_all_fds (3, NULL);
-
-      execl (wrapperpgm,
-             "pcsc-wrapper",
-             "--",
-             "1", /* API version */
-             opt.pcsc_driver, /* Name of the PC/SC library. */
-              NULL);
-      _exit (31);
-    }
-
-  /*
-     === Parent ===
-   */
-  close (wp[0]);
-  close (rp[1]);
-  slotp->pcsc.req_fd = wp[1];
-  slotp->pcsc.rsp_fd = rp[0];
-
-  /* Wait for the intermediate child to terminate. */
-#ifdef USE_NPTH
-#define WAIT npth_waitpid
-#else
-#define WAIT waitpid
-#endif
-  while ( (i=WAIT (pid, NULL, 0)) == -1 && errno == EINTR)
-    ;
-#undef WAIT
-
-  /* Now send the open request. */
-  msgbuf[0] = 0x01; /* OPEN command. */
-  len = portstr? strlen (portstr):0;
-  msgbuf[1] = (len >> 24);
-  msgbuf[2] = (len >> 16);
-  msgbuf[3] = (len >>  8);
-  msgbuf[4] = (len      );
-  if ( writen (slotp->pcsc.req_fd, msgbuf, 5)
-       || (portstr && writen (slotp->pcsc.req_fd, portstr, len)))
-    {
-      log_error ("error sending PC/SC OPEN request: %s\n",
-                 strerror (errno));
-      goto command_failed;
-    }
-  /* Read the response. */
-  if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
-    {
-      log_error ("error receiving PC/SC OPEN response: %s\n",
-                 i? strerror (errno) : "premature EOF");
-      goto command_failed;
-    }
-  len = buf32_to_size_t (msgbuf+1);
-  if (msgbuf[0] != 0x81 || len < 4)
-    {
-      log_error ("invalid response header from PC/SC received\n");
-      goto command_failed;
-    }
-  len -= 4; /* Already read the error code. */
-  if (len > DIM (slotp->atr))
-    {
-      log_error ("PC/SC returned a too large ATR (len=%lx)\n",
-                 (unsigned long)len);
-      goto command_failed;
-    }
-  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
-  if (err)
-    {
-      log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err));
-      goto command_failed;
-    }
-
-  /* The open request may return a zero for the ATR length to
-     indicate that no card is present.  */
-  n = len;
-  if (n)
-    {
-      if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n)
-        {
-          log_error ("error receiving PC/SC OPEN response: %s\n",
-                     i? strerror (errno) : "premature EOF");
-          goto command_failed;
-        }
-    }
-  slotp->atrlen = len;
-
-  reader_table[slot].close_reader = close_pcsc_reader;
-  reader_table[slot].reset_reader = reset_pcsc_reader;
-  reader_table[slot].get_status_reader = pcsc_get_status;
-  reader_table[slot].send_apdu_reader = pcsc_send_apdu;
-  reader_table[slot].dump_status_reader = dump_pcsc_reader_status;
-
-  pcsc_vendor_specific_init (slot);
-
-  /* Read the status so that IS_T0 will be set. */
-  pcsc_get_status (slot, &dummy_status);
-
-  dump_reader_status (slot);
-  unlock_slot (slot);
-  return slot;
-
- command_failed:
-  close (slotp->pcsc.req_fd);
-  close (slotp->pcsc.rsp_fd);
-  slotp->pcsc.req_fd = -1;
-  slotp->pcsc.rsp_fd = -1;
-  if (slotp->pcsc.pid != -1)
-    kill (slotp->pcsc.pid, SIGTERM);
-  slotp->pcsc.pid = (pid_t)(-1);
-  slotp->used = 0;
-  unlock_slot (slot);
-  /* There is no way to return SW. */
-  return -1;
-
-}
-#endif /*NEED_PCSC_WRAPPER*/
-
-
-static int
-open_pcsc_reader (const char *portstr)
-{
-#ifdef NEED_PCSC_WRAPPER
-  return open_pcsc_reader_wrapped (portstr);
-#else
-  return open_pcsc_reader_direct (portstr);
-#endif
-}
 
 
 /* Check whether the reader supports the ISO command code COMMAND
@@ -2471,12 +1383,12 @@ set_progress_cb_ccid_reader (int slot, gcry_handler_progress_t cb, void *cb_arg)
 
 
 static int
-get_status_ccid (int slot, unsigned int *status)
+get_status_ccid (int slot, unsigned int *status, int on_wire)
 {
   int rc;
   int bits;
 
-  rc = ccid_slot_status (reader_table[slot].ccid.handle, &bits);
+  rc = ccid_slot_status (reader_table[slot].ccid.handle, &bits, on_wire);
   if (rc)
     return rc;
 
@@ -2584,19 +1496,19 @@ open_ccid_reader (struct dev_list *dl)
 
   err = ccid_open_reader (dl->portstr, dl->idx, dl->ccid_table,
                           &slotp->ccid.handle, &slotp->rdrname);
-  if (err)
+  if (!err)
     {
-      slotp->used = 0;
-      unlock_slot (slot);
-      return -1;
+      err = ccid_get_atr (slotp->ccid.handle,
+                          slotp->atr, sizeof slotp->atr, &slotp->atrlen);
+      if (err)
+        ccid_close_reader (slotp->ccid.handle);
     }
 
-  err = ccid_get_atr (slotp->ccid.handle,
-                      slotp->atr, sizeof slotp->atr, &slotp->atrlen);
   if (err)
     {
-      slotp->atrlen = 0;
-      err = 0;
+      slotp->used = 0;
+      unlock_slot (slot);
+      return -1;
     }
 
   require_get_status = ccid_require_get_status (slotp->ccid.handle);
@@ -2718,13 +1630,14 @@ reset_rapdu_reader (int slot)
 
 
 static int
-my_rapdu_get_status (int slot, unsigned int *status)
+my_rapdu_get_status (int slot, unsigned int *status, int on_wire)
 {
   int err;
   reader_table_t slotp;
   rapdu_msg_t msg = NULL;
   int oldslot;
 
+  (void)on_wire;
   slotp = reader_table + slot;
 
   oldslot = rapdu_set_reader (slotp->rapdu.handle, slot);
@@ -2994,45 +1907,15 @@ apdu_dev_list_finish (struct dev_list *dl)
 static int
 apdu_open_one_reader (const char *portstr)
 {
-  static int pcsc_api_loaded, ct_api_loaded;
+  static int pcsc_api_loaded;
   int slot;
 
   if (DBG_READER)
     log_debug ("enter: apdu_open_reader: portstr=%s\n", portstr);
 
-  if (opt.ctapi_driver && *opt.ctapi_driver)
-    {
-      int port = portstr? atoi (portstr) : 32768;
-
-      if (!ct_api_loaded)
-        {
-          void *handle;
-
-          handle = dlopen (opt.ctapi_driver, RTLD_LAZY);
-          if (!handle)
-            {
-              log_error ("apdu_open_reader: failed to open driver: %s\n",
-                         dlerror ());
-              return -1;
-            }
-          CT_init = dlsym (handle, "CT_init");
-          CT_data = dlsym (handle, "CT_data");
-          CT_close = dlsym (handle, "CT_close");
-          if (!CT_init || !CT_data || !CT_close)
-            {
-              log_error ("apdu_open_reader: invalid CT-API driver\n");
-              dlclose (handle);
-              return -1;
-            }
-          ct_api_loaded = 1;
-        }
-      return open_ct_reader (port);
-    }
-
-  /* No ctAPI configured, so lets try the PC/SC API */
+  /* Lets try the PC/SC API */
   if (!pcsc_api_loaded)
     {
-#ifndef NEED_PCSC_WRAPPER
       void *handle;
 
       handle = dlopen (opt.pcsc_driver, RTLD_LAZY);
@@ -3111,7 +1994,6 @@ apdu_open_one_reader (const char *portstr)
           dlclose (handle);
           return -1;
         }
-#endif /*!NEED_PCSC_WRAPPER*/
       pcsc_api_loaded = 1;
     }
 
@@ -3123,7 +2005,7 @@ apdu_open_one_reader (const char *portstr)
 }
 
 int
-apdu_open_reader (struct dev_list *dl)
+apdu_open_reader (struct dev_list *dl, int app_empty)
 {
   int slot;
 
@@ -3173,6 +2055,7 @@ apdu_open_reader (struct dev_list *dl)
           /* Check identity by BAI against already opened HANDLEs.  */
           for (slot = 0; slot < MAX_READER; slot++)
             if (reader_table[slot].used
+                && reader_table[slot].ccid.handle
                 && ccid_compare_BAI (reader_table[slot].ccid.handle, bai))
               break;
 
@@ -3197,12 +2080,19 @@ apdu_open_reader (struct dev_list *dl)
             dl->idx++;
         }
 
-      slot = -1;
+      /* Not found.  Try one for PC/SC, only when it's the initial scan.  */
+      if (app_empty && dl->idx == dl->idx_max)
+        {
+          dl->idx++;
+          slot = apdu_open_one_reader (dl->portstr);
+        }
+      else
+        slot = -1;
     }
   else
 #endif
     { /* PC/SC readers.  */
-      if (dl->idx == 0)
+      if (app_empty && dl->idx == 0)
         {
           dl->idx++;
           slot = apdu_open_one_reader (dl->portstr);
@@ -3557,7 +2447,7 @@ static int
 apdu_get_status_internal (int slot, int hang, unsigned int *status, int on_wire)
 {
   int sw;
-  unsigned int s;
+  unsigned int s = 0;
 
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -3565,20 +2455,8 @@ apdu_get_status_internal (int slot, int hang, unsigned int *status, int on_wire)
   if ((sw = hang? lock_slot (slot) : trylock_slot (slot)))
     return sw;
 
-  /* If the card (with its lower-level driver) doesn't require
-     GET_STATUS on wire (because it supports INTERRUPT transfer for
-     status change, or it's a token which has a card always inserted),
-     no need to send on wire.  */
-  if (!on_wire && !reader_table[slot].require_get_status)
-    {
-      unlock_slot (slot);
-      if (status)
-        *status = (APDU_CARD_USABLE|APDU_CARD_ACTIVE);
-      return 0;
-    }
-
   if (reader_table[slot].get_status_reader)
-    sw = reader_table[slot].get_status_reader (slot, &s);
+    sw = reader_table[slot].get_status_reader (slot, &s, on_wire);
 
   unlock_slot (slot);
 
@@ -3935,7 +2813,6 @@ send_le (int slot, int class, int ins, int p0, int p1,
     {
       xfree (apdu_buffer);
       apdu_buffer = NULL;
-      apdu_buffer_size = 0;
     }
 
   /* Store away the returned data but strip the statusword. */