On Fri, 2011-02-11 at 15:16 -0600, Douglas E. Engert wrote: > > On 2/11/2011 3:02 PM, Andre Zepezauer wrote: > > On Fri, 2011-02-11 at 22:25 +0200, Martin Paljak wrote: > >>>>>> Furthermore, any cardmod adjustments can be implemented and isolated > >>>>>> with ifdef-s, > >>>>> > >>>>> The only #ifdef ENABLED_CARDMOD left is in ctx, and that could easily be > >>>>> removed as it tests the app_name for "cardmod" (The cardmod/Makefile.am > >>>>> has one to compile or not.) That test for the app_name is needed today > >>>>> because of the way the readers are initialized, and the cardmod looks > >>>>> like a separate driver. This could change if the mods were merged better > >>>>> in reader-pcsc.c > >>>> > >>>> As you said above, "The cardmod modifications to > >>>> reader-pcsc for the most part turn off all these features, so they don't > >>>> get accidentally executed and cause problems.". > >>>> > >>>> > >>>> #ifdef-s in reader-pcsc.c are OK to assure those limitations. > >>>> But those ifdef-s only should exist in reader-pcsc.c, as the only reader > >>>> driver the minidriver will know about is the pcsc driver. And to make it > >>>> very sure, if the codebase is compiled to produce minidriver DLL, the > >>>> extra ifdef-s will guarantee that those restrictions are enforced > >>>> (actually it should be assured by the minidriver code that nothing gets > >>>> called that would "confuse" reader-pcsc.c) > >>>> > >>> > >>> I would still assume that the first thing a combined driver would do > >>> would be to set a "use_provided_readers" or "cardmod_mode" flag so > >>> "#ifdef"s are not used, but "if" statements are. > >>> > >>> This would allow the same build to be used for both cardmod and pkcs#11. > >> > >> If-s should suffice, I assume the same. Eventually #ifdef-s and a separate > >> compile could probably allow to reduce the overall binary dll size even > >> more. > > > > BTW: There was a _standalone_ reader-cardmod.c proposed on Monday. It > > uses the 'init' function to pass in the handles. Making 'init' a stub > > and using its body for the new 'use_reader' function should be enough to > > make it work with current trunk. > > Have you tried this? > > > > > The only thing that could be shared with the original reader-pcsc.c is > > 'transmit'. And even that could be re-written from scratch if closer > > coupling to the underlying platform is required.
See attachment for a more compact implementation of 'transmit'.
/* * reader-pcsc.c: Reader driver for PC/SC interface * * Copyright (C) 2002 Juha Yrjölä <juha.yrj...@iki.fi> * Copyright (C) 2009,2010 Martin Paljak <mar...@paljak.pri.ee> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include <assert.h> #include <stdlib.h> #include <string.h> #include "libopensc/internal.h" #include "libopensc/internal-winscard.h" #include "reader-cardmod.h" /* Logging */ #define PCSC_TRACE(reader, desc, rv) do { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s:" desc ": 0x%08lx\n", reader->name, rv); } while (0) #define PCSC_LOG(ctx, desc, rv) do { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, desc ": 0x%08lx\n", rv); } while (0) static unsigned int pcsc_proto_to_opensc(DWORD proto) { switch (proto) { case SCARD_PROTOCOL_T0: return SC_PROTO_T0; case SCARD_PROTOCOL_T1: return SC_PROTO_T1; case SCARD_PROTOCOL_RAW: return SC_PROTO_RAW; default: return 0; } } static int pcsc_transmit(sc_reader_t *reader, sc_apdu_t *apdu) { SCARD_IO_REQUEST sSendPci, sRecvPci; LONG rv; size_t ssize, rsize; u8 *sbuf = NULL, *rbuf = NULL; int r; struct pcsc_private_data *priv = (struct pcsc_private_data *) reader->ctx->reader_drv_data; /* prepare sbuf, ssize */ r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, pcsc_proto_to_opensc(priv->dwProtocol)); if (r != SC_SUCCESS) goto out; /* prepare rbuf, rsize */ rsize = apdu->le + 2; rbuf = malloc(rsize); if (rbuf == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto out; } /* don't know */ sSendPci.dwProtocol = priv->dwProtocol; sSendPci.cbPciLength = sizeof(sSendPci); rv = SCardTransmit(priv->hSCard, &sSendPci, sbuf, ssize, &sRecvPci, rbuf, (DWORD *) &rsize); if (rv != SCARD_S_SUCCESS) { PCSC_TRACE(reader, "SCardTransmit/Control failed", rv); switch (rv) { case SCARD_W_REMOVED_CARD: r = SC_ERROR_CARD_REMOVED; break; default: r = SC_ERROR_TRANSMIT_FAILED; break; } goto out; } r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize); out: if (sbuf != NULL) free(sbuf); if (rbuf != NULL) free(rbuf); if(r) fprintf(stderr, "transmit failed\n"); else fprintf(stderr, "transmit succeed\n"); return r; } static int pcsc_init(sc_context_t *ctx, void *priv_data) { struct pcsc_private_data *priv; sc_reader_t *reader; DWORD atr_len = SC_MAX_ATR_SIZE; DWORD name_len; DWORD dwState; size_t i; int r; if (ctx == NULL || priv_data == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } if (ctx->reader_drv_data != NULL) { return SC_ERROR_INVALID_DATA; /* Already initialised */ } priv = calloc(1, sizeof(struct pcsc_private_data)); if (priv == NULL) { return SC_ERROR_OUT_OF_MEMORY; } *priv = *((struct pcsc_private_data *) priv_data); ctx->reader_drv_data = priv; reader = calloc(1, sizeof(sc_reader_t)); if (reader == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto error; } name_len = 127; reader->name = malloc(sizeof(char) * (name_len + 1)); if (reader->name == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto error; } r = SCardStatus(priv->hSCard, reader->name, &name_len, &dwState, &priv->dwProtocol, reader->atr.value, &atr_len); if (r != SCARD_S_SUCCESS) { fprintf(stderr, "SCardStatus failed: %s\n", pcsc_stringify_error(r)); r = SC_ERROR_READER; goto error; } reader->name[name_len] = 0; reader->atr.len = atr_len; fprintf(stderr, "Current Reader Name : %s\n", reader->name); fprintf(stderr, "Current Reader State : 0x%lx\n", dwState); fprintf(stderr, "Current Reader Protocol : T%ld\n", priv->dwProtocol - 1); fprintf(stderr, "Current Reader ATR Size : %u\n", reader->atr.len); fprintf(stderr, "Current Reader ATR Value : "); for (i = 0; i < reader->atr.len; i++) { fprintf(stderr, "%02X ", reader->atr.value[i]); } fprintf(stderr, "\n"); reader->flags = SC_READER_CARD_PRESENT; reader->driver = ctx->reader_driver; reader->ops = reader->driver->ops; r = _sc_add_reader(ctx, reader); if (r != SC_SUCCESS) { fprintf(stderr, "_sc_add_reader failed\n"); goto error; } fprintf(stderr, "init succeed\n"); return SC_SUCCESS; error: if (reader != NULL) { if (reader->name != NULL) free(reader->name); free(reader); } free(ctx->reader_drv_data); ctx->reader_drv_data = NULL; fprintf(stderr, "init failed\n"); return r; } static int pcsc_finish(sc_context_t *ctx) { if (ctx->reader_drv_data != NULL) { free(ctx->reader_drv_data); ctx->reader_drv_data = NULL; } fprintf(stderr, "finish succeed\n"); return SC_SUCCESS; } static int pcsc_detect_card_presence(sc_reader_t *reader) { fprintf(stderr, "detect_card_presence succeed\n"); return SC_READER_CARD_PRESENT; } static int pcsc_connect(sc_reader_t *reader) { fprintf(stderr, "connect succeed\n"); return SC_SUCCESS; } static int pcsc_disconnect(sc_reader_t * reader) { fprintf(stderr, "disconnect succeed\n"); return SC_SUCCESS; } struct sc_reader_driver * get_reader_driver(void) { struct sc_reader_driver *pcsc_drv; pcsc_drv = calloc(1, sizeof(struct sc_reader_driver)); if (pcsc_drv == NULL) { return NULL; } pcsc_drv->ops = calloc(1, sizeof(struct sc_reader_operations)); if (pcsc_drv->ops == NULL) { free(pcsc_drv); return NULL; } pcsc_drv->name = "cardmod"; pcsc_drv->short_name = "cardmod"; pcsc_drv->ops->init = pcsc_init; pcsc_drv->ops->finish = pcsc_finish; pcsc_drv->ops->detect_card_presence = pcsc_detect_card_presence; pcsc_drv->ops->connect = pcsc_connect; pcsc_drv->ops->disconnect = pcsc_disconnect; pcsc_drv->ops->transmit = pcsc_transmit; return pcsc_drv; }
struct pcsc_private_data { SCARDCONTEXT hSCardCtx; SCARDHANDLE hSCard; DWORD dwProtocol; }; int my_pcsc_init(struct pcsc_private_data *priv); struct sc_reader_driver * get_reader_driver(void);
_______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel