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ä <[email protected]>
* Copyright (C) 2009,2010 Martin Paljak <[email protected]>
*
* 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
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel