On Wed, 2006-03-22 at 01:41 +0100, Josep Monés Teixidor wrote:

> I hope you like this second try.
> 

Hello,

Due to some cleanup before posting my first patch i overlooked that i
had changed SCARD_LEAVE_CARD to SCARD_RESET_CARD in SCardReconnect,
which would reset again card if driver detected that card had been reset
while in pcsc_lock.

I include a reset param to pcsc_reconnect in order to preserve behaviour
while reusing code.


-- 
Josep Monés
[EMAIL PROTECTED]
C3PO, S.L.
http://www.c3po.es
C/ Bertran, 113  -  08023 Barcelona
Tel. 93 417 99 55  -  Fax 93 253 12 80
Index: src/libopensc/card.c
===================================================================
--- src/libopensc/card.c	(revision 2875)
+++ src/libopensc/card.c	(working copy)
@@ -249,6 +249,29 @@
 	SC_FUNC_RETURN(ctx, 1, 0);
 }
 
+int sc_reset(sc_card_t *card)
+{
+	int r = SC_SUCCESS;
+	int r2 = SC_SUCCESS;
+
+	if (card == NULL)
+		return SC_ERROR_INVALID_ARGUMENTS;
+	
+	r = sc_mutex_lock(card->ctx, card->mutex);
+	if (r != SC_SUCCESS)
+		return r;	
+			
+	if(card->reader->ops->reset == NULL)
+		r = SC_ERROR_NOT_SUPPORTED;
+	else
+		r = card->reader->ops->reset(card->reader, card->slot);
+	
+	r2 = sc_mutex_unlock(card->ctx, card->mutex);
+
+	/* prefer reset error message to sc_mutex_unlock one */
+	return (r != SC_SUCCESS) ? r : r2;
+}
+
 int sc_lock(sc_card_t *card)
 {
 	int r = 0;
Index: src/libopensc/reader-pcsc.c
===================================================================
--- src/libopensc/reader-pcsc.c	(revision 2875)
+++ src/libopensc/reader-pcsc.c	(working copy)
@@ -93,6 +93,7 @@
 	SCARD_READERSTATE_A reader_state;
 	DWORD verify_ioctl;
 	DWORD modify_ioctl;
+	int locked;
 };
 
 static int pcsc_detect_card_presence(sc_reader_t *reader, sc_slot_info_t *slot);
@@ -452,7 +453,7 @@
 	}
 }
 
-static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot)
+static int pcsc_reconnect(sc_reader_t * reader, sc_slot_info_t * slot, int reset)
 {
 	DWORD active_proto, protocol;
 	LONG rv;
@@ -476,9 +477,12 @@
 		protocol = slot->active_protocol;
 	}
 
+	/* reconnect always unlocks transaction */
+	pslot->locked = 0;
+	
 	rv = SCardReconnect(pslot->pcsc_card,
 			    priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED, protocol,
-			    SCARD_LEAVE_CARD, &active_proto);
+			    reset ? SCARD_RESET_CARD : SCARD_LEAVE_CARD, &active_proto);
 	if (rv != SCARD_S_SUCCESS) {
 		PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
 		return pcsc_ret_to_error(rv);
@@ -524,6 +528,9 @@
 	slot->active_protocol = pcsc_proto_to_opensc(active_proto);
 	pslot->pcsc_card = card_handle;
 
+	/* after connect reader is not locked yet */
+	pslot->locked = 0;
+	
 	/* check for pinpad support */
 #ifdef PINPAD_ENABLED
 	sc_debug(reader->ctx, "Requesting reader features ... ");
@@ -586,7 +593,7 @@
 
 	if ((unsigned int)rv == SCARD_W_RESET_CARD) {
 		/* try to reconnect if the card was reset by some other application */
-		rv = pcsc_reconnect(reader, slot);
+		rv = pcsc_reconnect(reader, slot, 0);
 		if (rv != SCARD_S_SUCCESS) {
 			PCSC_ERROR(reader->ctx, "SCardReconnect failed", rv);
 			return pcsc_ret_to_error(rv);
@@ -600,6 +607,9 @@
 		PCSC_ERROR(reader->ctx, "SCardBeginTransaction failed", rv);
 		return pcsc_ret_to_error(rv);
 	}
+
+	pslot->locked = 1;
+	
 	return SC_SUCCESS;
 }
 
@@ -610,12 +620,16 @@
 	struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
 
 	assert(pslot != NULL);
+
 	rv = SCardEndTransaction(pslot->pcsc_card, priv->gpriv->transaction_reset ?
                            SCARD_RESET_CARD : SCARD_LEAVE_CARD);
 	if (rv != SCARD_S_SUCCESS) {
 		PCSC_ERROR(reader->ctx, "SCardEndTransaction failed", rv);
 		return pcsc_ret_to_error(rv);
 	}
+
+	pslot->locked = 0;
+	
 	return 0;
 }
 
@@ -635,6 +649,23 @@
 	return 0;
 }
 
+static int pcsc_reset(sc_reader_t *reader, sc_slot_info_t *slot)
+{
+	int r;
+	struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
+	int old_locked = pslot->locked;
+
+	r = pcsc_reconnect(reader, slot, 1);
+	if(r != SC_SUCCESS)
+		return r;
+
+	/* pcsc_reconnect unlocks card... try to lock it again if it was locked */
+	if(old_locked)
+		r = pcsc_lock(reader, slot);
+	
+	return r;
+}
+	
 static struct sc_reader_operations pcsc_ops;
 
 static struct sc_reader_driver pcsc_drv = {
@@ -784,6 +815,7 @@
 	pcsc_ops.disconnect = pcsc_disconnect;
 	pcsc_ops.perform_verify = pcsc_pin_cmd;
 	pcsc_ops.wait_for_event = pcsc_wait_for_event;
+	pcsc_ops.reset = pcsc_reset;
 
 	return &pcsc_drv;
 }
Index: src/libopensc/opensc.h
===================================================================
--- src/libopensc/opensc.h	(revision 2875)
+++ src/libopensc/opensc.h	(working copy)
@@ -394,6 +394,7 @@
 			      int *reader_index,
 			      unsigned int *event,
 			      int timeout);
+	int (*reset)(struct sc_reader *, struct sc_slot_info *);
 };
 
 /*
@@ -806,6 +807,14 @@
                       int *reader, unsigned int *event, int timeout);
 
 /**
+ * Resets the card.
+ * NOTE: only PC/SC backend implements this function at this moment.
+ * @param card The card to reset.
+ * @retval SC_SUCCESS on success
+ */
+int sc_reset(sc_card_t *card);
+
+/**
  * Locks the card against modification from other threads.
  * After the initial call to sc_lock, the card is protected from
  * access from other processes. The function may be called several times.
_______________________________________________
opensc-devel mailing list
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to