diff --git a/.gitignore b/.gitignore
index 97696dc..4f4cde0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,5 +6,7 @@
.depend
*.o
*.so
-hexStringTest
+*.dylib
+hexStringTest*
socketTest
+Testing*
diff --git a/de.persosim.driver.linux/Makefile b/de.persosim.driver.linux/Makefile
deleted file mode 100644
index fe47f2c..0000000
--- a/de.persosim.driver.linux/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-CC = cc
-CFLAGS = -g -std=gnu99 -fpic -Werror
-INCLUDE = -I. -I/usr/include/PCSC
-DEPENDFILE = .depend
-
-#LDFLAGS = -lm
-#LDLIBS = -lm
-
-
-OBJ := $(filter-out %test.o %Test.o, $(patsubst %.c,%.o,$(wildcard *.c)))
-LIBNAME := ifdhPersoSim.so
-PREFIX = /usr/local/pcsc
-
-DEFS = -DPCSC_DEBUG=1 #-DATR_DEBUG=1
-
-all: $(LIBNAME) tests
-
-# gennerate and pull in dependency info
-$(DEPENDFILE): *.c *.h
- $(CC) -MM $+ > $(DEPENDFILE)
--include $(DEPENDFILE)
-
-clean:
- rm -f *.o $(LIBNAME) $(DEPENDFILE) *Test
-
-install: $(LIBNAME)
- sudo cp reader.conf /etc/reader.conf.d/persoSim
- sudo cp $(LIBNAME) /usr/lib/pcsc/drivers/serial/
-
-uninstall:
- sudo rm -f /etc/reader.conf.d/persoSim
- sudo rm -f /usr/lib/pcsc/drivers/serial/$(LIBNAME)
-
-tests: hexStringTest
-
-runtests: tests
- ./hexStringTest
-
-%.so: $(OBJ)
- $(CC) $(CFLAGS) -shared $(OBJ) -o $@
-
-%.o : %.c
- $(CC) $(CFLAGS) -c $< $(INCLUDE) $(DEFS)
-
-% : %.c hexString.o
- #TODO remove the hardcoded dependecy above
- $(CC) $(CFLAGS) $^ -o $@ $(INCLUDE)
-
-.PHONY: clean test
-
diff --git a/de.persosim.driver.linux/README b/de.persosim.driver.linux/README
deleted file mode 100644
index bd797b7..0000000
--- a/de.persosim.driver.linux/README
+++ /dev/null
@@ -1,19 +0,0 @@
-PersoSim - Der Open Source Simulator für den elektronischen Personalausweis
-
-Stand: 12.01.2015
-
-
-*Systemvorraussetzungen*
-Bisher getestet unter Ubuntu 12.04 LTS
-Benötigt werden zusätzlich zur Standardinstallation die folgenden Pakete
-pcscd
-pcsc-tools
-libpcsclite-dev
-Diese können per "sudo apt-get install pcscd pcsc-tools libpcsclite-dev" installiert werden.
-
-
-
-*Installation*
-Das Linux-Treiberpaket liegt im Moment lediglich im Quellcode vor und kann mit der weit verbreiteten Kommandokombination "make && make install" kompiliert und installiert werden.
-
-Solange kein Simulator läuft, meldet der Treiber "Keine Karte im Leser". Sobald ein Simulator am konfigurierten Port verfügbar ist, ist dieser über den Treiber nutzbar.
diff --git a/de.persosim.driver.linux/reader.conf b/de.persosim.driver.linux/reader.conf
deleted file mode 100644
index fa91d96..0000000
--- a/de.persosim.driver.linux/reader.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-FRIENDLYNAME "PersoSimHandshake"
-DEVICENAME localhost:5678
-LIBPATH /usr/lib/pcsc/drivers/serial/ifdhPersoSim.so
-CHANNELID 0x8C7B
-
-FRIENDLYNAME "PersoSim1"
-DEVICENAME localhost:5678
-LIBPATH /usr/lib/pcsc/drivers/serial/ifdhPersoSim.so
-CHANNELID 0x8C7C
-
-FRIENDLYNAME "PersoSim2"
-DEVICENAME localhost:5678
-LIBPATH /usr/lib/pcsc/drivers/serial/ifdhPersoSim.so
-CHANNELID 0x8C7D
diff --git a/de.persosim.driver.linux/.cproject b/de.persosim.driver.unix/.cproject
similarity index 100%
rename from de.persosim.driver.linux/.cproject
rename to de.persosim.driver.unix/.cproject
diff --git a/de.persosim.driver.linux/.project b/de.persosim.driver.unix/.project
similarity index 100%
rename from de.persosim.driver.linux/.project
rename to de.persosim.driver.unix/.project
diff --git a/de.persosim.driver.unix/CMakeLists.txt b/de.persosim.driver.unix/CMakeLists.txt
new file mode 100644
index 0000000..e3c986d
--- /dev/null
+++ b/de.persosim.driver.unix/CMakeLists.txt
@@ -0,0 +1,62 @@
+cmake_minimum_required(VERSION 3.0)
+project("de.persosim.driver.unix" VERSION 0.8.0)
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ set(IS_LINUX TRUE)
+endif()
+
+if(!APPLE AND !IS_LINUX)
+ message(FATAL_ERROR "Currently only OS X and Linux platforms are supported")
+endif()
+
+
+if(IS_LINUX)
+ file(GLOB SRC_FILES *.c)
+elseif(APPLE)
+ file(GLOB SRC_FILES *.c MacOSX/*.c)
+endif()
+list(REMOVE_ITEM SRC_FILES ${PROJECT_SOURCE_DIR}/hexStringTest.c)
+
+
+# Build the library
+set(LIB_NAME ifdhPersoSim)
+set(CMAKE_C_FLAGS "-g -std=gnu99 -fpic")
+add_definitions(-DPCSC_DEBUG=1)
+#add_definitions(-DATR_DEBUG=1)
+if(IS_LINUX)
+ include_directories(${PROJECT_SOURCE_DIR} /usr/include/PCSC)
+elseif(APPLE)
+ include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/MacOSX)
+ add_definitions(-DUSE_SYSLOG -DRESPONSECODE_DEFINED_IN_WINTYPES_H)
+endif()
+add_library(${LIB_NAME} SHARED ${SRC_FILES})
+
+
+# Create the installation files
+if(IS_LINUX)
+ set(LIBPATH "/usr/lib/pcsc/drivers/serial/${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}")
+elseif(APPLE)
+ set(BUNDLEPATH "/usr/local/libexec/SmartCardServices/drivers/${LIB_NAME}.bundle")
+ set(LIBPATH ${BUNDLEPATH})
+ set(CFBUNDLEEXECUTABLE ${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
+ configure_file("${PROJECT_SOURCE_DIR}/MacOSX/Info.plist.in" "${PROJECT_BINARY_DIR}/Info.plist")
+endif()
+configure_file("${PROJECT_SOURCE_DIR}/reader.conf.in" "${PROJECT_BINARY_DIR}/reader.conf")
+
+
+# Specify installations files and locations
+if(IS_LINUX)
+ install(TARGETS ${LIB_NAME} DESTINATION "/usr/lib/pcsc/drivers/serial/")
+ install(FILES ${PROJECT_BINARY_DIR}/reader.conf DESTINATION "/etc/reader.conf.d/" RENAME "${LIB_NAME}.conf")
+elseif(APPLE)
+ install(FILES ${PROJECT_BINARY_DIR}/Info.plist DESTINATION "${BUNDLEPATH}/Contents")
+ install(TARGETS ${LIB_NAME} DESTINATION "${BUNDLEPATH}/Contents/MacOS")
+ install(FILES ${PROJECT_BINARY_DIR}/reader.conf DESTINATION "/etc/")
+endif()
+
+
+# Build the test (you may run the test by invoking make test)
+enable_testing()
+include(CTest)
+add_executable(hexStringTest hexStringTest.c hexString.c)
+add_test(NAME hexStringTest COMMAND ${CMAKE_BINARY_DIR}/hexStringTest)
diff --git a/de.persosim.driver.unix/MacOSX/.DS_Store b/de.persosim.driver.unix/MacOSX/.DS_Store
new file mode 100644
index 0000000..108a47e
Binary files /dev/null and b/de.persosim.driver.unix/MacOSX/.DS_Store differ
diff --git a/de.persosim.driver.unix/MacOSX/Info.plist.in b/de.persosim.driver.unix/MacOSX/Info.plist.in
new file mode 100644
index 0000000..aa82f01
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/Info.plist.in
@@ -0,0 +1,35 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ BNDL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ @PROJECT_VERSION@
+ ifdCapabilities
+ 0x00000000
+ ifdProtocolSupport
+ 0x00000001
+ ifdVersionNumber
+ 0x00000001
+
+ CFBundleExecutable
+ @CFBUNDLEEXECUTABLE@
+
+ ifdManufacturerString
+ Federal Office for Information Security, Germany
+
+ ifdProductString
+ Driver for virtual smart card reader PersoSim
+
+ ifdFriendlyName
+ PersoSim smart card reader
+
+
diff --git a/de.persosim.driver.unix/MacOSX/debug.c b/de.persosim.driver.unix/MacOSX/debug.c
new file mode 100644
index 0000000..1302b23
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/debug.c
@@ -0,0 +1,181 @@
+/*
+ debug.c: log (or not) messages
+ Copyright (C) 2003-2011 Ludovic Rousseau
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "misc.h"
+#include "debug.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef USE_SYSLOG
+#include
+#endif
+
+
+#undef LOG_TO_STDERR
+
+#ifdef LOG_TO_STDERR
+#define LOG_STREAM stderr
+#else
+#define LOG_STREAM stdout
+#endif
+
+void log_msg(const int priority, const char *fmt, ...)
+{
+ char debug_buffer[160]; /* up to 2 lines of 80 characters */
+ va_list argptr;
+ static struct timeval last_time = { 0, 0 };
+ struct timeval new_time = { 0, 0 };
+ struct timeval tmp;
+ int delta;
+#ifdef USE_SYSLOG
+ int syslog_level;
+
+ switch(priority)
+ {
+ case PCSC_LOG_CRITICAL:
+ syslog_level = LOG_CRIT;
+ break;
+ case PCSC_LOG_ERROR:
+ syslog_level = LOG_ERR;
+ break;
+ case PCSC_LOG_INFO:
+ syslog_level = LOG_INFO;
+ break;
+ default:
+ syslog_level = LOG_DEBUG;
+ }
+#else
+ const char *color_pfx = "", *color_sfx = "";
+ const char *time_pfx = "", *time_sfx = "";
+ static int initialized = 0;
+ static int LogDoColor = 0;
+
+ if (!initialized)
+ {
+ char *term;
+
+ initialized = 1;
+ term = getenv("TERM");
+ if (term)
+ {
+ const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
+ unsigned int i;
+
+ /* for each known color terminal */
+ for (i = 0; i < COUNT_OF(terms); i++)
+ {
+ /* we found a supported term? */
+ if (0 == strcmp(terms[i], term))
+ {
+ LogDoColor = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (LogDoColor)
+ {
+ color_sfx = "\33[0m";
+ time_sfx = color_sfx;
+ time_pfx = "\33[36m"; /* Cyan */
+
+ switch (priority)
+ {
+ case PCSC_LOG_CRITICAL:
+ color_pfx = "\33[01;31m"; /* bright + Red */
+ break;
+
+ case PCSC_LOG_ERROR:
+ color_pfx = "\33[35m"; /* Magenta */
+ break;
+
+ case PCSC_LOG_INFO:
+ color_pfx = "\33[34m"; /* Blue */
+ break;
+
+ case PCSC_LOG_DEBUG:
+ color_pfx = ""; /* normal (black) */
+ color_sfx = "";
+ break;
+ }
+ }
+#endif
+
+ gettimeofday(&new_time, NULL);
+ if (0 == last_time.tv_sec)
+ last_time = new_time;
+
+ tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
+ tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
+ if (tmp.tv_usec < 0)
+ {
+ tmp.tv_sec--;
+ tmp.tv_usec += 1000000;
+ }
+ if (tmp.tv_sec < 100)
+ delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
+ else
+ delta = 99999999;
+
+ last_time = new_time;
+
+ va_start(argptr, fmt);
+ (void)vsnprintf(debug_buffer, sizeof debug_buffer, fmt, argptr);
+ va_end(argptr);
+
+#ifdef USE_SYSLOG
+ syslog(syslog_level, "%.8d %s", delta, debug_buffer);
+#else
+ (void)fprintf(LOG_STREAM, "%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
+ color_pfx, debug_buffer, color_sfx);
+ fflush(LOG_STREAM);
+#endif
+} /* log_msg */
+
+void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
+ const int len)
+{
+ int i;
+ char *c, debug_buffer[len*3 + strlen(msg) +1];
+ size_t l;
+
+ (void)priority;
+
+ l = strlcpy(debug_buffer, msg, sizeof debug_buffer);
+ c = debug_buffer + l;
+
+ for (i = 0; i < len; ++i)
+ {
+ /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
+ (void)snprintf(c, 4, "%02X ", buffer[i]);
+ c += 3;
+ }
+
+#ifdef USE_SYSLOG
+ syslog(LOG_DEBUG, "%s", debug_buffer);
+#else
+ (void)fprintf(LOG_STREAM, "%s\n", debug_buffer);
+ fflush(LOG_STREAM);
+#endif
+} /* log_xxd */
diff --git a/de.persosim.driver.unix/MacOSX/debug.h b/de.persosim.driver.unix/MacOSX/debug.h
new file mode 100644
index 0000000..6508196
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/debug.h
@@ -0,0 +1,96 @@
+/*
+ debug.h: log (or not) messages using syslog
+ Copyright (C) 2003-2008 Ludovic Rousseau
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/*
+ * DEBUG_CRITICAL("text");
+ * log "text" if (LogLevel & DEBUG_LEVEL_CRITICAL) is TRUE
+ *
+ * DEBUG_CRITICAL2("text: %d", 1234);
+ * log "text: 1234" if (DEBUG_LEVEL_CRITICAL & DEBUG_LEVEL_CRITICAL) is TRUE
+ * the format string can be anything printf() can understand
+ *
+ * same thing for DEBUG_INFO, DEBUG_COMM and DEBUG_PERIODIC
+ *
+ * DEBUG_XXD(msg, buffer, size);
+ * log a dump of buffer if (LogLevel & DEBUG_LEVEL_COMM) is TRUE
+ *
+ */
+
+#ifndef _GCDEBUG_H_
+#define _GCDEBUG_H_
+
+/* You can't do #ifndef __FUNCTION__ */
+#if !defined(__GNUC__) && !defined(__IBMC__)
+#define __FUNCTION__ ""
+#endif
+
+extern int LogLevel;
+
+#define DEBUG_LEVEL_CRITICAL 1
+#define DEBUG_LEVEL_INFO 2
+#define DEBUG_LEVEL_COMM 4
+#define DEBUG_LEVEL_PERIODIC 8
+
+#include /* from pcsc-lite */
+
+/* DEBUG_CRITICAL */
+#define DEBUG_CRITICAL(fmt) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log1(PCSC_LOG_CRITICAL, fmt)
+
+#define DEBUG_CRITICAL2(fmt, data) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log2(PCSC_LOG_CRITICAL, fmt, data)
+
+#define DEBUG_CRITICAL3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log3(PCSC_LOG_CRITICAL, fmt, data1, data2)
+
+#define DEBUG_CRITICAL4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log4(PCSC_LOG_CRITICAL, fmt, data1, data2, data3)
+
+#define DEBUG_CRITICAL5(fmt, data1, data2, data3, data4) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log5(PCSC_LOG_CRITICAL, fmt, data1, data2, data3, data4)
+
+/* DEBUG_INFO */
+#define DEBUG_INFO1(fmt) if (LogLevel & DEBUG_LEVEL_INFO) Log1(PCSC_LOG_INFO, fmt)
+
+#define DEBUG_INFO2(fmt, data) if (LogLevel & DEBUG_LEVEL_INFO) Log2(PCSC_LOG_INFO, fmt, data)
+
+#define DEBUG_INFO3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_INFO) Log3(PCSC_LOG_INFO, fmt, data1, data2)
+
+#define DEBUG_INFO4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_INFO) Log4(PCSC_LOG_INFO, fmt, data1, data2, data3)
+
+#define DEBUG_INFO5(fmt, data1, data2, data3, data4) if (LogLevel & DEBUG_LEVEL_INFO) Log5(PCSC_LOG_INFO, fmt, data1, data2, data3, data4)
+
+#define DEBUG_INFO_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_INFO) LogXxd(PCSC_LOG_INFO, msg, buffer, size)
+
+/* DEBUG_PERIODIC */
+#define DEBUG_PERIODIC(fmt) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log1(PCSC_LOG_DEBUG, fmt)
+
+#define DEBUG_PERIODIC2(fmt, data) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log2(PCSC_LOG_DEBUG, fmt, data)
+
+#define DEBUG_PERIODIC3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log3(PCSC_LOG_DEBUG, fmt, data1, data2)
+
+/* DEBUG_COMM */
+#define DEBUG_COMM(fmt) if (LogLevel & DEBUG_LEVEL_COMM) Log1(PCSC_LOG_DEBUG, fmt)
+
+#define DEBUG_COMM2(fmt, data) if (LogLevel & DEBUG_LEVEL_COMM) Log2(PCSC_LOG_DEBUG, fmt, data)
+
+#define DEBUG_COMM3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_COMM) Log3(PCSC_LOG_DEBUG, fmt, data1, data2)
+
+#define DEBUG_COMM4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_COMM) Log4(PCSC_LOG_DEBUG, fmt, data1, data2, data3)
+
+/* DEBUG_XXD */
+#define DEBUG_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_COMM) LogXxd(PCSC_LOG_DEBUG, msg, buffer, size)
+
+#endif
+
diff --git a/de.persosim.driver.unix/MacOSX/debuglog.h b/de.persosim.driver.unix/MacOSX/debuglog.h
new file mode 100644
index 0000000..30c45fd
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/debuglog.h
@@ -0,0 +1,133 @@
+/*
+ * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
+ *
+ * Copyright (C) 1999-2004
+ * David Corcoran
+ * Copyright (C) 1999-2011
+ * Ludovic Rousseau
+ *
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief This handles debugging.
+ *
+ * @note log message is sent to syslog or stderr depending on --foreground
+ * command line argument
+ *
+ * @code
+ * Log1(priority, "text");
+ * log "text" with priority level priority
+ * Log2(priority, "text: %d", 1234);
+ * log "text: 1234"
+ * the format string can be anything printf() can understand
+ * Log3(priority, "text: %d %d", 1234, 5678);
+ * log "text: 1234 5678"
+ * the format string can be anything printf() can understand
+ * LogXxd(priority, msg, buffer, size);
+ * log "msg" + a hex dump of size bytes of buffer[]
+ * @endcode
+ */
+
+#ifndef __debuglog_h__
+#define __debuglog_h__
+
+#ifndef PCSC_API
+#define PCSC_API
+#endif
+
+enum {
+ DEBUGLOG_NO_DEBUG = 0,
+ DEBUGLOG_SYSLOG_DEBUG,
+ DEBUGLOG_STDOUT_DEBUG,
+ DEBUGLOG_STDOUT_COLOR_DEBUG
+};
+
+#define DEBUG_CATEGORY_NOTHING 0
+#define DEBUG_CATEGORY_APDU 1
+#define DEBUG_CATEGORY_SW 2
+
+enum {
+ PCSC_LOG_DEBUG = 0,
+ PCSC_LOG_INFO,
+ PCSC_LOG_ERROR,
+ PCSC_LOG_CRITICAL
+};
+
+/* You can't do #ifndef __FUNCTION__ */
+#if !defined(__GNUC__) && !defined(__IBMC__)
+#define __FUNCTION__ ""
+#endif
+
+#ifndef __GNUC__
+#define __attribute__(x) /*nothing*/
+#endif
+
+#ifdef NO_LOG
+
+#define Log0(priority) do { } while(0)
+#define Log1(priority, fmt) do { } while(0)
+#define Log2(priority, fmt, data) do { } while(0)
+#define Log3(priority, fmt, data1, data2) do { } while(0)
+#define Log4(priority, fmt, data1, data2, data3) do { } while(0)
+#define Log5(priority, fmt, data1, data2, data3, data4) do { } while(0)
+#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) do { } while(0)
+#define LogXxd(priority, msg, buffer, size) do { } while(0)
+
+#define DebugLogA(a)
+#define DebugLogB(a, b)
+#define DebugLogC(a, b,c)
+
+#else
+
+#define Log0(priority) log_msg(priority, "%s:%d:%s()", __FILE__, __LINE__, __FUNCTION__)
+#define Log1(priority, fmt) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__)
+#define Log2(priority, fmt, data) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data)
+#define Log3(priority, fmt, data1, data2) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2)
+#define Log4(priority, fmt, data1, data2, data3) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3)
+#define Log5(priority, fmt, data1, data2, data3, data4) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4)
+#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4, data5, data6, data7, data8)
+#define LogXxd(priority, msg, buffer, size) log_xxd(priority, msg, buffer, size)
+
+#define DebugLogA(a) Log1(PCSC_LOG_INFO, a)
+#define DebugLogB(a, b) Log2(PCSC_LOG_INFO, a, b)
+#define DebugLogC(a, b,c) Log3(PCSC_LOG_INFO, a, b, c)
+
+#endif /* NO_LOG */
+
+PCSC_API void log_msg(const int priority, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+
+PCSC_API void log_xxd(const int priority, const char *msg,
+ const unsigned char *buffer, const int size);
+
+void DebugLogSuppress(const int);
+void DebugLogSetLogType(const int);
+int DebugLogSetCategory(const int);
+void DebugLogCategory(const int, const unsigned char *, const int);
+PCSC_API void DebugLogSetLevel(const int level);
+
+#endif /* __debuglog_h__ */
+
diff --git a/de.persosim.driver.unix/MacOSX/ifdhandler.h b/de.persosim.driver.unix/MacOSX/ifdhandler.h
new file mode 100644
index 0000000..ffd31a0
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/ifdhandler.h
@@ -0,0 +1,820 @@
+/*
+ * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
+ *
+ * Copyright (C) 1999-2004
+ * David Corcoran
+ * Copyright (C) 2003-2004
+ * Damien Sauveron
+ * Copyright (C) 2002-2011
+ * Ludovic Rousseau
+ *
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @defgroup IFDHandler IFDHandler
+ * @brief This provides reader specific low-level calls.
+
+The routines specified hereafter will allow you to write an IFD handler
+for the PC/SC Lite resource manager. Please use the complement
+developer's kit complete with headers and Makefile at:
+http://www.musclecard.com/drivers.html
+
+This gives a common API for communication to most readers in a
+homogeneous fashion. This document assumes that the driver developer is
+experienced with standards such as ISO-7816-(1, 2, 3, 4), EMV and MCT
+specifications. For listings of these specifications please access the
+above web site.
+
+@section UsbReaders USB readers
+
+USB readers use the bundle approach so that the reader can be loaded
+and unloaded upon automatic detection of the device. The bundle
+approach is simple: the actual library is just embedded in a
+directory so additional information can be gathered about the device.
+
+A bundle looks like the following:
+
+@verbatim
+GenericReader.bundle/
+ Contents/
+ Info.plist - XML file describing the reader
+ MacOS/ - Driver directory for OS X
+ Solaris/ - Driver directory for Solaris
+ Linux/ - Driver directory for Linux
+ HPUX/ - Driver directory for HPUX
+@endverbatim
+
+The @c Info.plist file describes the driver and gives the loader
+all the necessary information. The following must be contained in the
+@c Info.plist file:
+
+@subsection ifdVendorID
+
+The vendor ID of the USB device.
+
+Example:
+
+@verbatim
+ ifdVendorID
+ 0x04E6
+@endverbatim
+
+You may have an OEM of this reader in which an additional @c
+can be used like in the below example:
+
+@verbatim
+ ifdVendorID
+
+ 0x04E6
+ 0x0973
+
+@endverbatim
+
+If multiples exist all the other parameters must have a second value
+also. You may chose not to support this feature but it is useful when
+reader vendors OEM products so you only distribute one driver.
+
+
+The CCID driver from Ludovic Rousseau
+http://pcsclite.alioth.debian.org/ccid.html uses this feature since the
+same driver supports many different readers.
+
+@subsection ifdProductID
+
+ The product id of the USB device.
+
+@verbatim
+ ifdProductID
+ 0x3437
+@endverbatim
+
+@subsection ifdFriendlyName
+
+ Example:
+
+@verbatim
+ ifdFriendlyName
+ SCM Microsystems USB Reader
+@endverbatim
+
+The reader name must use the ASCII character set.
+
+@subsection CFBundleExecutable
+
+ The executable name which exists in the particular platform's directory.
+
+ Example:
+
+@verbatim
+ CFBundleExecutable
+ libccid.so.0.4.2
+@endverbatim
+
+@subsection ifdCapabilities
+
+ List of capabilities supported by the driver. This is a bit field. Possible values are:
+
+- 0
+ No special capabilities
+- 1 IFD_GENERATE_HOTPLUG
+ The driver supports the hot plug feature.
+
+Complete sample file:
+
+@verbatim
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ BNDL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 0.0.1d1
+ ifdCapabilities
+ 0x00000000
+ ifdProtocolSupport
+ 0x00000001
+ ifdVersionNumber
+ 0x00000001
+
+ CFBundleExecutable
+ libfoobar.so.x.y
+
+ ifdManufacturerString
+ Foo bar inc.
+
+ ifdProductString
+ Driver for Foobar reader, version x.y
+
+ ifdVendorID
+ 0x1234
+
+ ifdProductID
+ 0x5678
+
+ ifdFriendlyName
+ Foobar USB reader
+
+
+@endverbatim
+
+As indicated in the XML file the DTD is available at
+http://www.apple.com/DTDs/PropertyList-1.0.dtd.
+
+@section SerialReaders Serial readers
+
+Serial drivers must be configured to operate on a particular port and
+respond to a particular name. The @c reader.conf file is used for this
+purpose.
+
+It has the following syntax:
+
+@verbatim
+# Configuration file for pcsc-lite
+# David Corcoran
+
+FRIENDLYNAME Generic Reader
+DEVICENAME /dev/ttyS0
+LIBPATH /usr/lib/pcsc/drivers/libgen_ifd.so
+CHANNELID 1
+@endverbatim
+
+The pound sign # denotes a comment.
+
+@subsection FRIENDLYNAME
+The FRIENDLYNAME field is an arbitrary text used to identify the reader.
+This text is displayed by commands like @c pcsc_scan
+http://ludovic.rousseau.free.fr/softwares/pcsc-tools/ that prints the
+names of all the connected and detected readers.
+
+@subsection DEVICENAME
+The DEVICENAME field was not used for old drivers (using the IFD handler
+version 2.0 or previous). It is now (IFD handler version 3.0) used to
+identify the physical port on which the reader is connected. This is
+the device name of this port. It is dependent of the OS kernel. For
+example the first serial port device is called @c /dev/ttyS0 under Linux
+and @c /dev/cuaa0 under FreeBSD.
+
+If you want to use IFDHCreateChannel() instead of
+IFDHCreateChannelByName() then do not use any DEVICENAME line in the
+configuration file. IFDHCreateChannel() will then be called with the
+CHANNELID parameter.
+
+@subsection LIBPATH
+The LIBPATH field is the filename of the driver code. The driver is a
+dynamically loaded piece of code (generally a @c drivername.so* file).
+
+@subsection CHANNELID
+The CHANNELID is no more used for recent drivers (IFD handler 3.0) and
+has been superseded by DEVICENAME.
+
+If you have an old driver this field is used to indicate the port to
+use. You should read your driver documentation to know what information
+is needed here. It should be the serial port number for a serial reader.
+
+CHANNELID was the numeric version of the port in which the reader will
+be located. This may be done by a symbolic link where @c /dev/pcsc/1 is
+the first device which may be a symbolic link to @c /dev/ttyS0 or
+whichever location your reader resides.
+
+ */
+
+#ifndef _ifd_handler_h_
+#define _ifd_handler_h_
+
+#include
+
+ /*
+ * List of data structures available to ifdhandler
+ */
+ typedef struct _DEVICE_CAPABILITIES
+ {
+ LPSTR Vendor_Name; /**< Tag 0x0100 */
+ LPSTR IFD_Type; /**< Tag 0x0101 */
+ DWORD IFD_Version; /**< Tag 0x0102 */
+ LPSTR IFD_Serial; /**< Tag 0x0103 */
+ DWORD IFD_Channel_ID; /**< Tag 0x0110 */
+
+ DWORD Asynch_Supported; /**< Tag 0x0120 */
+ DWORD Default_Clock; /**< Tag 0x0121 */
+ DWORD Max_Clock; /**< Tag 0x0122 */
+ DWORD Default_Data_Rate; /**< Tag 0x0123 */
+ DWORD Max_Data_Rate; /**< Tag 0x0124 */
+ DWORD Max_IFSD; /**< Tag 0x0125 */
+ DWORD Synch_Supported; /**< Tag 0x0126 */
+ DWORD Power_Mgmt; /**< Tag 0x0131 */
+ DWORD Card_Auth_Devices; /**< Tag 0x0140 */
+ DWORD User_Auth_Device; /**< Tag 0x0142 */
+ DWORD Mechanics_Supported; /**< Tag 0x0150 */
+ DWORD Vendor_Features; /**< Tag 0x0180 - 0x01F0 User Defined. */
+ }
+ DEVICE_CAPABILITIES, *PDEVICE_CAPABILITIES;
+
+ typedef struct _ICC_STATE
+ {
+ UCHAR ICC_Presence; /**< Tag 0x0300 */
+ UCHAR ICC_Interface_Status; /**< Tag 0x0301 */
+ UCHAR ATR[MAX_ATR_SIZE]; /**< Tag 0x0303 */
+ UCHAR ICC_Type; /**< Tag 0x0304 */
+ }
+ ICC_STATE, *PICC_STATE;
+
+ typedef struct _PROTOCOL_OPTIONS
+ {
+ DWORD Protocol_Type; /**< Tag 0x0201 */
+ DWORD Current_Clock; /**< Tag 0x0202 */
+ DWORD Current_F; /**< Tag 0x0203 */
+ DWORD Current_D; /**< Tag 0x0204 */
+ DWORD Current_N; /**< Tag 0x0205 */
+ DWORD Current_W; /**< Tag 0x0206 */
+ DWORD Current_IFSC; /**< Tag 0x0207 */
+ DWORD Current_IFSD; /**< Tag 0x0208 */
+ DWORD Current_BWT; /**< Tag 0x0209 */
+ DWORD Current_CWT; /**< Tag 0x020A */
+ DWORD Current_EBC; /**< Tag 0x020B */
+ }
+ PROTOCOL_OPTIONS, *PPROTOCOL_OPTIONS;
+
+ /**
+ * Use by SCardTransmit()
+ */
+ typedef struct _SCARD_IO_HEADER
+ {
+ DWORD Protocol;
+ DWORD Length;
+ }
+ SCARD_IO_HEADER, *PSCARD_IO_HEADER;
+
+ /*
+ * The list of tags should be alot more but this is all I use in the
+ * meantime
+ */
+#define TAG_IFD_ATR 0x0303 /**< ATR */
+#define TAG_IFD_SLOTNUM 0x0180 /**< select a slot */
+#define TAG_IFD_SLOT_THREAD_SAFE 0x0FAC /**< support access to different slots of the reader */
+#define TAG_IFD_THREAD_SAFE 0x0FAD /**< driver is thread safe */
+#define TAG_IFD_SLOTS_NUMBER 0x0FAE /**< number of slots of the reader */
+#define TAG_IFD_SIMULTANEOUS_ACCESS 0x0FAF /**< number of reader the driver can manage */
+#define TAG_IFD_POLLING_THREAD 0x0FB0 /**< not used. See TAG_IFD_POLLING_THREAD_WITH_TIMEOUT */
+#define TAG_IFD_POLLING_THREAD_KILLABLE 0x0FB1 /**< the polling thread can be killed */
+#define TAG_IFD_STOP_POLLING_THREAD 0x0FB2 /**< method used to stop the polling thread (instead of just pthread_kill()) */
+#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT 0x0FB3 /**< driver uses a polling thread with a timeout parameter */
+
+ /*
+ * IFD Handler version number enummerations
+ */
+#define IFD_HVERSION_1_0 0x00010000
+#define IFD_HVERSION_2_0 0x00020000
+#define IFD_HVERSION_3_0 0x00030000
+
+ /*
+ * List of defines available to ifdhandler
+ */
+#define IFD_POWER_UP 500 /**< power up the card */
+#define IFD_POWER_DOWN 501 /**< power down the card */
+#define IFD_RESET 502 /**< warm reset */
+
+#define IFD_NEGOTIATE_PTS1 1 /**< negotiate PTS1 */
+#define IFD_NEGOTIATE_PTS2 2 /**< negotiate PTS2 */
+#define IFD_NEGOTIATE_PTS3 4 /**< negotiate PTS3 */
+
+#define IFD_SUCCESS 0 /**< no error */
+#define IFD_ERROR_TAG 600 /**< tag unknown */
+#define IFD_ERROR_SET_FAILURE 601 /**< set failed */
+#define IFD_ERROR_VALUE_READ_ONLY 602 /**< value is read only */
+#define IFD_ERROR_PTS_FAILURE 605 /**< failed to negotiate PTS */
+#define IFD_ERROR_NOT_SUPPORTED 606
+#define IFD_PROTOCOL_NOT_SUPPORTED 607 /**< requested protocol not supported */
+#define IFD_ERROR_POWER_ACTION 608 /**< power up failed */
+#define IFD_ERROR_SWALLOW 609
+#define IFD_ERROR_EJECT 610
+#define IFD_ERROR_CONFISCATE 611
+#define IFD_COMMUNICATION_ERROR 612 /**< generic error */
+#define IFD_RESPONSE_TIMEOUT 613 /**< timeout */
+#define IFD_NOT_SUPPORTED 614 /**< request is not supported */
+#define IFD_ICC_PRESENT 615 /**< card is present */
+#define IFD_ICC_NOT_PRESENT 616 /**< card is absent */
+/**
+ * The \ref IFD_NO_SUCH_DEVICE error must be returned by the driver when
+ * it detects the reader is no more present. This will tell pcscd to
+ * remove the reader from the list of available readers.
+ */
+#define IFD_NO_SUCH_DEVICE 617
+#define IFD_ERROR_INSUFFICIENT_BUFFER 618 /**< buffer is too small */
+
+#ifndef RESPONSECODE_DEFINED_IN_WINTYPES_H
+ typedef long RESPONSECODE;
+#endif
+
+ /*
+ * If you want to compile a V2.0 IFDHandler, define IFDHANDLERv2
+ * before you include this file.
+ *
+ * By default it is setup for for most recent version of the API (V3.0)
+ */
+
+#ifndef IFDHANDLERv2
+
+ /*
+ * List of Defined Functions Available to IFD_Handler 3.0
+ *
+ * All the functions of IFD_Handler 2.0 are available
+ * IFDHCreateChannelByName() is new
+ * IFDHControl() API changed
+ */
+
+/**
+This function is required to open a communications channel to the port
+listed by @p DeviceName.
+
+Once the channel is opened the reader must be in a state in which it is
+possible to query IFDHICCPresence() for card status.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number\n
+ Use this for multiple card slots or multiple readers. 0xXXXXYYYY -
+ XXXX multiple readers, YYYY multiple slots. The resource manager will
+ set these automatically. By default the resource manager loads a new
+ instance of the driver so if your reader does not have more than one
+ smart card slot then ignore the Lun in all the functions.\n
+ \n
+ PC/SC supports the loading of multiple readers through one instance of
+ the driver in which XXXX is important. XXXX identifies the unique
+ reader in which the driver communicates to. The driver should set up
+ an array of structures that asociate this XXXX with the underlying
+ details of the particular reader.
+
+@param[in] DeviceName Filename to use by the driver.\n
+ For drivers configured by @p /etc/reader.conf this is the value of the
+ field \ref DEVICENAME.
+ \n
+ For USB drivers the @p DeviceName must start with @p usb:VID/PID. VID
+ is the Vendor ID and PID is the Product ID. Both are a 4-digits hex
+ number.
+
+Typically the string is generated by:
+
+@code
+printf("usb:%04x/%04x", idVendor, idProduct);
+@endcode
+
+The @p DeviceName string may also contain a more specialised
+identification string. This additional information is used to
+differentiate between two identical readers connected at the same time.
+In this case the driver can't differentiate the two readers using VID
+and PID and must use some additional information identifying the USB
+port used by each reader.
+
+- libusb
+
+ For USB drivers using libusb-1.0 http://libusb.sourceforge.net/ for USB
+ abstraction the @p DeviceName the string may be generated by:
+
+ @code
+ printf("usb:%04x/%04x:libusb-1.0:%d:%d:%d",
+ idVendor, idProduct, bus_number, device_address, interface)
+ @endcode
+
+ So it is something like: usb:08e6/3437:libusb-1.0:7:99:0 under
+ GNU/Linux.
+
+- libudev
+
+ If pcscd is compiled with libudev support instead of libusb (default
+ since pcsc-lite 1.6.8) the string will look like:
+
+ @code
+ printf("usb:%04x/%04x:libudev:%d:%s", idVendor, idProduct,
+ bInterfaceNumber, devpath);
+ @endcode
+
+ bInterfaceNumber is the number of the interface on the device. It is
+ only usefull for devices with more than one CCID interface.
+
+ devpath is the filename of the device on the file system.
+
+ So it is something like:
+ usb:08e6/3437:libudev:0:/dev/bus/usb/008/047
+ under GNU/Linux.
+
+- other
+
+ If the driver does not understand the :libusb: or
+ :libudev: scheme or if a new scheme is used, the driver should
+ ignore the part it does not understand instead of failing.
+
+ The driver shall recognize the usb:VID/PID part and, only if
+ possible, the remaining of the DeviceName field.
+
+ It is the responsibility of the driver to correctly identify the reader.
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR DeviceName);
+
+/**
+This function performs a data exchange with the reader (not the card)
+specified by Lun. It is responsible for abstracting functionality such
+as PIN pads, biometrics, LCD panels, etc. You should follow the MCT and
+CTBCS specifications for a list of accepted commands to implement. This
+function is fully voluntary and does not have to be implemented unless
+you want extended functionality.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+@param[in] dwControlCode Control code for the operation\n
+ This value identifies the specific operation to be performed. This
+ value is driver specific.
+@param[in] TxBuffer Transmit data
+@param[in] TxLength Length of this buffer
+@param[out] RxBuffer Receive data
+@param[in] RxLength Length of the response buffer
+@param[out] pdwBytesReturned Length of response\n
+ This function will be passed the length of the buffer RxBuffer in
+ RxLength and it must set the length of the received data in
+ pdwBytesReturned.
+
+@note
+ @p *pdwBytesReturned should be set to zero on error.
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR
+ TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
+ LPDWORD pdwBytesReturned);
+
+#else
+
+/**
+ * Available in IFD_Handler 2.0
+ *
+ * @deprecated
+ * You should use the new form of IFDHControl()
+ */
+RESPONSECODE IFDHControl(DWORD Lun, PUCHAR TxBuffer, DWORD TxLength,
+ PUCHAR RxBuffer, PDWORD RxLength);
+
+#endif
+
+ /*
+ * common functions in IFD_Handler 2.0 and 3.0
+ */
+/**
+This function is required to open a communications channel to the port
+listed by Channel. For example, the first serial reader on COM1 would
+link to @p /dev/pcsc/1 which would be a symbolic link to @p /dev/ttyS0
+on some machines This is used to help with inter-machine independence.
+
+On machines with no /dev directory the driver writer may choose to map
+their Channel to whatever they feel is appropriate.
+
+Once the channel is opened the reader must be in a state in which it is
+possible to query IFDHICCPresence() for card status.
+
+USB readers can ignore the @p Channel parameter and query the USB bus
+for the particular reader by manufacturer and product id.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number\n
+ Use this for multiple card slots or multiple readers. 0xXXXXYYYY -
+ XXXX multiple readers, YYYY multiple slots. The resource manager will
+ set these automatically. By default the resource manager loads a new
+ instance of the driver so if your reader does not have more than one
+ smart card slot then ignore the Lun in all the functions.\n
+ \n
+ PC/SC supports the loading of multiple readers through one instance of
+ the driver in which XXXX is important. XXXX identifies the unique
+ reader in which the driver communicates to. The driver should set up
+ an array of structures that associate this XXXX with the underlying
+ details of the particular reader.
+@param[in] Channel Channel ID
+ This is denoted by the following:
+ - 0x000001 @p /dev/pcsc/1
+ - 0x000002 @p /dev/pcsc/2
+ - 0x000003 @p /dev/pcsc/3
+ - 0x000004 @p /dev/pcsc/4
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+
+ */
+RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel);
+
+/**
+This function should close the reader communication channel for the
+particular reader. Prior to closing the communication channel the reader
+should make sure the card is powered down and the terminal is also
+powered down.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHCloseChannel(DWORD Lun);
+
+/**
+This function should get the slot/card capabilities for a particular
+slot/card specified by Lun. Again, if you have only 1 card slot and
+don't mind loading a new driver for each reader then ignore Lun.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+@param[in] Tag Tag of the desired data value
+- \ref TAG_IFD_ATR
+ Return the ATR and its size (implementation is mandatory).
+- \ref TAG_IFD_SLOTNUM
+ Unused/deprecated
+- \ref SCARD_ATTR_ATR_STRING
+ Same as \ref TAG_IFD_ATR but this one is not mandatory. It is defined
+ in Microsoft PC/SC SCardGetAttrib().
+- \ref TAG_IFD_SIMULTANEOUS_ACCESS
+ Return the number of sessions (readers) the driver can handle in
+ Value[0].
+ This is used for multiple readers sharing the same driver.
+- \ref TAG_IFD_THREAD_SAFE
+ If the driver supports more than one reader (see
+ \ref TAG_IFD_SIMULTANEOUS_ACCESS above) this tag indicates if the
+ driver supports access to multiple readers at the same time.\n
+ Value[0] = 1 indicates the driver supports simultaneous accesses.
+- \ref TAG_IFD_SLOTS_NUMBER
+ Return the number of slots in this reader in Value[0].
+- \ref TAG_IFD_SLOT_THREAD_SAFE
+ If the reader has more than one slot (see \ref TAG_IFD_SLOTS_NUMBER
+ above) this tag indicates if the driver supports access to multiple
+ slots of the same reader at the same time.\n
+ Value[0] = 1 indicates the driver supports simultaneous slot
+ accesses.
+- \ref TAG_IFD_POLLING_THREAD
+ Unused/deprecated
+- \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT
+ If the driver provides a polling thread then @p Value is a pointer to
+ this function. The function prototype is:
+@verbatim
+ RESPONSECODE foo(DWORD Lun, int timeout);
+@endverbatim
+- \ref TAG_IFD_POLLING_THREAD_KILLABLE
+ Tell if the polling thread can be killed (pthread_kill()) by pcscd
+- \ref TAG_IFD_STOP_POLLING_THREAD
+ Returns a pointer in @p Value to the function used to stop the polling
+ thread returned by \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT. The
+ function prototype is:
+@verbatim
+ RESPONSECODE foo(DWORD Lun);
+@endverbatim
+@param[in,out] Length Length of the desired data value
+@param[out] Value Value of the desired data
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag, PDWORD Length,
+ PUCHAR Value);
+
+/**
+This function should set the slot/card capabilities for a particular
+slot/card specified by @p Lun. Again, if you have only 1 card slot and
+don't mind loading a new driver for each reader then ignore @p Lun.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+@param[in] Tag Tag of the desired data value
+@param[in,out] Length Length of the desired data value
+@param[out] Value Value of the desired data
+
+This function is also called when the application uses the PC/SC
+SCardGetAttrib() function. The list of supported tags is not limited.
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG)
+@retval IFD_ERROR_SET_FAILURE Could not set value (\ref IFD_ERROR_SET_FAILURE)
+@retval IFD_ERROR_VALUE_READ_ONLY Trying to set read only value (\ref IFD_ERROR_VALUE_READ_ONLY)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value);
+
+/**
+This function should set the Protocol Type Selection (PTS) of a
+particular card/slot using the three PTS parameters sent
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+@param[in] Protocol Desired protocol
+- \ref SCARD_PROTOCOL_T0
+ T=0 protocol
+- \ref SCARD_PROTOCOL_T1
+ T=1 protocol
+@param[in] Flags Logical OR of possible values to determine which PTS values
+to negotiate
+- \ref IFD_NEGOTIATE_PTS1
+- \ref IFD_NEGOTIATE_PTS2
+- \ref IFD_NEGOTIATE_PTS3
+@param[in] PTS1 1st PTS Value
+@param[in] PTS2 2nd PTS Value
+@param[in] PTS3 3rd PTS Value\n
+ See ISO 7816/EMV documentation.
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_ERROR_PTS_FAILURE Could not set PTS value (\ref IFD_ERROR_PTS_FAILURE)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_PROTOCOL_NOT_SUPPORTED Protocol is not supported (\ref IFD_PROTOCOL_NOT_SUPPORTED)
+@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol, UCHAR Flags,
+ UCHAR PTS1, UCHAR PTS2, UCHAR PTS3);
+/**
+This function controls the power and reset signals of the smart card
+reader at the particular reader/slot specified by @p Lun.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+@param[in] Action Action to be taken on the card
+- \ref IFD_POWER_UP
+ Power up the card (store and return Atr and AtrLength)
+- \ref IFD_POWER_DOWN
+ Power down the card (Atr and AtrLength should be zeroed)
+- \ref IFD_RESET
+ Perform a warm reset of the card (no power down). If the card is not powered then power up the card (store and return Atr and AtrLength)
+@param[out] Atr Answer to Reset (ATR) of the card\n
+ The driver is responsible for caching this value in case
+ IFDHGetCapabilities() is called requesting the ATR and its length. The
+ ATR length should not exceed \ref MAX_ATR_SIZE.
+@param[in,out] AtrLength Length of the ATR\n
+ This should not exceed \ref MAX_ATR_SIZE.
+
+@note
+Memory cards without an ATR should return \ref IFD_SUCCESS on reset but the
+Atr should be zeroed and the length should be zero Reset errors should
+return zero for the AtrLength and return \ref IFD_ERROR_POWER_ACTION.
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_ERROR_POWER_ACTION Error powering/resetting card (\ref IFD_ERROR_POWER_ACTION)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD
+ AtrLength);
+
+/**
+This function performs an APDU exchange with the card/slot specified by
+Lun. The driver is responsible for performing any protocol specific
+exchanges such as T=0, 1, etc. differences. Calling this function will
+abstract all protocol differences.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+@param[in] SendPci contains two structure members
+- Protocol 0, 1, ... 14\n
+ T=0 ... T=14
+- Length\n
+ Not used.
+@param[in] TxBuffer Transmit APDU\n
+ Example: "\x00\xA4\x00\x00\x02\x3F\x00"
+@param[in] TxLength Length of this buffer
+@param[out] RxBuffer Receive APDU\n
+ Example: "\x61\x14"
+@param[in,out] RxLength Length of the received APDU\n
+ This function will be passed the size of the buffer of RxBuffer and
+ this function is responsible for setting this to the length of the
+ received APDU response. This should be ZERO on all errors. The
+ resource manager will take responsibility of zeroing out any temporary
+ APDU buffers for security reasons.
+@param[out] RecvPci contains two structure members
+- Protocol - 0, 1, ... 14\n
+ T=0 ... T=14
+- Length\n
+ Not used.
+
+@note
+The driver is responsible for knowing what type of card it has. If the
+current slot/card contains a memory card then this command should ignore
+the Protocol and use the MCT style commands for support for these style
+cards and transmit them appropriately. If your reader does not support
+memory cards or you don't want to implement this functionality, then
+ignore this.
+@par
+RxLength should be set to zero on error.
+@par
+The driver is not responsible for doing an automatic Get Response
+command for received buffers containing 61 XX.
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT)
+@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT)
+@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
+ PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD
+ RxLength, PSCARD_IO_HEADER RecvPci);
+
+/**
+This function returns the status of the card inserted in the reader/slot
+specified by @p Lun. In cases where the device supports asynchronous
+card insertion/removal detection, it is advised that the driver manages
+this through a thread so the driver does not have to send and receive a
+command each time this function is called.
+
+@ingroup IFDHandler
+@param[in] Lun Logical Unit Number
+
+@return Error codes
+@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
+@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
+@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT)
+@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
+ */
+RESPONSECODE IFDHICCPresence(DWORD Lun);
+
+#endif
diff --git a/de.persosim.driver.unix/MacOSX/pcsclite.h b/de.persosim.driver.unix/MacOSX/pcsclite.h
new file mode 100644
index 0000000..0a454f6
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/pcsclite.h
@@ -0,0 +1,2 @@
+#include
+#include
diff --git a/de.persosim.driver.unix/MacOSX/winscard.h b/de.persosim.driver.unix/MacOSX/winscard.h
new file mode 100644
index 0000000..18dea51
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/winscard.h
@@ -0,0 +1,2 @@
+#include
+#include
diff --git a/de.persosim.driver.unix/MacOSX/wintypes.h b/de.persosim.driver.unix/MacOSX/wintypes.h
new file mode 100644
index 0000000..a9736e8
--- /dev/null
+++ b/de.persosim.driver.unix/MacOSX/wintypes.h
@@ -0,0 +1 @@
+#include
diff --git a/de.persosim.driver.unix/README.md b/de.persosim.driver.unix/README.md
new file mode 100644
index 0000000..2bd8bb8
--- /dev/null
+++ b/de.persosim.driver.unix/README.md
@@ -0,0 +1,28 @@
+# PersoSim - Der Open Source Simulator für den elektronischen Personalausweis
+Stand: 02.06.2016
+
+## Systemvorraussetzungen
+Bisher getestet unter Ubuntu 12.04 LTS und OS X 10.10
+
+### Ubuntu 12.04 LTS
+Benötigt werden zusätzlich zur Standardinstallation die folgenden Pakete
+- pcscd
+- pcsc-tools
+- libpcsclite-dev
+
+Diese können per `sudo apt-get install pcscd pcsc-tools libpcsclite-dev` installiert werden.
+
+### OS X 10.10
+Benötigt wird das Paket XCode, welches über den Mac App Store installiert werden kann.
+
+## Installation
+Das Treiberpaket liegt momentan lediglich im Quellcode vor und kann mit der weit verbreiteten Kommandokombination
+```
+cmake .
+make
+sudo make install
+```
+kompiliert und installiert werden.
+
+# Sonstiges
+Solange kein Simulator läuft, meldet der Treiber "Keine Karte im Leser". Sobald ein Simulator am konfigurierten Port verfügbar ist, ist dieser über den Treiber nutzbar.
diff --git a/de.persosim.driver.linux/hexString.c b/de.persosim.driver.unix/hexString.c
similarity index 100%
rename from de.persosim.driver.linux/hexString.c
rename to de.persosim.driver.unix/hexString.c
diff --git a/de.persosim.driver.linux/hexString.h b/de.persosim.driver.unix/hexString.h
similarity index 100%
rename from de.persosim.driver.linux/hexString.h
rename to de.persosim.driver.unix/hexString.h
diff --git a/de.persosim.driver.linux/hexStringTest.c b/de.persosim.driver.unix/hexStringTest.c
similarity index 100%
rename from de.persosim.driver.linux/hexStringTest.c
rename to de.persosim.driver.unix/hexStringTest.c
diff --git a/de.persosim.driver.linux/ifdhPersoSim.c b/de.persosim.driver.unix/ifdhPersoSim.c
similarity index 100%
rename from de.persosim.driver.linux/ifdhPersoSim.c
rename to de.persosim.driver.unix/ifdhPersoSim.c
diff --git a/de.persosim.driver.unix/misc.h b/de.persosim.driver.unix/misc.h
new file mode 100644
index 0000000..ea0d098
--- /dev/null
+++ b/de.persosim.driver.unix/misc.h
@@ -0,0 +1,83 @@
+/*
+ * This handles GCC attributes
+ *
+ * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
+ *
+ * Copyright (C) 2005-2010
+ * Ludovic Rousseau
+ *
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __misc_h__
+#define __misc_h__
+
+/*
+ * Declare the function as internal to the library: the function name is
+ * not exported and can't be used by a program linked to the library
+ *
+ * see http://gcc.gnu.org/onlinedocs/gcc-3.3.5/gcc/Function-Attributes.html#Function-Attributes
+ * see http://www.nedprod.com/programs/gccvisibility.html
+ */
+#if defined __GNUC__ && (! defined (__sun)) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
+#define INTERNAL __attribute__ ((visibility("hidden")))
+#define PCSC_API __attribute__ ((visibility("default")))
+#elif (! defined __GNUC__ ) && defined (__sun)
+/* http://wikis.sun.com/display/SunStudio/Macros+for+Shared+Library+Symbol+Visibility */
+#define INTERNAL __hidden
+#define PCSC_API __global
+#else
+#define INTERNAL
+#define PCSC_API
+#endif
+#define EXTERNAL PCSC_API
+
+#if defined __GNUC__
+
+/* GNU Compiler Collection (GCC) */
+#define CONSTRUCTOR __attribute__ ((constructor))
+#define DESTRUCTOR __attribute__ ((destructor))
+
+#else
+
+/* SUN C compiler does not use __attribute__ but #pragma init (function)
+ * We can't use a # inside a #define so it is not possible to use
+ * #define CONSTRUCTOR_DECLARATION(x) #pragma init (x)
+ * The #pragma is used directly where needed */
+
+/* any other */
+#define CONSTRUCTOR
+#define DESTRUCTOR
+
+#endif
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef COUNT_OF
+#define COUNT_OF(arr) (sizeof(arr)/sizeof(arr[0]))
+#endif
+
+#endif /* __misc_h__ */
diff --git a/de.persosim.driver.linux/persoSimConnect.c b/de.persosim.driver.unix/persoSimConnect.c
similarity index 98%
rename from de.persosim.driver.linux/persoSimConnect.c
rename to de.persosim.driver.unix/persoSimConnect.c
index a125b56..4fcc172 100644
--- a/de.persosim.driver.linux/persoSimConnect.c
+++ b/de.persosim.driver.unix/persoSimConnect.c
@@ -56,7 +56,7 @@ int transmit (int sockfd, const char* msgBuffer) {
strcat(transmitBuffer, "\n");
Log2(PCSC_LOG_DEBUG, "Sending message to client: %s", transmitBuffer);
- if (send(sockfd, transmitBuffer, bufferLength, MSG_NOSIGNAL) < 0) {
+ if (send(sockfd, transmitBuffer, bufferLength, 0) < 0) {
Log1(PCSC_LOG_ERROR, "Failure during transmit to client");
return PSIM_COMMUNICATION_ERROR;
}
@@ -195,9 +195,10 @@ void * handleHandshakeConnections(void * param) {
// enable connector as new reader
curReader->clientSocket = clientSocket;
+#if !defined(__APPLE__)
//let pcsc rescan readers
raise(SIGUSR1);
-
+#endif
//XXX implement closing and disposal of client sockets (through handshake as well as on errors)
}
diff --git a/de.persosim.driver.linux/persoSimConnect.h b/de.persosim.driver.unix/persoSimConnect.h
similarity index 100%
rename from de.persosim.driver.linux/persoSimConnect.h
rename to de.persosim.driver.unix/persoSimConnect.h
diff --git a/de.persosim.driver.unix/reader.conf.in b/de.persosim.driver.unix/reader.conf.in
new file mode 100644
index 0000000..e2a1527
--- /dev/null
+++ b/de.persosim.driver.unix/reader.conf.in
@@ -0,0 +1,4 @@
+FRIENDLYNAME "PersoSimHandshake"
+DEVICENAME localhost:5678
+LIBPATH @LIBPATH@
+CHANNELID 0x8C7B