diff --git a/picc_to_pcsc/configure.ac b/picc_to_pcsc/configure.ac
index eb38e86..5c6d558 100644
--- a/picc_to_pcsc/configure.ac
+++ b/picc_to_pcsc/configure.ac
@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65])
-AC_INIT([picc_to_pcsc], [0.1], [http://sourceforge.net/projects/vsmartcard/support])
-AC_CONFIG_SRCDIR([src/picc_to_pcsc.c])
+AC_INIT([pcsc-relay], [0.2], [http://sourceforge.net/projects/vsmartcard/support])
+AC_CONFIG_SRCDIR([src/pcsc-relay.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
@@ -17,17 +17,27 @@ PKG_PROG_PKG_CONFIG
PKG_CHECK_EXISTS([libpcsclite],
[PKG_CHECK_MODULES([PCSC], [libpcsclite])],
[AC_MSG_WARN([libpcsclite not found by pkg-config])])
+# Checks for libraries.
+PKG_CHECK_EXISTS([libnfc >= 1.3.9],
+ [PKG_CHECK_MODULES([LIBNFC], [libnfc >= 1.3.9])],
+ [AC_MSG_WARN([libnfc >= 1.3.9 not found by pkg-config])])
+
saved_CPPFLAGS="$CPPFLAGS"
saved_LIBS="$LIBS"
-CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS"
-LIBS="$LDFLAGS $PCSC_LIBS"
+CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS $LIBNFC_CFLAGS"
+LIBS="$LDFLAGS $PCSC_LIBS $LIBNFC_LIBS"
AC_CHECK_HEADERS(winscard.h, [], [ AC_MSG_ERROR([winscard.h not found, install PC/SC Lite or similar or use ./configure PCSC_CFLAGS=...]) ])
AC_CHECK_HEADERS(reader.h, [AC_DEFINE(HAVE_READER_H, 1, [use reader.h from PC/SC Lite])], [])
AC_CHECK_HEADERS(pcsclite.h, [AC_DEFINE(HAVE_PCSCLITE_H, 1, [use pcsclite.h from PC/SC Lite])], [])
AC_MSG_CHECKING([for SCardEstablishContext])
AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ],
[ AC_MSG_ERROR([libpcsclite not found, use ./configure PCSC_LIBS=...]) ])
+AC_CHECK_HEADERS(nfc/nfc.h,,
+ [ AC_MSG_ERROR([nfc/nfc.h not found, install libnfc >= 1.3.9 or use ./configure LIBNFC_CFLAGS=...]) ])
+AC_MSG_CHECKING([for nfc_initiator_select_passive_target])
+AC_TRY_LINK_FUNC(nfc_initiator_select_passive_target, [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_ERROR([libnfc >= 1.3.9 not found, use ./configure LIBNFC_LIBS=...]) ])
CPPFLAGS="$saved_CPPFLAGS"
LIBS="$saved_LIBS"
@@ -51,7 +61,7 @@ AC_FUNC_MALLOC
cat << EOF
-picc_to_pcsc has been configured with following options:
+pcsc-relay has been configured with following options:
Version: ${PACKAGE_VERSION}
User binaries: $(eval eval eval echo "${bindir}")
@@ -67,6 +77,8 @@ Linker flags: ${LDFLAGS}
Libraries: ${LIBS}
PCSC_CFLAGS: ${PCSC_CFLAGS}
PCSC_LIBS: ${PCSC_LIBS}
+LIBNFC_CFLAGS: ${LIBNFC_CFLAGS}
+LIBNFC_LIBS: ${LIBNFC_LIBS}
EOF
diff --git a/picc_to_pcsc/src/Makefile.am b/picc_to_pcsc/src/Makefile.am
index 513c119..0e1b7d7 100644
--- a/picc_to_pcsc/src/Makefile.am
+++ b/picc_to_pcsc/src/Makefile.am
@@ -1,10 +1,10 @@
EXTRA_DIST = picc.py
-bin_PROGRAMS = picc_to_pcsc
+bin_PROGRAMS = pcsc-relay
bin_SCRIPTS = picc.py
-picc_to_pcsc_SOURCES = picc_to_pcsc.c pcscutil.c
-picc_to_pcsc_LDADD = $(PCSC_LIBS)
-picc_to_pcsc_CFLAGS = $(PCSC_CFLAGS)
+pcsc_relay_SOURCES = pcsc-relay.c pcscutil.c opicc.c
+pcsc_relay_LDADD = $(PCSC_LIBS)
+pcsc_relay_CFLAGS = $(PCSC_CFLAGS)
-noinst_HEADERS = pcscutil.h
+noinst_HEADERS = pcscutil.h pcsc-relay.h
diff --git a/picc_to_pcsc/src/opicc.c b/picc_to_pcsc/src/opicc.c
new file mode 100644
index 0000000..d13bb10
--- /dev/null
+++ b/picc_to_pcsc/src/opicc.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2010 Frank Morgner
+ *
+ * This file is part of ccid.
+ *
+ * ccid is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * ccid 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ccid. If not, see .
+ */
+#include
+#include
+
+#include "config.h"
+#include "pcsc-relay.h"
+
+struct picc_data {
+ char *read;
+ size_t readlen;
+ FILE *fd;
+};
+static size_t picc_encode_rapdu(const unsigned char *inbuf, size_t inlen, char **outbuf);
+static size_t picc_decode_apdu(const char *inbuf, size_t inlen, unsigned char **outbuf);
+
+
+size_t picc_encode_rapdu(const unsigned char *inbuf, size_t inlen, char **outbuf)
+{
+ char *p;
+ const unsigned char *next;
+ size_t length;
+
+ if (!inbuf || inlen > 0xffff || !outbuf)
+ goto err;
+
+ length = 5+inlen*3+1;
+ p = realloc(*outbuf, length);
+ if (!p) {
+ if (debug || verbose)
+ fprintf(stderr, "Error allocating memory for encoded R-APDU\n");
+ goto err;
+ }
+ *outbuf = p;
+
+ sprintf(*outbuf, "%04X:", inlen);
+
+ next = inbuf;
+ /* let p point behind ':' */
+ p += 5;
+ while (inbuf+inlen > next) {
+ sprintf(p," %02X",*next);
+ next++;
+ p += 3;
+ }
+
+ return length;
+
+err:
+ return 0;
+}
+
+size_t picc_decode_apdu(const char *inbuf, size_t inlen, unsigned char **outbuf)
+{
+ size_t pos, length;
+ unsigned char buf[0xffff];
+ char *end, *p;
+ unsigned long int b;
+
+ if (!outbuf || inbuf == NULL || inlen == 0 || inbuf[0] == '\0') {
+ /* Ignore invalid parameters, empty and 'RESET' lines */
+ goto noapdu;
+ }
+
+ length = strtoul(inbuf, &end, 16);
+
+ /* check for ':' right behind the length */
+ if (inbuf+inlen < end+1 || end[0] != ':')
+ goto noapdu;
+ end++;
+
+ p = realloc(*outbuf, length);
+ if (!p) {
+ if (debug || verbose)
+ fprintf(stderr, "Error allocating memory for decoded C-APDU\n");
+ goto noapdu;
+ }
+ *outbuf = p;
+
+ pos = 0;
+ while(inbuf+inlen > end && length > pos) {
+ b = strtoul(end, &end, 16);
+ if (b > 0xff) {
+ if (debug || verbose)
+ fprintf(stderr, "%s:%u Error decoding C-APDU\n", __FILE__, __LINE__);
+ goto noapdu;
+ }
+
+ (*outbuf)[pos++] = b;
+ }
+
+ return length;
+
+noapdu:
+ return 0;
+}
+
+
+static int picc_connect(void **driver_data)
+{
+ struct picc_data *p;
+
+ if (!driver_data)
+ return 0;
+
+ p = realloc(*driver_data, sizeof *p);
+ if (!p)
+ return 0;
+ *driver_data = p;
+
+ p->fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/
+ if (!p->fd) {
+ if (debug || verbose)
+ fprintf(stderr,"Error opening %s\n", PICCDEV);
+ return 0;
+ }
+ if (debug || verbose)
+ printf("Connected to %s\n", PICCDEV);
+
+ return 1;
+}
+
+static int picc_disconnect(void *driver_data)
+{
+ struct picc_data *data = driver_data;
+ if (data && data->fd)
+ fclose(data->fd);
+
+ return 1;
+}
+
+static int picc_receive_capdu(void *driver_data,
+ unsigned char **capdu, size_t *len)
+{
+ ssize_t linelen;
+ struct picc_data *data = driver_data;
+
+ if (!data || !capdu || !len)
+ return 0;
+
+
+ /* read C-APDU */
+ linelen = getline(&data->read, &data->readlen, data->fd);
+ if (linelen < 0) {
+ if (linelen < 0) {
+ if (debug || verbose)
+ fprintf(stderr,"Error reading from %s\n", PICCDEV);
+ return 0;
+ }
+ }
+ if (linelen == 0) {
+ *len = 0;
+ return 1;
+ }
+ fflush(data->fd);
+
+ if (debug)
+ printf("%s\n", data->read);
+
+
+ /* decode C-APDU */
+ *len = picc_decode_apdu(data->read, linelen, capdu);
+
+ return 1;
+}
+
+static int picc_send_rapdu(void *driver_data,
+ const unsigned char *rapdu, size_t len)
+{
+ char *buf = NULL;
+ size_t buflen;
+ struct picc_data *data = driver_data;
+
+ if (!data || !rapdu)
+ return 0;
+
+
+ /* encode R-APDU */
+ buflen = picc_encode_rapdu(rapdu, len, &buf);
+
+
+ /* write R-APDU */
+ if (debug)
+ printf("INF: Writing R-APDU\n\n%s\n\n", buf);
+
+ if (fprintf(data->fd,"%s\r\n", (char *) buf) < 0
+ || fflush(data->fd) != 0) {
+ free(buf);
+ return 0;
+ }
+
+ free(buf);
+
+ return 1;
+}
+
+
+struct rf_driver driver_openpicc = {
+ .data = NULL,
+ .connect = picc_connect,
+ .disconnect = picc_disconnect,
+ .receive_capdu = picc_receive_capdu,
+ .send_rapdu = picc_send_rapdu,
+};
diff --git a/picc_to_pcsc/src/picc_to_pcsc.c b/picc_to_pcsc/src/pcsc-relay.c
similarity index 56%
rename from picc_to_pcsc/src/picc_to_pcsc.c
rename to picc_to_pcsc/src/pcsc-relay.c
index 480c398..18bb401 100644
--- a/picc_to_pcsc/src/picc_to_pcsc.c
+++ b/picc_to_pcsc/src/pcsc-relay.c
@@ -30,21 +30,21 @@
#include
#include "config.h"
+#include "pcsc-relay.h"
#include "pcscutil.h"
-static FILE *picc_fd = NULL; /*filehandle used for PICCDEV*/
+struct rf_driver *driver = &driver_openpicc;
+
static LPSTR readers = NULL;
static SCARDCONTEXT hContext = 0;
static SCARDHANDLE hCard = 0;
-static int verbose = 0, debug = 0;
+int verbose = 0, debug = 0;
/* Forward declaration */
static void daemonize();
static void cleanup_exit(int signo);
static void cleanup(void);
-static size_t picc_decode_apdu(char *inbuf, size_t inlen, unsigned char **outbuf);
-static size_t picc_encode_rapdu(unsigned char *inbuf, size_t inlen, char **outbuf);
void daemonize() {
pid_t pid, sid;
@@ -86,91 +86,10 @@ void cleanup_exit(int signo){
}
void cleanup(void) {
- if (picc_fd)
- fclose(picc_fd);
+ driver->disconnect(driver->data);
pcsc_disconnect(hContext, hCard, readers);
}
-size_t picc_decode_apdu(char *inbuf, size_t inlen, unsigned char **outbuf)
-{
- size_t pos, length;
- unsigned char buf[0xffff];
- char *end, *p;
- unsigned long int b;
-
- if (!outbuf || inbuf == NULL || inlen == 0 || inbuf[0] == '\0') {
- /* Ignore invalid parameters, empty and 'RESET' lines */
- goto noapdu;
- }
-
- length = strtoul(inbuf, &end, 16);
-
- /* check for ':' right behind the length */
- if (inbuf+inlen < end+1 || end[0] != ':')
- goto noapdu;
- end++;
-
- p = realloc(*outbuf, length);
- if (!p) {
- if (debug || verbose)
- fprintf(stderr, "Error allocating memory for decoded C-APDU\n");
- goto noapdu;
- }
- *outbuf = p;
-
- pos = 0;
- while(inbuf+inlen > end && length > pos) {
- b = strtoul(end, &end, 16);
- if (b > 0xff) {
- if (debug || verbose)
- fprintf(stderr, "%s:%u Error decoding C-APDU\n", __FILE__, __LINE__);
- goto noapdu;
- }
-
- (*outbuf)[pos++] = b;
- }
-
- return length;
-
-noapdu:
- return 0;
-}
-
-size_t picc_encode_rapdu(unsigned char *inbuf, size_t inlen, char **outbuf)
-{
- char *p;
- unsigned char *next;
- size_t length;
-
- if (!inbuf || inlen > 0xffff || !outbuf)
- goto err;
-
- length = 5+inlen*3+1;
- p = realloc(*outbuf, length);
- if (!p) {
- if (debug || verbose)
- fprintf(stderr, "Error allocating memory for encoded R-APDU\n");
- goto err;
- }
- *outbuf = p;
-
- sprintf(*outbuf, "%04X:", inlen);
-
- next = inbuf;
- /* let p point behind ':' */
- p += 5;
- while (inbuf+inlen > next) {
- sprintf(p," %02X",*next);
- next++;
- p += 3;
- }
-
- return length;
-
-err:
- return 0;
-}
-
int main (int argc, char **argv)
{
/*printf("%s:%d\n", __FILE__, __LINE__);*/
@@ -185,7 +104,6 @@ int main (int argc, char **argv)
char *read = NULL;
size_t readlen = 0;
- ssize_t linelen;
unsigned int readernum = 0;
@@ -223,15 +141,7 @@ parse_err:
/* Open the device */
- picc_fd = fopen(PICCDEV, "a+"); /*O_NOCTTY ?*/
- if (!picc_fd) {
- if (debug || verbose)
- fprintf(stderr,"Error opening %s\n", PICCDEV);
- goto err;
- }
- if (debug || verbose)
- printf("Connected to %s\n", PICCDEV);
-
+ driver->connect(&driver->data);
/* connect to reader and card */
r = pcsc_connect(readernum, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY,
@@ -241,27 +151,7 @@ parse_err:
while(1) {
- /* read C-APDU */
- linelen = getline(&read, &readlen, picc_fd);
- if (linelen < 0) {
- if (linelen < 0) {
- if (debug || verbose)
- fprintf(stderr,"Error reading from %s\n", PICCDEV);
- goto err;
- }
- }
- if (linelen == 0)
- continue;
- fflush(picc_fd);
-
- if (debug)
- printf("%s\n", read);
-
-
- /* decode C-APDU */
- buflen = picc_decode_apdu(read, linelen, (unsigned char **) &buf);
- if (!buflen)
- continue;
+ driver->receive_capdu(driver->data, (unsigned char **) &buf, &buflen);
if (!verbose)
printb("C-APDU: ===================================================\n", buf, buflen);
@@ -277,16 +167,7 @@ parse_err:
printb("R-APDU:\n", outputBuffer, outputLength);
- /* encode R-APDU */
- buflen = picc_encode_rapdu(outputBuffer, outputLength, (char **) &buf);
-
-
- /* write R-APDU */
- if (debug)
- printf("INF: Writing R-APDU\n\n%s\n\n", (char *) buf);
-
- fprintf(picc_fd,"%s\r\n", (char *) buf);
- fflush(picc_fd);
+ driver->send_rapdu(driver->data, outputBuffer, outputLength);
}
err:
diff --git a/picc_to_pcsc/src/pcsc-relay.h b/picc_to_pcsc/src/pcsc-relay.h
new file mode 100644
index 0000000..8ffc7a4
--- /dev/null
+++ b/picc_to_pcsc/src/pcsc-relay.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Frank Morgner
+ *
+ * This file is part of ccid.
+ *
+ * ccid is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * ccid 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ccid. If not, see .
+ */
+/**
+ * @file
+ */
+#ifndef _PCSC_RELAY_H
+#define _PCSC_RELAY_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rf_driver {
+ void *data;
+ int (*connect) (void **driver_data);
+ int (*disconnect) (void *driver_data);
+ int (*receive_capdu) (void *driver_data,
+ unsigned char **capdu, size_t *len);
+ int (*send_rapdu) (void *driver_data,
+ const unsigned char *rapdu, size_t len);
+};
+
+extern int verbose, debug;
+
+extern struct rf_driver driver_openpicc;
+extern struct rf_driver driver_libnfc;
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif