$OpenBSD: patch-src_libopensc_card_c,v 1.1 2016/08/25 13:21:26 dcoppa Exp $

commit 1e82dbe5c79e431e4d1b333a91b329e0164a86c2
Author: Doug Engert <deengert@gmail.com>
Date:   Fri Jul 22 12:41:39 2016 -0500

libopensc: fix reopen SM after reader reconnect

After card reset detected, run SM open under new transaction

Before trying to reestablish SM session or onto code that may
need to use a transaction,  get the transaction that will be
used by the caller od sc_lock.

--- src/libopensc/card.c.orig	Fri Jun  3 11:19:51 2016
+++ src/libopensc/card.c	Thu Aug 25 14:49:54 2016
@@ -387,6 +387,7 @@ int sc_reset(sc_card_t *card, int do_cold_reset)
 int sc_lock(sc_card_t *card)
 {
 	int r = 0, r2 = 0;
+	int was_reset = 0;
 
 	if (card == NULL)
 		return SC_ERROR_INVALID_ARGUMENTS;
@@ -399,14 +400,12 @@ int sc_lock(sc_card_t *card)
 	if (card->lock_count == 0) {
 		if (card->reader->ops->lock != NULL) {
 			r = card->reader->ops->lock(card->reader);
-			if (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) {
+			while (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) {
 				/* invalidate cache */
 				memset(&card->cache, 0, sizeof(card->cache));
 				card->cache.valid = 0;
-#ifdef ENABLE_SM
-				if (card->sm_ctx.ops.open)
-					card->sm_ctx.ops.open(card);
-#endif
+				if (was_reset++ > 4) /* TODO retry a few times */
+					break;
 				r = card->reader->ops->lock(card->reader);
 			}
 		}
@@ -415,6 +414,14 @@ int sc_lock(sc_card_t *card)
 	}
 	if (r == 0)
 		card->lock_count++;
+
+	if (r == 0 && was_reset > 0) {
+#ifdef ENABLE_SM
+		if (card->sm_ctx.ops.open)
+			card->sm_ctx.ops.open(card);
+#endif
+	}
+
 	r2 = sc_mutex_unlock(card->ctx, card->mutex);
 	if (r2 != SC_SUCCESS) {
 		sc_log(card->ctx, "unable to release lock");
