Hello Nils,
On Tue, 2006-03-21 at 20:38 +0100, Nils Larsch wrote:
>
> SC_SUCCESS is better than 0
>
[....]
> if the reader doesn't support this operation this function MUST
> return a error like SC_ERROR_NOT_SUPPORTED (and of course applications
> using this features must be able to handle this return value).
>
Just for the record: this patch intended to mimic sc_lock and sc_unlock
functions, which use 0 and don't return SC_ERROR_NOT_SUPPORTED if
pointer is not initialized.
I include your suggestions in a second try.
> actually one should _never_ ignore return values ;-)
well... this actually was different than sc_lock and sc_unlock, because
these functions overwrite r if there has been an error because they
assign sc_unlock result to it (which looks like a bug to me).
I don't believe on such maximalisms, but if you really need
sc_mutex_unlock's error, then i think it's better to return reset error
if both fail (which will be more explanatory). Do you agree?
> It should be mentioned that this function is not always implemented
> (depending on the used reader driver used).
I hope someone who interfaces a reader using CT-API or OpenCT will be willing
to add this for those backends ;)
I've included a comment following your suggestion in the meanwhile.
I hope you like this second try.
Regards,
--
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);
@@ -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);
+ SCARD_RESET_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 ... ");
@@ -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);
+ 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