[pkg-opensc-commit] [opensc] 235/295: reader-pcsc: removed cardmod driver

Eric Dorland eric at moszumanska.debian.org
Sat Jun 24 21:11:35 UTC 2017


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository opensc.

commit fcc8ea5939c360ca6c497852c83751e4045ce6be
Author: Frank Morgner <frankmorgner at gmail.com>
Date:   Tue Nov 15 22:48:48 2016 +0100

    reader-pcsc: removed cardmod driver
    
    - pcsc driver takes over all the functionality
    - no dedicated reader driver config values for cardmod, use application
      specific blocks to define a different behavior for the pcsc reader if
      needed
    - removes legacy code; requiring at least libpcsclite 1.6.5
    
    Fixes https://github.com/OpenSC/OpenSC/issues/892
---
 etc/opensc.conf.in          |  12 +-
 src/libopensc/ctx.c         |  11 +-
 src/libopensc/internal.h    |  17 +-
 src/libopensc/reader-pcsc.c | 879 +++++++++++++++-----------------------------
 src/minidriver/minidriver.c |   4 +-
 5 files changed, 307 insertions(+), 616 deletions(-)

diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in
index 239c44c..63abba9 100644
--- a/etc/opensc.conf.in
+++ b/etc/opensc.conf.in
@@ -769,7 +769,7 @@ app onepin-opensc-pkcs11 {
 	}
 }
 
-# Used by OpenSC.tokend on Mac OS X only.
+# Used by OpenSC.tokend on Mac OS X only
 app tokend {
 	# The file to which debug log will be written
 	# Default: /tmp/opensc-tokend.log
@@ -785,14 +785,6 @@ app tokend {
 	}
 }
 
-# XXX: remove cardmod pseudodriver
+# Used by OpenSC minidriver on Windows only
 app cardmod {
-	# cardmod app name use special pcsc reader subset
-	# fix options for this reader driver here.
-
-	reader_driver cardmod {
-		# Enable pinpad if detected (PC/SC v2.0.2 Part 10)
-		# Default: true
-		# enable_pinpad = false;
-	}
 }
diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c
index fb42477..1f91dff 100644
--- a/src/libopensc/ctx.c
+++ b/src/libopensc/ctx.c
@@ -56,10 +56,8 @@ int _sc_delete_reader(sc_context_t *ctx, sc_reader_t *reader)
 	}
 	if (reader->ops->release)
 			reader->ops->release(reader);
-	if (reader->name)
-		free(reader->name);
-	if (reader->vendor)
-		free(reader->vendor);
+	free(reader->name);
+	free(reader->vendor);
 	list_delete(&ctx->readers, reader);
 	free(reader);
 	return SC_SUCCESS;
@@ -796,11 +794,6 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
 
 #ifdef ENABLE_PCSC
 	ctx->reader_driver = sc_get_pcsc_driver();
-/* XXX: remove cardmod pseudoreader driver */
-#ifdef ENABLE_MINIDRIVER
-	if(strcmp(ctx->app_name, "cardmod") == 0)
-		ctx->reader_driver = sc_get_cardmod_driver();
-#endif
 #elif defined(ENABLE_CRYPTOTOKENKIT)
 	ctx->reader_driver = sc_get_cryptotokenkit_driver();
 #elif defined(ENABLE_CTAPI)
diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h
index 9ff27d8..5d64fd6 100644
--- a/src/libopensc/internal.h
+++ b/src/libopensc/internal.h
@@ -129,10 +129,10 @@ int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_ou
 
 int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info *info);
 int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
-			 unsigned long flags, unsigned long exponent);
+		unsigned long flags, unsigned long exponent);
 int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length,
-			 unsigned long flags, unsigned long ext_flags,
-			 struct sc_object_id *curve_oid);
+		unsigned long flags, unsigned long ext_flags,
+		struct sc_object_id *curve_oid);
 
 /********************************************************************/
 /*                 pkcs1 padding/encoding functions                 */
@@ -157,7 +157,7 @@ int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
  * @return SC_SUCCESS on success and an error code otherwise
  */
 int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
-	const u8 *in, size_t inlen, u8 *out, size_t *outlen, size_t modlen);
+		const u8 *in, size_t inlen, u8 *out, size_t *outlen, size_t modlen);
 /**
  * Get the necessary padding and sec. env. flags.
  * @param  ctx     IN  sc_contex_t object
@@ -168,8 +168,8 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
  * @return SC_SUCCESS on success and an error code otherwise
  */
 int sc_get_encoding_flags(sc_context_t *ctx,
-	unsigned long iflags, unsigned long caps,
-	unsigned long *pflags, unsigned long *salg);
+		unsigned long iflags, unsigned long caps,
+		unsigned long *pflags, unsigned long *salg);
 
 /********************************************************************/
 /*             mutex functions                                      */
@@ -231,7 +231,7 @@ unsigned long sc_thread_id(const sc_context_t *ctx);
  * @return SC_SUCCESS on success and an error code otherwise
  */
 int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf,
-	size_t *len, unsigned int proto);
+		size_t *len, unsigned int proto);
 /**
  * Sets the status bytes and return data in the APDU
  * @param  ctx     sc_context_t object
@@ -241,7 +241,7 @@ int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf,
  * @return SC_SUCCESS on success and an error code otherwise
  */
 int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf,
-	size_t len);
+		size_t len);
 /**
  * Logs APDU
  * @param  ctx          sc_context_t object
@@ -256,7 +256,6 @@ int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf,
 extern struct sc_reader_driver *sc_get_pcsc_driver(void);
 extern struct sc_reader_driver *sc_get_ctapi_driver(void);
 extern struct sc_reader_driver *sc_get_openct_driver(void);
-extern struct sc_reader_driver *sc_get_cardmod_driver(void);
 extern struct sc_reader_driver *sc_get_cryptotokenkit_driver(void);
 
 #ifdef __cplusplus
diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c
index 149f529..0196c0f 100644
--- a/src/libopensc/reader-pcsc.c
+++ b/src/libopensc/reader-pcsc.c
@@ -24,6 +24,7 @@
 #endif
 
 #ifdef ENABLE_PCSC	/* empty file without pcsc */
+
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
@@ -76,16 +77,14 @@
 #define PCSC_TRACE(reader, desc, rv) do { sc_log(reader->ctx, "%s:" desc ": 0x%08lx\n", reader->name, (unsigned long)((ULONG)rv)); } while (0)
 #define PCSC_LOG(ctx, desc, rv) do { sc_log(ctx, desc ": 0x%08lx\n", (unsigned long)((ULONG)rv)); } while (0)
 
-/* Utility for handling big endian IOCTL codes. */
-#define dw2i_be(a, x) ((((((a[x] << 8) + a[x+1]) << 8) + a[x+2]) << 8) + a[x+3])
-
-#define GET_PRIV_DATA(r) ((struct pcsc_private_data *) (r)->drv_data)
-
 struct pcsc_global_private_data {
+	int cardmod;
 	SCARDCONTEXT pcsc_ctx;
 	SCARDCONTEXT pcsc_wait_ctx;
 	int enable_pinpad;
 	int enable_pace;
+	size_t force_max_recv_size;
+	size_t force_max_send_size;
 	int connect_exclusive;
 	DWORD disconnect_action;
 	DWORD transaction_end_action;
@@ -157,10 +156,8 @@ static int pcsc_to_opensc_error(LONG rv)
 		return SC_ERROR_CARD_UNRESPONSIVE;
 	case SCARD_E_SHARING_VIOLATION:
 		return SC_ERROR_READER_LOCKED;
-#ifdef SCARD_E_NO_READERS_AVAILABLE /* Older pcsc-lite does not have it */
 	case SCARD_E_NO_READERS_AVAILABLE:
 		return SC_ERROR_NO_READERS_FOUND;
-#endif
 	case SCARD_E_NO_SERVICE:
 		/* If the service is (auto)started, there could be readers later */
 		return SC_ERROR_NO_READERS_FOUND;
@@ -206,7 +203,7 @@ static int pcsc_internal_transmit(sc_reader_t *reader,
 			 u8 *recvbuf, size_t *recvsize,
 			 unsigned long control)
 {
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	SCARD_IO_REQUEST sSendPci, sRecvPci;
 	DWORD dwSendLength, dwRecvLength;
 	LONG rv;
@@ -277,6 +274,7 @@ static int pcsc_transmit(sc_reader_t *reader, sc_apdu_t *apdu)
 		r = SC_ERROR_OUT_OF_MEMORY;
 		goto out;
 	}
+
 	/* encode and log the APDU */
 	r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, reader->active_protocol);
 	if (r != SC_SUCCESS)
@@ -295,6 +293,7 @@ static int pcsc_transmit(sc_reader_t *reader, sc_apdu_t *apdu)
 	sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, rbuf, rsize, 0);
 	/* set response */
 	r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize);
+
 out:
 	if (sbuf != NULL) {
 		sc_mem_clear(sbuf, ssize);
@@ -308,10 +307,11 @@ out:
 	return r;
 }
 
-/* Calls SCardGetStatusChange on the reader to set ATR and associated flags (card present/changed) */
+/* Calls SCardGetStatusChange on the reader to set ATR and associated flags
+ * (card present/changed) */
 static int refresh_attributes(sc_reader_t *reader)
 {
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	int old_flags = reader->flags;
 	DWORD state, prev_state;
 	LONG rv;
@@ -325,8 +325,7 @@ static int refresh_attributes(sc_reader_t *reader)
 		priv->reader_state.szReader = reader->name;
 		priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
 		priv->reader_state.dwEventState = SCARD_STATE_UNAWARE;
-	}
-	else {
+	} else {
 		priv->reader_state.dwCurrentState = priv->reader_state.dwEventState;
 	}
 
@@ -334,9 +333,10 @@ static int refresh_attributes(sc_reader_t *reader)
 
 	if (rv != SCARD_S_SUCCESS) {
 		if (rv == (LONG)SCARD_E_TIMEOUT) {
-			/* Timeout, no change from previous recorded state. Make sure that changed flag is not set. */
+			/* Timeout, no change from previous recorded state. Make sure that
+			 * changed flag is not set. */
 			reader->flags &= ~SC_READER_CARD_CHANGED;
-			SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
+			LOG_FUNC_RETURN(reader->ctx, SC_SUCCESS);
 		}
 		PCSC_TRACE(reader, "SCardGetStatusChange failed", rv);
 		return pcsc_to_opensc_error(rv);
@@ -380,22 +380,20 @@ static int refresh_attributes(sc_reader_t *reader)
 			/* Requires pcsc-lite 1.6.5+ to function properly */
 			if ((state & 0xFFFF0000) != (prev_state & 0xFFFF0000)) {
 				reader->flags |= SC_READER_CARD_CHANGED;
-			}
-			else {
+			} else {
 				/* Check if the card handle is still valid. If the card changed,
 				 * the handle will be invalid. */
 				DWORD readers_len = 0, cstate, prot, atr_len = SC_MAX_ATR_SIZE;
 				unsigned char atr[SC_MAX_ATR_SIZE];
-				rv = priv->gpriv->SCardStatus(priv->pcsc_card, NULL, &readers_len, &cstate, &prot, atr, &atr_len);
+				rv = priv->gpriv->SCardStatus(priv->pcsc_card, NULL,
+						&readers_len, &cstate, &prot, atr, &atr_len);
 				if (rv == (LONG)SCARD_W_REMOVED_CARD)
 					reader->flags |= SC_READER_CARD_CHANGED;
 			}
-		}
-		else {
+		} else {
 			reader->flags |= SC_READER_CARD_CHANGED;
 		}
-	}
-	else {
+	} else {
 		reader->flags &= ~SC_READER_CARD_PRESENT;
 		if (old_flags & SC_READER_CARD_PRESENT)
 			reader->flags |= SC_READER_CARD_CHANGED;
@@ -414,8 +412,8 @@ static int pcsc_detect_card_presence(sc_reader_t *reader)
 
 	rv = refresh_attributes(reader);
 	if (rv != SC_SUCCESS)
-		SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, rv);
-	SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, reader->flags);
+		LOG_FUNC_RETURN(reader->ctx, rv);
+	LOG_FUNC_RETURN(reader->ctx, reader->flags);
 }
 
 static int check_forced_protocol(sc_context_t *ctx, struct sc_atr *atr, DWORD *protocol)
@@ -450,7 +448,7 @@ static int pcsc_reconnect(sc_reader_t * reader, DWORD action)
 	DWORD active_proto = opensc_proto_to_pcsc(reader->active_protocol),
 		  tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
 	LONG rv;
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	int r;
 
 	sc_log(reader->ctx, "Reconnecting to the card...");
@@ -472,8 +470,8 @@ static int pcsc_reconnect(sc_reader_t * reader, DWORD action)
 #endif
 
 	rv = priv->gpriv->SCardReconnect(priv->pcsc_card,
-			    priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
-			    protocol, action, &active_proto);
+			priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
+			protocol, action, &active_proto);
 
 	
 	PCSC_TRACE(reader, "SCardReconnect returned", rv);
@@ -521,53 +519,55 @@ static int pcsc_connect(sc_reader_t *reader)
 	DWORD active_proto, tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
 	SCARDHANDLE card_handle;
 	LONG rv;
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	int r;
 
 	LOG_FUNC_CALLED(reader->ctx);
 
 	r = refresh_attributes(reader);
 	if (r != SC_SUCCESS)
-		SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, r);
+		LOG_FUNC_RETURN(reader->ctx, r);
 
 	if (!(reader->flags & SC_READER_CARD_PRESENT))
-		SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_CARD_NOT_PRESENT);
+		LOG_FUNC_RETURN(reader->ctx, SC_ERROR_CARD_NOT_PRESENT);
 
 
-	rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
-			  priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
-			  protocol, &card_handle, &active_proto);
-#ifdef __APPLE__
-	if (rv == (LONG)SCARD_E_SHARING_VIOLATION) {
-		sleep(1); /* Try again to compete with Tokend probes */
+	if (!priv->gpriv->cardmod) {
 		rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
-			  priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
-			  protocol, &card_handle, &active_proto);
-	}
+				priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
+				protocol, &card_handle, &active_proto);
+#ifdef __APPLE__
+		if (rv == (LONG)SCARD_E_SHARING_VIOLATION) {
+			sleep(1); /* Try again to compete with Tokend probes */
+			rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
+					priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
+					protocol, &card_handle, &active_proto);
+		}
 #endif
-	if (rv != SCARD_S_SUCCESS) {
-		PCSC_TRACE(reader, "SCardConnect failed", rv);
-		return pcsc_to_opensc_error(rv);
-	}
-
-	reader->active_protocol = pcsc_proto_to_opensc(active_proto);
-	priv->pcsc_card = card_handle;
+		if (rv != SCARD_S_SUCCESS) {
+			PCSC_TRACE(reader, "SCardConnect failed", rv);
+			return pcsc_to_opensc_error(rv);
+		}
 
-	sc_log(reader->ctx, "Initial protocol: %s", reader->active_protocol == SC_PROTO_T1 ? "T=1" : "T=0");
+		reader->active_protocol = pcsc_proto_to_opensc(active_proto);
+		priv->pcsc_card = card_handle;
 
-	/* Check if we need a specific protocol. refresh_attributes above already sets the ATR */
-	if (check_forced_protocol(reader->ctx, &reader->atr, &tmp)) {
-		if (active_proto != tmp) {
-			sc_log(reader->ctx, "Reconnecting to force protocol");
-			r = pcsc_reconnect(reader, SCARD_UNPOWER_CARD);
-			if (r != SC_SUCCESS) {
-				sc_log(reader->ctx,
-				       "pcsc_reconnect (to force protocol) failed (%d)",
-				       r);
-				return r;
+		sc_log(reader->ctx, "Initial protocol: %s", reader->active_protocol == SC_PROTO_T1 ? "T=1" : "T=0");
+
+		/* Check if we need a specific protocol. refresh_attributes above already sets the ATR */
+		if (check_forced_protocol(reader->ctx, &reader->atr, &tmp)) {
+			if (active_proto != tmp) {
+				sc_log(reader->ctx, "Reconnecting to force protocol");
+				r = pcsc_reconnect(reader, SCARD_UNPOWER_CARD);
+				if (r != SC_SUCCESS) {
+					sc_log(reader->ctx,
+							"pcsc_reconnect (to force protocol) failed (%d)",
+							r);
+					return r;
+				}
 			}
+			sc_log(reader->ctx, "Final protocol: %s", reader->active_protocol == SC_PROTO_T1 ? "T=1" : "T=0");
 		}
-		sc_log(reader->ctx, "Final protocol: %s", reader->active_protocol == SC_PROTO_T1 ? "T=1" : "T=0");
 	}
 
 	initialize_uid(reader);
@@ -580,13 +580,10 @@ static int pcsc_connect(sc_reader_t *reader)
 
 static int pcsc_disconnect(sc_reader_t * reader)
 {
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
-	LONG rv;
-
-	LOG_FUNC_CALLED(reader->ctx);
+	struct pcsc_private_data *priv = reader->drv_data;
 
-	if (!(reader->ctx->flags & SC_CTX_FLAG_TERMINATE)) {
-		rv = priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action);
+	if (!priv->gpriv->cardmod && !(reader->ctx->flags & SC_CTX_FLAG_TERMINATE)) {
+		LONG rv = priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action);
 		PCSC_TRACE(reader, "SCardDisconnect returned", rv);
 	}
 	reader->flags = 0;
@@ -597,7 +594,10 @@ static int pcsc_lock(sc_reader_t *reader)
 {
 	LONG rv;
 	int r;
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
+
+	if (priv->gpriv->cardmod)
+		return SC_SUCCESS;
 
 	LOG_FUNC_CALLED(reader->ctx);
 
@@ -608,7 +608,7 @@ static int pcsc_lock(sc_reader_t *reader)
 
 
 	if (rv != SCARD_S_SUCCESS)
-	    PCSC_TRACE(reader, "SCardBeginTransaction returned", rv);
+		PCSC_TRACE(reader, "SCardBeginTransaction returned", rv);
 
 	switch (rv) {
 		case SCARD_E_INVALID_HANDLE:
@@ -616,7 +616,7 @@ static int pcsc_lock(sc_reader_t *reader)
 			r = pcsc_connect(reader);
 			if (r != SC_SUCCESS) {
 				sc_log(reader->ctx, "pcsc_connect failed (%d)",
-				       r);
+						r);
 				return r;
 			}
 			/* return failure so that upper layers will be notified and try to lock again */
@@ -627,7 +627,7 @@ static int pcsc_lock(sc_reader_t *reader)
 			r = pcsc_reconnect(reader, SCARD_LEAVE_CARD);
 			if (r != SC_SUCCESS) {
 				sc_log(reader->ctx,
-				       "pcsc_reconnect failed (%d)", r);
+						"pcsc_reconnect failed (%d)", r);
 				return r;
 			}
 			/* return failure so that upper layers will be notified and try to lock again */
@@ -644,7 +644,10 @@ static int pcsc_lock(sc_reader_t *reader)
 static int pcsc_unlock(sc_reader_t *reader)
 {
 	LONG rv;
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
+
+	if (priv->gpriv->cardmod)
+		return SC_SUCCESS;
 
 	LOG_FUNC_CALLED(reader->ctx);
 
@@ -663,7 +666,7 @@ static int pcsc_unlock(sc_reader_t *reader)
 
 static int pcsc_release(sc_reader_t *reader)
 {
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 
 	free(priv);
 	return SC_SUCCESS;
@@ -673,7 +676,7 @@ static int pcsc_reset(sc_reader_t *reader, int do_cold_reset)
 {
 	int r;
 #ifndef HAVE_PCSCLITE
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	int old_locked = priv->locked;
 #endif
 
@@ -742,42 +745,64 @@ static int pcsc_init(sc_context_t *ctx)
 		goto out;
 	}
 
-	/* Defaults */
+	if(strcmp(ctx->app_name, "cardmod") == 0) {
+		gpriv->cardmod = 1;
+	}
+
+	/* PC/SC Defaults */
+	gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
 	gpriv->connect_exclusive = 0;
 	gpriv->disconnect_action = SCARD_RESET_CARD;
 	gpriv->transaction_end_action = SCARD_LEAVE_CARD;
 	gpriv->reconnect_action = SCARD_LEAVE_CARD;
 	gpriv->enable_pinpad = 1;
 	gpriv->enable_pace = 1;
-	gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
 	gpriv->pcsc_ctx = -1;
 	gpriv->pcsc_wait_ctx = -1;
+	/* max send/receive sizes: if exist in configuration these options overwrite
+	 *			   the values by default and values declared by reader */
+	gpriv->force_max_send_size = 0;
+	gpriv->force_max_recv_size = 0;
 
 	conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1);
 	if (conf_block) {
+		gpriv->provider_library =
+			scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
 		gpriv->connect_exclusive =
-		    scconf_get_bool(conf_block, "connect_exclusive", gpriv->connect_exclusive);
+			scconf_get_bool(conf_block, "connect_exclusive", gpriv->connect_exclusive);
 		gpriv->disconnect_action =
-		    pcsc_reset_action(scconf_get_str(conf_block, "disconnect_action", "reset"));
+			pcsc_reset_action(scconf_get_str(conf_block, "disconnect_action", "reset"));
 		gpriv->transaction_end_action =
-		    pcsc_reset_action(scconf_get_str(conf_block, "transaction_end_action", "leave"));
+			pcsc_reset_action(scconf_get_str(conf_block, "transaction_end_action", "leave"));
 		gpriv->reconnect_action =
-		    pcsc_reset_action(scconf_get_str(conf_block, "reconnect_action", "leave"));
-		gpriv->enable_pinpad =
-		    scconf_get_bool(conf_block, "enable_pinpad", gpriv->enable_pinpad);
-		gpriv->enable_pace =
-		    scconf_get_bool(conf_block, "enable_pace", gpriv->enable_pace);
-		gpriv->provider_library =
-		    scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
+			pcsc_reset_action(scconf_get_str(conf_block, "reconnect_action", "leave"));
+		gpriv->enable_pinpad = scconf_get_bool(conf_block, "enable_pinpad",
+				gpriv->enable_pinpad);
+		gpriv->enable_pace = scconf_get_bool(conf_block, "enable_pace",
+				gpriv->enable_pace);
+		gpriv->force_max_send_size = scconf_get_int(conf_block,
+				"max_send_size", gpriv->force_max_send_size);
+		gpriv->force_max_recv_size = scconf_get_int(conf_block,
+				"max_recv_size", gpriv->force_max_recv_size);
+	}
+
+	if (gpriv->cardmod) {
+		/* for cardmod, don't manipulate winscard.dll or the OS's builtin
+		 * management of SCARDHANDLEs */
+		gpriv->provider_library = DEFAULT_PCSC_PROVIDER;
+		gpriv->connect_exclusive = 0;
+		gpriv->disconnect_action = SCARD_LEAVE_CARD;
+		gpriv->transaction_end_action = SCARD_LEAVE_CARD;
+		gpriv->reconnect_action = SCARD_LEAVE_CARD;
 	}
 	sc_log(ctx,
-	       "PC/SC options: connect_exclusive=%d disconnect_action=%u transaction_end_action=%u"
-	       " reconnect_action=%u enable_pinpad=%d enable_pace=%d",
-	       gpriv->connect_exclusive,
-	       (unsigned int)gpriv->disconnect_action,
-	       (unsigned int)gpriv->transaction_end_action,
-	       (unsigned int)gpriv->reconnect_action, gpriv->enable_pinpad,
-	       gpriv->enable_pace);
+			"PC/SC options: connect_exclusive=%d disconnect_action=%u transaction_end_action=%u"
+			" reconnect_action=%u enable_pinpad=%d enable_pace=%d",
+			gpriv->connect_exclusive,
+			(unsigned int)gpriv->disconnect_action,
+			(unsigned int)gpriv->transaction_end_action,
+			(unsigned int)gpriv->reconnect_action, gpriv->enable_pinpad,
+			gpriv->enable_pace);
 
 	gpriv->dlhandle = sc_dlopen(gpriv->provider_library);
 	if (gpriv->dlhandle == NULL) {
@@ -853,6 +878,7 @@ out:
 	return ret;
 }
 
+
 static int pcsc_finish(sc_context_t *ctx)
 {
 	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
@@ -860,7 +886,8 @@ static int pcsc_finish(sc_context_t *ctx)
 	LOG_FUNC_CALLED(ctx);
 
 	if (gpriv) {
-		if (gpriv->pcsc_ctx != (SCARDCONTEXT)-1 && !(ctx->flags & SC_CTX_FLAG_TERMINATE))
+		if (!gpriv->cardmod && gpriv->pcsc_ctx != (SCARDCONTEXT)-1 &&
+				!(ctx->flags & SC_CTX_FLAG_TERMINATE))
 			gpriv->SCardReleaseContext(gpriv->pcsc_ctx);
 		if (gpriv->dlhandle != NULL)
 			sc_dlclose(gpriv->dlhandle);
@@ -870,6 +897,7 @@ static int pcsc_finish(sc_context_t *ctx)
 	return SC_SUCCESS;
 }
 
+
 /**
  * @brief Detects reader's PACE capabilities
  *
@@ -891,7 +919,7 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader, SCARDH
 
 	if (!reader)
 		goto err;
-	priv = GET_PRIV_DATA(reader);
+	priv = reader->drv_data;
 	if (!priv)
 		goto err;
 
@@ -923,10 +951,10 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader, SCARDH
 		flags |= SC_READER_CAP_PACE_GENERIC;
 	if (*p & PACE_CAPABILITY_DestroyPACEChannel)
 		flags |= SC_READER_CAP_PACE_DESTROY_CHANNEL;
-    }
+	}
 
 err:
-    return flags;
+	return flags;
 }
 
 static int
@@ -950,7 +978,7 @@ static size_t part10_detect_max_data(sc_reader_t *reader, SCARDHANDLE card_handl
 
 	if (!reader)
 		goto err;
-	priv = GET_PRIV_DATA(reader);
+	priv = reader->drv_data;
 	if (!priv)
 		goto err;
 
@@ -983,7 +1011,7 @@ static int part10_get_vendor_product(struct sc_reader *reader,
 
 	if (!reader)
 		return SC_ERROR_INVALID_ARGUMENTS;
-	priv = GET_PRIV_DATA(reader);
+	priv = reader->drv_data;
 	if (!priv)
 		return SC_ERROR_INVALID_ARGUMENTS;
 
@@ -1015,7 +1043,7 @@ static int part10_get_vendor_product(struct sc_reader *reader,
 static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) {
 	sc_context_t *ctx = reader->ctx;
 	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
 	DWORD rcount, feature_len, i;
 	PCSC_TLV_STRUCTURE *pcsc_tlv;
@@ -1024,6 +1052,8 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
 
 	LOG_FUNC_CALLED(ctx);
 
+	sc_log(ctx, "Requesting reader features ... ");
+
 	if (gpriv->SCardControl == NULL)
 		return;
 
@@ -1115,9 +1145,9 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
 			}
 			else   {
 				sc_log(ctx,
-				       "Returned PIN properties structure has bad length (%lu/%"SC_FORMAT_LEN_SIZE_T"u)",
-				       (unsigned long)rcount,
-				       sizeof(PIN_PROPERTIES_STRUCTURE));
+						"Returned PIN properties structure has bad length (%lu/%"SC_FORMAT_LEN_SIZE_T"u)",
+						(unsigned long)rcount,
+						sizeof(PIN_PROPERTIES_STRUCTURE));
 			}
 		}
 	}
@@ -1135,13 +1165,34 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
 		}
 	}
 
+	/* max send/receive sizes: with default values only short APDU supported */
+	reader->max_send_size = priv->gpriv->force_max_send_size ?
+		priv->gpriv->force_max_send_size :
+		SC_READER_SHORT_APDU_MAX_SEND_SIZE;
+	reader->max_recv_size = priv->gpriv->force_max_recv_size ?
+		priv->gpriv->force_max_recv_size :
+		SC_READER_SHORT_APDU_MAX_RECV_SIZE;
 	if (priv->get_tlv_properties) {
 		/* Try to set reader max_send_size and max_recv_size based on
 		 * detected max_data */
 		int max_data = part10_detect_max_data(reader, card_handle);
-		if (max_data > 0)   {
-			reader->max_send_size = max_data;
-			reader->max_recv_size = max_data;
+
+		if (max_data > 0) {
+			sc_log(ctx, "Reader supports transceiving %d bytes of data",
+					max_data);
+			if (priv->gpriv->force_max_send_size)
+				reader->max_send_size = max_data;
+			else
+				sc_log(ctx, "Sending is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data"
+						" in configuration file", reader->max_send_size);
+			if (!priv->gpriv->force_max_recv_size)
+				reader->max_recv_size = max_data;
+			else
+				sc_log(ctx, "Receiving is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data"
+						" in configuration file", reader->max_recv_size);
+		} else {
+			sc_log(ctx, "Assuming that the reader supports transceiving "
+					"short length APDUs only");
 		}
 
 		/* debug the product and vendor ID of the reader */
@@ -1169,6 +1220,45 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
 	}
 }
 
+int pcsc_add_reader(sc_context_t *ctx,
+	   	char *reader_name, size_t reader_name_len,
+		sc_reader_t **out_reader)
+{
+	int ret = SC_ERROR_INTERNAL;
+	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
+	struct pcsc_private_data *priv;
+	sc_reader_t *reader;
+
+	sc_log(ctx, "Adding new PC/SC reader '%s'", reader_name);
+
+	if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) {
+		ret = SC_ERROR_OUT_OF_MEMORY;
+		goto err1;
+	}
+	*out_reader = reader;
+	if ((priv = calloc(1, sizeof(struct pcsc_private_data))) == NULL) {
+		ret = SC_ERROR_OUT_OF_MEMORY;
+		goto err1;
+	}
+
+	priv->gpriv = gpriv;
+
+	reader->drv_data = priv;
+	reader->ops = &pcsc_ops;
+	reader->driver = &pcsc_drv;
+	if ((reader->name = strdup(reader_name)) == NULL) {
+		ret = SC_ERROR_OUT_OF_MEMORY;
+		goto err1;
+	}
+
+	ret = _sc_add_reader(ctx, reader);
+
+	refresh_attributes(reader);
+
+err1:
+	return ret;
+}
+
 static int pcsc_detect_readers(sc_context_t *ctx)
 {
 	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
@@ -1188,6 +1278,11 @@ static int pcsc_detect_readers(sc_context_t *ctx)
 		goto out;
 	}
 
+	if (gpriv->cardmod) {
+		ret = SC_ERROR_NOT_ALLOWED;
+		goto out;
+	}
+
 	/* temporarily mark all readers as removed */
 	for (i=0;i < sc_ctx_get_reader_count(ctx);i++) {
 		sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
@@ -1204,12 +1299,12 @@ static int pcsc_detect_readers(sc_context_t *ctx)
 			 * is returned instead of SCARD_E_INVALID_HANDLE
 			 */
 			rv = SCARD_E_INVALID_HANDLE;
-		}
-		else {
-			rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL, (LPDWORD) &reader_buf_size);
+		} else {
+			rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL,
+					NULL, (LPDWORD) &reader_buf_size);
 			if (rv == (LONG)SCARD_E_NO_SERVICE) {
 				gpriv->SCardReleaseContext(gpriv->pcsc_ctx);
-				gpriv->pcsc_ctx = -1;
+				gpriv->pcsc_ctx = 0;
 				gpriv->pcsc_wait_ctx = -1;
 				/* reconnecting below may may restart PC/SC service */
 				rv = SCARD_E_INVALID_HANDLE;
@@ -1231,6 +1326,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
 				goto out;
 			}
 
+			/* try to fetch the list of readers again */
 			rv = SCARD_E_INVALID_HANDLE;
 		}
 	} while (rv != SCARD_S_SUCCESS);
@@ -1240,23 +1336,25 @@ static int pcsc_detect_readers(sc_context_t *ctx)
 		ret = SC_ERROR_OUT_OF_MEMORY;
 		goto out;
 	}
-	rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, mszGroups, reader_buf, (LPDWORD) &reader_buf_size);
+	rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, mszGroups, reader_buf,
+			(LPDWORD) &reader_buf_size);
 	if (rv != SCARD_S_SUCCESS) {
 		PCSC_LOG(ctx, "SCardListReaders failed", rv);
 		ret = pcsc_to_opensc_error(rv);
 		goto out;
 	}
-	for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen(reader_name) + 1) {
+
+	for (reader_name = reader_buf; *reader_name != '\x0';
+		   	reader_name += strlen(reader_name) + 1) {
 		sc_reader_t *reader = NULL, *old_reader = NULL;
 		struct pcsc_private_data *priv = NULL;
-		scconf_block *conf_block = NULL;
 		int found = 0;
 
 		for (i=0;i < sc_ctx_get_reader_count(ctx) && !found;i++) {
 			old_reader = sc_ctx_get_reader(ctx, i);
 			if (old_reader == NULL) {
 				ret = SC_ERROR_INTERNAL;
-				goto err1;
+				goto out;
 			}
 			if (!strcmp(old_reader->name, reader_name)) {
 				found = 1;
@@ -1269,105 +1367,50 @@ static int pcsc_detect_readers(sc_context_t *ctx)
 			continue;
 		}
 
-		sc_log(ctx, "Found new PC/SC reader '%s'", reader_name);
-
-		if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) {
-			ret = SC_ERROR_OUT_OF_MEMORY;
-			goto err1;
-		}
-		if ((priv = calloc(1, sizeof(struct pcsc_private_data))) == NULL) {
-			ret = SC_ERROR_OUT_OF_MEMORY;
-			goto err1;
-		}
-
-		reader->drv_data = priv;
-		reader->ops = &pcsc_ops;
-		reader->driver = &pcsc_drv;
-		if ((reader->name = strdup(reader_name)) == NULL) {
-			ret = SC_ERROR_OUT_OF_MEMORY;
-			goto err1;
-		}
-
-		priv->gpriv = gpriv;
-		if (_sc_add_reader(ctx, reader)) {
-			ret = SC_SUCCESS;	/* silent ignore */
-			goto err1;
+		ret = pcsc_add_reader(ctx, reader_name, strlen(reader_name), &reader);
+		if (ret != SC_SUCCESS) {
+			_sc_delete_reader(ctx, reader);
+			continue;
 		}
 
-		/* TODO need to check return codes */
-		refresh_attributes(reader);
-
 		/* check for pinpad support early, to allow opensc-tool -l display accurate information */
-		if (gpriv->SCardControl != NULL) {
-			if (priv->reader_state.dwEventState & SCARD_STATE_EXCLUSIVE)
-				continue;
-
-			sc_log(ctx, "Requesting reader features ... ");
+		priv = reader->drv_data;
+		if (priv->reader_state.dwEventState & SCARD_STATE_EXCLUSIVE)
+			continue;
 
-			rv = SCARD_E_SHARING_VIOLATION;
-			/* Use DIRECT mode only if there is no card in the reader */
-			if (!(reader->flags & SC_READER_CARD_PRESENT)) {
+		rv = SCARD_E_SHARING_VIOLATION;
+		/* Use DIRECT mode only if there is no card in the reader */
+		if (!(reader->flags & SC_READER_CARD_PRESENT)) {
 #ifndef _WIN32	/* Apple 10.5.7 and pcsc-lite previous to v1.5.5 do not support 0 as protocol identifier */
-				rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &card_handle, &active_proto);
+			rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &card_handle, &active_proto);
 #else
-				rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, 0, &card_handle, &active_proto);
+			rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, 0, &card_handle, &active_proto);
 #endif
-				PCSC_TRACE(reader, "SCardConnect(DIRECT)", rv);
-			}
-			if (rv == (LONG)SCARD_E_SHARING_VIOLATION) { /* Assume that there is a card in the reader in shared mode if direct communcation failed */
-				rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &card_handle, &active_proto);
-				PCSC_TRACE(reader, "SCardConnect(SHARED)", rv);
-			}
-
-			/* max send/receive sizes: with default values only short APDU supported */
-			reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE;
-			reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE;
-
-			/* max send/receive sizes: check if reader explicitely declares support of extended APDU */
-			if (rv == SCARD_S_SUCCESS) {
-				detect_reader_features(reader, card_handle);
-				gpriv->SCardDisconnect(card_handle, SCARD_LEAVE_CARD);
-			}
-
-			/* max send/receive sizes: if exist in configuration these options overwrite
-			 *			   the values by default and values declared by reader */
-			conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1);
-			if (conf_block) {
-				reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
-				reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
-				if (scconf_get_bool(conf_block, "enable_escape", 0))
-					reader->flags |= SC_READER_ENABLE_ESCAPE;
-			}
-
-			sc_log(ctx,
-			       "reader's max-send-size: %"SC_FORMAT_LEN_SIZE_T"u, max-recv-size: %"SC_FORMAT_LEN_SIZE_T"u",
-			       reader->max_send_size, reader->max_recv_size);
+			PCSC_TRACE(reader, "SCardConnect(DIRECT)", rv);
 		}
-
-		continue;
-
-	err1:
-		if (priv != NULL) {
-			free(priv);
+		if (rv == (LONG)SCARD_E_SHARING_VIOLATION) {
+			/* Assume that there is a card in the reader in shared mode if
+			 * direct communcation failed */
+			rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name,
+					SCARD_SHARE_SHARED,
+					SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &card_handle,
+					&active_proto);
+			PCSC_TRACE(reader, "SCardConnect(SHARED)", rv);
+			reader->active_protocol = pcsc_proto_to_opensc(active_proto);
 		}
-		if (reader != NULL) {
-			if (reader->name)
-				free(reader->name);
-			if (reader->vendor)
-				free(reader->vendor);
-			free(reader);
+
+		if (rv == SCARD_S_SUCCESS) {
+			detect_reader_features(reader, card_handle);
+			gpriv->SCardDisconnect(card_handle, SCARD_LEAVE_CARD);
 		}
-		goto out;
 	}
 
 	ret = SC_SUCCESS;
 
 out:
+	free(reader_buf);
 
-	if (reader_buf != NULL)
-		free (reader_buf);
-
-	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, ret);
+	LOG_FUNC_RETURN(ctx, ret);
 }
 
 
@@ -1390,13 +1433,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
 		sc_log(ctx, "free allocated reader states");
 		free(*reader_states);
 		*reader_states = NULL;
-		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
+		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
 	}
 
 	if (reader_states == NULL || *reader_states == NULL) {
 		rgReaderStates = calloc(sc_ctx_get_reader_count(ctx) + 2, sizeof(SCARD_READERSTATE));
 		if (!rgReaderStates)
-			SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
+			LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
 
 		/* Find out the current status */
 		num_watch = sc_ctx_get_reader_count(ctx);
@@ -1467,9 +1510,9 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
 		for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) {
 			DWORD state, prev_state;
 			sc_log(ctx, "'%s' before=0x%08X now=0x%08X",
-			       rsp->szReader,
-			       (unsigned int)rsp->dwCurrentState,
-			       (unsigned int)rsp->dwEventState);
+					rsp->szReader,
+					(unsigned int)rsp->dwCurrentState,
+					(unsigned int)rsp->dwEventState);
 			prev_state = rsp->dwCurrentState;
 			state = rsp->dwEventState;
 			rsp->dwCurrentState = rsp->dwEventState;
@@ -1556,7 +1599,7 @@ out:
 		*reader_states = rgReaderStates;
 	}
 
-	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
+	LOG_FUNC_RETURN(ctx, r);
 }
 
 
@@ -1841,12 +1884,12 @@ part10_check_pin_min_max(sc_reader_t *reader, struct sc_pin_cmd_data *data)
 	int r;
 	unsigned char buffer[256];
 	size_t length = sizeof buffer;
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	struct sc_pin_cmd_pin *pin_ref =
 		data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ?
 		&data->pin1 : &data->pin2;
 
-    if (!priv->get_tlv_properties)
+	if (!priv->get_tlv_properties)
 		return 0;
 
 	r = pcsc_internal_transmit(reader, NULL, 0, buffer, &length,
@@ -1883,7 +1926,7 @@ part10_check_pin_min_max(sc_reader_t *reader, struct sc_pin_cmd_data *data)
 static int
 pcsc_pin_cmd(sc_reader_t *reader, struct sc_pin_cmd_data *data)
 {
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
+	struct pcsc_private_data *priv = reader->drv_data;
 	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
 	/* sbuf holds a pin verification/modification structure plus an APDU. */
 	u8 sbuf[sizeof(PIN_VERIFY_STRUCTURE)>sizeof(PIN_MODIFY_STRUCTURE)?
@@ -1944,9 +1987,9 @@ pcsc_pin_cmd(sc_reader_t *reader, struct sc_pin_cmd_data *data)
 	LOG_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad: block transmit failed!");
 	/* finish the call if it was a two-phase operation */
 	if ((ioctl == priv->verify_ioctl_start)
-	    || (ioctl == priv->modify_ioctl_start)) {
+			|| (ioctl == priv->modify_ioctl_start)) {
 		if (rcount != 0) {
-			SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+			LOG_FUNC_RETURN(reader->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
 		}
 		ioctl = (ioctl == priv->verify_ioctl_start) ? priv->verify_ioctl_finish : priv->modify_ioctl_finish;
 
@@ -1957,7 +2000,7 @@ pcsc_pin_cmd(sc_reader_t *reader, struct sc_pin_cmd_data *data)
 
 	/* We expect only two bytes of result data (SW1 and SW2) */
 	if (rcount != 2) {
-		SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+		LOG_FUNC_RETURN(reader->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
 	}
 
 	/* Extract the SWs for the result APDU */
@@ -2196,7 +2239,7 @@ pcsc_perform_pace(struct sc_reader *reader, void *input_pace, void *output_pace)
 	if (!reader || !(reader->capabilities & SC_READER_CAP_PACE_GENERIC))
 		return SC_ERROR_INVALID_ARGUMENTS;
 
-	priv = GET_PRIV_DATA(reader);
+	priv = reader->drv_data;
 	if (!priv)
 		return SC_ERROR_INVALID_ARGUMENTS;
 
@@ -2216,157 +2259,27 @@ pcsc_perform_pace(struct sc_reader *reader, void *input_pace, void *output_pace)
 	return SC_SUCCESS;
 }
 
-struct sc_reader_driver * sc_get_pcsc_driver(void)
+static void detect_protocol(sc_reader_t *reader, SCARDHANDLE card_handle)
 {
-	pcsc_ops.init = pcsc_init;
-	pcsc_ops.finish = pcsc_finish;
-	pcsc_ops.detect_readers = pcsc_detect_readers;
-	pcsc_ops.transmit = pcsc_transmit;
-	pcsc_ops.detect_card_presence = pcsc_detect_card_presence;
-	pcsc_ops.lock = pcsc_lock;
-	pcsc_ops.unlock = pcsc_unlock;
-	pcsc_ops.release = pcsc_release;
-	pcsc_ops.connect = pcsc_connect;
-	pcsc_ops.disconnect = pcsc_disconnect;
-	pcsc_ops.perform_verify = pcsc_pin_cmd;
-	pcsc_ops.wait_for_event = pcsc_wait_for_event;
-	pcsc_ops.cancel = pcsc_cancel;
-	pcsc_ops.reset = pcsc_reset;
-	pcsc_ops.use_reader = NULL;
-	pcsc_ops.perform_pace = pcsc_perform_pace;
-
-	return &pcsc_drv;
-}
-
-#ifdef ENABLE_MINIDRIVER
-
-static int cardmod_connect(sc_reader_t *reader)
-{
-	int r;
-
-	r = refresh_attributes(reader);
-	if (r)
-		return r;
-	if (!(reader->flags & SC_READER_CARD_PRESENT))
-		return SC_ERROR_CARD_NOT_PRESENT;
-
-	initialize_uid(reader);
-
-	return SC_SUCCESS;
-}
-
-static int cardmod_disconnect(sc_reader_t * reader)
-{
-	reader->flags = 0;
-	return SC_SUCCESS;
-}
-
-static struct sc_reader_operations cardmod_ops;
-
-static struct sc_reader_driver cardmod_drv = {
-	"PC/SC cardmod reader",
-	"cardmod",
-	&cardmod_ops,
-	NULL
-};
-
-static int cardmod_init(sc_context_t *ctx)
-{
-	struct pcsc_global_private_data *gpriv;
-	scconf_block *conf_block = NULL;
-	int ret = SC_ERROR_INTERNAL;
-
-	gpriv = calloc(1, sizeof(struct pcsc_global_private_data));
-	if (gpriv == NULL) {
-		ret = SC_ERROR_OUT_OF_MEMORY;
-		goto out;
-	}
-
-	/* Defaults */
-	gpriv->enable_pinpad = 1;
-
-	conf_block = sc_get_conf_block(ctx, "reader_driver", "cardmod", 1);
-	if (conf_block) {
-		    scconf_get_bool(conf_block, "enable_pinpad", gpriv->enable_pinpad);
-	}
-	sc_log(ctx, "PC/SC options: enable_pinpad=%d", gpriv->enable_pinpad);
-
-	gpriv->dlhandle = sc_dlopen("winscard.dll");
-	if (gpriv->dlhandle == NULL) {
-		ret = SC_ERROR_CANNOT_LOAD_MODULE;
-		goto out;
-	}
-
-	gpriv->SCardStatus = (SCardStatus_t)sc_dlsym(gpriv->dlhandle, "SCardStatus");
-	gpriv->SCardGetStatusChange = (SCardGetStatusChange_t)sc_dlsym(gpriv->dlhandle, "SCardGetStatusChange");
-	gpriv->SCardTransmit = (SCardTransmit_t)sc_dlsym(gpriv->dlhandle, "SCardTransmit");
-
-	if (gpriv->SCardStatus == NULL)
-		gpriv->SCardStatus = (SCardStatus_t)sc_dlsym(gpriv->dlhandle, "SCardStatusA");
-	if (gpriv->SCardGetStatusChange == NULL)
-		gpriv->SCardGetStatusChange = (SCardGetStatusChange_t)sc_dlsym(gpriv->dlhandle, "SCardGetStatusChangeA");
-
-	gpriv->SCardGetAttrib = sc_dlsym(gpriv->dlhandle, "SCardGetAttrib");
-
-	/* If we have SCardGetAttrib it is correct API */
-	if (gpriv->SCardGetAttrib != NULL) {
-		if (gpriv->SCardControl == NULL) {
-			gpriv->SCardControl = (SCardControl_t)sc_dlsym(gpriv->dlhandle, "SCardControl");
-		}
-	}
-	else {
-		/* gpriv->SCardControlOLD = (SCardControlOLD_t)sc_dlsym(gpriv->dlhandle, "SCardControl"); */
-	}
-
-	if (
-		gpriv->SCardStatus == NULL ||
-		gpriv->SCardGetStatusChange == NULL ||
-		gpriv->SCardControl == NULL ||
-		gpriv->SCardTransmit == NULL ||
-		gpriv->SCardGetAttrib == NULL) {
-		ret = SC_ERROR_CANNOT_LOAD_MODULE;
-		goto out;
-	}
-
-	ctx->reader_drv_data = gpriv;
-	gpriv = NULL;
-	ret = SC_SUCCESS;
-
-out:
-	if (gpriv != NULL) {
-		if (gpriv->dlhandle != NULL)
-			sc_dlclose(gpriv->dlhandle);
-		free(gpriv);
-	}
-
-	return ret;
-}
-
-static int cardmod_finish(sc_context_t *ctx)
-{
-	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
-
-	if (gpriv) {
-		if (gpriv->dlhandle != NULL)
-			sc_dlclose(gpriv->dlhandle);
-		free(gpriv);
+	DWORD readers_len = 0, state, prot, atr_len = SC_MAX_ATR_SIZE;
+	unsigned char atr[SC_MAX_ATR_SIZE];
+	struct pcsc_private_data *priv = reader->drv_data;
+	/* attempt to detect protocol in use T0/T1/RAW */
+	DWORD rv = priv->gpriv->SCardStatus(card_handle, NULL,
+			&readers_len, &state, &prot, atr, &atr_len);
+	if (rv != SCARD_S_SUCCESS) {
+		prot = SCARD_PROTOCOL_T0;
 	}
-
-	return SC_SUCCESS;
+	reader->active_protocol = pcsc_proto_to_opensc(prot);
 }
 
-int cardmod_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_card_handle)
+int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_card_handle)
 {
 	SCARDHANDLE card_handle;
-	u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
-	PCSC_TLV_STRUCTURE *pcsc_tlv;
-	scconf_block *conf_block = NULL;
 	struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
-	LONG rv;
-	BYTE reader_name[128];
-	DWORD rcount, feature_len, display_ioctl = 0, reader_name_size = sizeof(reader_name);
+	char reader_name[128];
+	DWORD reader_name_size = sizeof(reader_name);
 	int ret = SC_ERROR_INTERNAL;
-	unsigned int i;
 
 	LOG_FUNC_CALLED(ctx);
 
@@ -2382,257 +2295,51 @@ int cardmod_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcs
 			_sc_delete_reader(ctx, oldrdr);
 	}
 
-	sc_log(ctx, "Probing pcsc readers");
+	sc_log(ctx, "Probing PC/SC reader");
 
 	gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle;
 	card_handle =  *(SCARDHANDLE *)pcsc_card_handle;
 
-	sc_log(ctx, "gpriv->pcsc_ctx = %llX, card_handle = %llX",
-	       (unsigned long long)gpriv->pcsc_ctx,
-	       (unsigned long long)card_handle);
-
-	if(gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_DEVICE_SYSTEM_NAME_A, \
-			reader_name, &reader_name_size) == SCARD_S_SUCCESS)
-	{
+	if(SCARD_S_SUCCESS == gpriv->SCardGetAttrib(card_handle,
+				SCARD_ATTR_DEVICE_SYSTEM_NAME_A, (LPBYTE)
+				reader_name, &reader_name_size)) {
 		sc_reader_t *reader = NULL;
-		struct pcsc_private_data *priv = NULL;
-		DWORD readers_len = 0, state, prot, atr_len = SC_MAX_ATR_SIZE;
-		unsigned char atr[SC_MAX_ATR_SIZE];
-		char texte[2048];
-
-		sc_bin_to_hex(reader_name, reader_name_size, texte, sizeof(texte)-5, ':');
-		sc_log(ctx, "lecteur name = %s\n%s\n", reader_name,texte);
-
-		if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) {
-			ret = SC_ERROR_OUT_OF_MEMORY;
-			goto err1;
-		}
-		if ((priv = calloc(1, sizeof(struct pcsc_private_data))) == NULL) {
-			ret = SC_ERROR_OUT_OF_MEMORY;
-			goto err1;
-		}
-
-		reader->drv_data = priv;
-		reader->ops = &cardmod_ops;
-		reader->driver = &cardmod_drv;
-		if ((reader->name = strdup((const char *)reader_name)) == NULL) {
-			ret = SC_ERROR_OUT_OF_MEMORY;
-			goto err1;
-		}
-		priv->gpriv = gpriv;
-
-		reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE;
-		reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE;
-
-		conf_block = sc_get_conf_block(ctx, "reader_driver", "cardmod", 1);
-		if (conf_block) {
-			reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
-			reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
-			if (scconf_get_bool(conf_block, "enable_escape", 0))
-				reader->flags |= SC_READER_ENABLE_ESCAPE;
-		}
-
-		/* attempt to detect protocol in use T0/T1/RAW */
-		rv = priv->gpriv->SCardStatus(card_handle, NULL, &readers_len,
-			&state, &prot, atr, &atr_len);
-		if (rv != SCARD_S_SUCCESS)
-		{
-			sc_log(ctx, "SCardStatus failed %08lx", rv);
-			prot = SCARD_PROTOCOL_T0;
-		}
-		sc_log(ctx, "Set protocole to %s", \
-			(prot==SCARD_PROTOCOL_T0)?"T0":((prot==SCARD_PROTOCOL_T1)?"T1":"RAW"));
-		reader->active_protocol = pcsc_proto_to_opensc(prot);
 
-		if (_sc_add_reader(ctx, reader)) {
-			ret = SC_SUCCESS;	/* silent ignore */
-			goto err1;
-		}
-		priv->pcsc_card = card_handle;
-
-		/* check for pinpad support */
-		if (gpriv->SCardControl != NULL)
-		{
-			sc_log(ctx, "Requesting reader features ... ");
-			rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len);
-			if (rv != SCARD_S_SUCCESS)
-			{
-				sc_log(ctx, "SCardControl failed %08lx", rv);
-			}
-			else
-			{
-				if ((feature_len % sizeof(PCSC_TLV_STRUCTURE)) != 0)
-				{
-					sc_log(ctx, "Inconsistent TLV from reader!");
-				}
-				else
-				{
-					char *log_disabled = "but it's disabled in configuration file";
-					/* get the number of elements instead of the complete size */
-					feature_len /= sizeof(PCSC_TLV_STRUCTURE);
-
-					pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature_buf;
-					for (i = 0; i < feature_len; i++)
-					{
-						sc_log(ctx, "Reader feature %02x detected", pcsc_tlv[i].tag);
-						if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT)
-						{
-							priv->verify_ioctl = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_START)
-						{
-							priv->verify_ioctl_start = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_FINISH)
-						{
-							priv->verify_ioctl_finish = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT)
-						{
-							priv->modify_ioctl = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_START)
-						{
-							priv->modify_ioctl_start = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_FINISH)
-						{
-							priv->modify_ioctl_finish = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES)
-						{
-							display_ioctl = ntohl(pcsc_tlv[i].value);
-						}
-						else if (pcsc_tlv[i].tag == FEATURE_EXECUTE_PACE)
-						{
-							priv->pace_ioctl = ntohl(pcsc_tlv[i].value);
-						}
-						else
-						{
-							sc_log(ctx, "Reader feature %02x is not supported", pcsc_tlv[i].tag);
-						}
-					}
-
-					/* Set slot capabilities based on detected IOCTLs */
-					if (priv->verify_ioctl || (priv->verify_ioctl_start && priv->verify_ioctl_finish)) {
-						char *log_text = "Reader supports pinpad PIN verification";
-						if (priv->gpriv->enable_pinpad) {
-							sc_log(ctx, "%s", log_text);
-							reader->capabilities |= SC_READER_CAP_PIN_PAD;
-						} else {
-							sc_log(ctx, "%s %s", log_text, log_disabled);
-						}
-					}
-
-					if (priv->modify_ioctl || (priv->modify_ioctl_start && priv->modify_ioctl_finish)) {
-						char *log_text = "Reader supports pinpad PIN modification";
-						if (priv->gpriv->enable_pinpad) {
-							sc_log(ctx, "%s", log_text);
-							reader->capabilities |= SC_READER_CAP_PIN_PAD;
-						} else {
-							sc_log(ctx, "%s %s", log_text, log_disabled);
-						}
-					}
-
-					if (display_ioctl)
-					{
-						rcount = sizeof(rbuf);
-						rv = gpriv->SCardControl(card_handle, display_ioctl, NULL, 0, rbuf, sizeof(rbuf), &rcount);
-						if (rv == SCARD_S_SUCCESS)
-						{
-							if (rcount == sizeof(PIN_PROPERTIES_STRUCTURE))
-							{
-								PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)rbuf;
-								if (caps->wLcdLayout > 0)
-								{
-									sc_log(ctx, "Reader has a display: %04X", caps->wLcdLayout);
-									reader->capabilities |= SC_READER_CAP_DISPLAY;
-								}
-								else
-									sc_log(ctx, "Reader does not have a display.");
-							}
-							else
-							{
-								sc_log(ctx,
-								       "Returned PIN properties structure has bad length (%lu/%"SC_FORMAT_LEN_SIZE_T"u)",
-								       (unsigned long)rcount,
-								       sizeof(PIN_PROPERTIES_STRUCTURE));
-							}
-						}
-					}
-
-					if (priv->pace_ioctl) {
-						char *log_text = "Reader supports PACE";
-						if (priv->gpriv->enable_pace) {
-							sc_log(ctx, "%s", log_text);
-							reader->capabilities |= SC_READER_CAP_PACE_GENERIC;
-						} else {
-							sc_log(ctx, "%s %s", log_text, log_disabled);
-						}
-					}
-				}
-			}
-		}
-
-
-		/* TODO should check return codes */
-		refresh_attributes(reader);
-
-		ret = SC_SUCCESS;
-
-		goto out;
-
-	err1:
-		if (priv != NULL) {
-			free(priv);
-		}
-		if (reader != NULL) {
-			if (reader->name)
-				free(reader->name);
-			if (reader->vendor)
-				free(reader->vendor);
-			free(reader);
+		ret = pcsc_add_reader(ctx, reader_name, reader_name_size, &reader);
+		if (ret == SC_SUCCESS) {
+			struct pcsc_private_data *priv = reader->drv_data;
+			priv->pcsc_card = card_handle;
+			detect_protocol(reader, card_handle);
+			detect_reader_features(reader, card_handle);
+		} else {
+			_sc_delete_reader(ctx, reader);
 		}
 	}
 
 out:
-
-	SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, ret);
+	LOG_FUNC_RETURN(ctx, ret);
 }
 
-static int cardmod_release(sc_reader_t *reader)
-{
-	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
-
-	free(priv);
-	return SC_SUCCESS;
-}
-
-struct sc_reader_driver * sc_get_cardmod_driver(void)
+struct sc_reader_driver * sc_get_pcsc_driver(void)
 {
+	pcsc_ops.init = pcsc_init;
+	pcsc_ops.finish = pcsc_finish;
+	pcsc_ops.detect_readers = pcsc_detect_readers;
+	pcsc_ops.transmit = pcsc_transmit;
+	pcsc_ops.detect_card_presence = pcsc_detect_card_presence;
+	pcsc_ops.lock = pcsc_lock;
+	pcsc_ops.unlock = pcsc_unlock;
+	pcsc_ops.release = pcsc_release;
+	pcsc_ops.connect = pcsc_connect;
+	pcsc_ops.disconnect = pcsc_disconnect;
+	pcsc_ops.perform_verify = pcsc_pin_cmd;
+	pcsc_ops.wait_for_event = pcsc_wait_for_event;
+	pcsc_ops.cancel = pcsc_cancel;
+	pcsc_ops.reset = pcsc_reset;
+	pcsc_ops.use_reader = pcsc_use_reader;
+	pcsc_ops.perform_pace = pcsc_perform_pace;
 
-	struct sc_reader_driver *pcsc_drv = sc_get_pcsc_driver();
-
-	cardmod_ops = *(pcsc_drv->ops);
-
-	cardmod_ops.init = cardmod_init;
-	cardmod_ops.finish = cardmod_finish;
-	cardmod_ops.detect_readers = NULL;
-	/* cardmod_ops.transmit = ; */
-	cardmod_ops.lock = NULL;
-	cardmod_ops.unlock = NULL;
-	cardmod_ops.release = cardmod_release;
-	cardmod_ops.connect = cardmod_connect;
-	cardmod_ops.disconnect = cardmod_disconnect;
-	/* cardmod_ops.perform_verify = ; */
-	cardmod_ops.wait_for_event = NULL;
-	cardmod_ops.reset = NULL;
-	cardmod_ops.use_reader = cardmod_use_reader;
-	cardmod_ops.perform_pace = NULL;
-
-	return &cardmod_drv;
+	return &pcsc_drv;
 }
 
-#endif
-
 #endif   /* ENABLE_PCSC */
diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c
index 60af206..8d7af5a 100644
--- a/src/minidriver/minidriver.c
+++ b/src/minidriver/minidriver.c
@@ -5816,7 +5816,7 @@ static int associate_card(PCARD_DATA pCardData)
 	vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
 	/*
 	 * set the addresses of the reader and card handles
-	 * Our cardmod pcsc code will use these  when we call sc_ctx_use_reader
+	 * Our pcsc code will use these  when we call sc_ctx_use_reader
 	 * We use the address of the handles as provided in the pCardData
 	 */
 	vs->hSCardCtx = pCardData->hSCardCtx;
@@ -5834,7 +5834,7 @@ static int associate_card(PCARD_DATA pCardData)
 	}
 
 	/* set the provided reader and card handles into ctx */
-	logprintf(pCardData, 5, "cardmod_use_handles %d\n", sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard));
+	logprintf(pCardData, 5, "sc_ctx_use_reader %d\n", sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard));
 
 	/* should be only one reader */
 	logprintf(pCardData, 5, "sc_ctx_get_reader_count(ctx): %d\n", sc_ctx_get_reader_count(vs->ctx));

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git



More information about the pkg-opensc-commit mailing list