diff --git a/pcsc-relay/src/Makefile.am b/pcsc-relay/src/Makefile.am
index 1adfc93..c749dbc 100644
--- a/pcsc-relay/src/Makefile.am
+++ b/pcsc-relay/src/Makefile.am
@@ -28,11 +28,11 @@ pcsc-relay.1:
bin_PROGRAMS = pcsc-relay
bin_SCRIPTS = picc.py
-pcsc_relay_SOURCES = pcsc-relay.c pcsc.c opicc.c lnfc.c $(BUILT_SOURCES)
+pcsc_relay_SOURCES = pcsc-relay.c pcsc.c vpcd.c vpcd-driver.c opicc.c lnfc.c $(BUILT_SOURCES)
pcsc_relay_LDADD = $(PCSC_LIBS) $(LIBNFC_LIBS)
pcsc_relay_CFLAGS = $(PCSC_CFLAGS) $(LIBNFC_CFLAGS)
-noinst_HEADERS = pcsc-relay.h
+noinst_HEADERS = pcsc-relay.h vpcd.h
pcsc-relay.c: $(BUILT_SOURCES)
diff --git a/pcsc-relay/src/pcsc-relay.c b/pcsc-relay/src/pcsc-relay.c
index d8c4e77..7fcabd2 100644
--- a/pcsc-relay/src/pcsc-relay.c
+++ b/pcsc-relay/src/pcsc-relay.c
@@ -158,6 +158,18 @@ int main (int argc, char **argv)
}
readernum = args_info.reader_arg;
+ switch (args_info.connector_arg) {
+ case connector_arg_vicc:
+ scdriver = &driver_vpcd;
+ break;
+ case connector_arg_pcsc:
+ scdriver = &driver_pcsc;
+ break;
+ default:
+ exit(2);
+ }
+ vpcdport = args_info.port_arg;
+
#if HAVE_SIGACTION
struct sigaction new_sig, old_sig;
diff --git a/pcsc-relay/src/pcsc-relay.ggo.in b/pcsc-relay/src/pcsc-relay.ggo.in
index a9b7a95..464edb0 100644
--- a/pcsc-relay/src/pcsc-relay.ggo.in
+++ b/pcsc-relay/src/pcsc-relay.ggo.in
@@ -1,15 +1,24 @@
purpose "Emulate a contact-less smart card"
description "Using an contact-less interface (currently OpenPICC or libnfc) @PACKAGE@ receives command APDUs which are forwared to an existing smart card via PC/SC. @PACKAGE@ sends the response APDU back to the contact-less interface."
-option "reader" r
- "Number of the PC/SC reader to use (-1 for autodetect)"
- int default="-1"
- optional
option "emulator" e
"Contact-less emulator backend"
values="libnfc","openpicc" default="libnfc"
enum
optional
+option "connector" c
+ "Smart card connector backend"
+ values="pcsc","vicc" default="pcsc"
+ enum
+ optional
+option "reader" r
+ "Number of the PC/SC reader to use (-1 for autodetect)"
+ int default="-1"
+ optional
+option "port" p
+ "Port to listen for virtual smart card"
+ int default="35963"
+ optional
option "foreground" f
"Stay in foreground"
flag off
diff --git a/pcsc-relay/src/pcsc-relay.h b/pcsc-relay/src/pcsc-relay.h
index fc8e39e..55172fa 100644
--- a/pcsc-relay/src/pcsc-relay.h
+++ b/pcsc-relay/src/pcsc-relay.h
@@ -55,6 +55,8 @@ struct sc_driver {
extern struct sc_driver driver_pcsc;
extern unsigned int readernum;
+extern struct sc_driver driver_vpcd;
+extern unsigned int vpcdport;
#define LEVEL_INFO 1
#define LEVEL_DEBUG 2
diff --git a/pcsc-relay/src/vpcd-driver.c b/pcsc-relay/src/vpcd-driver.c
new file mode 100644
index 0000000..360ba51
--- /dev/null
+++ b/pcsc-relay/src/vpcd-driver.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 Frank Morgner
+ *
+ * This file is part of pcsc-relay.
+ *
+ * pcsc-relay 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.
+ *
+ * pcsc-relay 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
+ * pcsc-relay. If not, see .
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcsc-relay.h"
+#include "vpcd.h"
+#include
+#include
+#include
+
+
+
+unsigned int vpcdport = VPCDPORT;
+
+
+static int vpcd_connect(driver_data_t **driver_data)
+{
+ int vicc_found = 0;
+
+
+ if (vicc_init(vpcdport) < 0) {
+ RELAY_ERROR("Could not initialize connection to virtual ICC\n");
+ return 0;
+ }
+ INFO("Waiting for virtual ICC on port %hu\n",
+ (unsigned short) vpcdport);
+
+
+ do {
+ switch (vicc_present()) {
+ case 0:
+ /* not present */
+ sleep(1);
+ break;
+ case 1:
+ vicc_found = 1;
+ break;
+ default:
+ RELAY_ERROR("Could not get ICC state\n");
+ return 0;
+ }
+ } while (!vicc_found);
+
+
+ if (vicc_poweron() < 0) {
+ RELAY_ERROR("could not powerup\n");
+ return 0;
+ }
+
+ INFO("Connected to virtual ICC\n");
+
+
+ return 1;
+}
+
+static int vpcd_disconnect(driver_data_t *driver_data)
+{
+ if (vicc_eject() != 0)
+ DEBUG("Could not eject virtual ICC\n");
+
+ if (vicc_exit() != 0) {
+ RELAY_ERROR("Could not close connection to virtual ICC\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int vpcd_transmit(driver_data_t *driver_data,
+ const unsigned char *send, size_t send_len,
+ unsigned char *recv, size_t *recv_len)
+{
+ char *rapdu;
+ int size = vicc_transmit(send_len, (char *) send, &rapdu);
+
+ if (size < 0) {
+ RELAY_ERROR("could not send apdu or receive rapdu\n");
+ *recv_len = 0;
+ return 0;
+ }
+
+ if (*recv_len < size) {
+ RELAY_ERROR("Not enough memory for rapdu\n");
+ *recv_len = 0;
+ free(rapdu);
+ return 0;
+ }
+
+ *recv_len = size;
+ memcpy(recv, rapdu, size);
+ free(rapdu);
+
+ return 1;
+}
+
+
+struct sc_driver driver_vpcd = {
+ .connect = vpcd_connect,
+ .disconnect = vpcd_disconnect,
+ .transmit = vpcd_transmit,
+};
diff --git a/pcsc-relay/src/vpcd.c b/pcsc-relay/src/vpcd.c
new file mode 120000
index 0000000..272ab7d
--- /dev/null
+++ b/pcsc-relay/src/vpcd.c
@@ -0,0 +1 @@
+../../virtualsmartcard/src/vpcd/vpcd.c
\ No newline at end of file
diff --git a/pcsc-relay/src/vpcd.h b/pcsc-relay/src/vpcd.h
new file mode 120000
index 0000000..1b50d33
--- /dev/null
+++ b/pcsc-relay/src/vpcd.h
@@ -0,0 +1 @@
+../../virtualsmartcard/src/vpcd/vpcd.h
\ No newline at end of file