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

Reply via email to