From 9d84541e6ffa5afbb6adb0b4887c0bebb0afeb41 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 20 Oct 2016 15:47:19 +0200 Subject: [PATCH] libports: add pcsc-lite library Fixes #2145 --- repos/libports/lib/import/import-pcsc-lite.mk | 1 + repos/libports/lib/mk/pcsc-lite.mk | 51 ++ repos/libports/ports/pcsc-lite.hash | 1 + repos/libports/ports/pcsc-lite.port | 13 + repos/libports/run/smartcard.run | 124 +++ repos/libports/src/lib/pcsc-lite/README | 12 + repos/libports/src/lib/pcsc-lite/config.h | 245 ++++++ repos/libports/src/lib/pcsc-lite/init.cc | 88 ++ .../src/lib/pcsc-lite/pcsc-lite.patch | 760 ++++++++++++++++++ repos/libports/src/test/smartcard/main.cc | 104 +++ repos/libports/src/test/smartcard/target.mk | 5 + tool/autopilot.list | 1 + 12 files changed, 1405 insertions(+) create mode 100644 repos/libports/lib/import/import-pcsc-lite.mk create mode 100644 repos/libports/lib/mk/pcsc-lite.mk create mode 100644 repos/libports/ports/pcsc-lite.hash create mode 100644 repos/libports/ports/pcsc-lite.port create mode 100644 repos/libports/run/smartcard.run create mode 100644 repos/libports/src/lib/pcsc-lite/README create mode 100644 repos/libports/src/lib/pcsc-lite/config.h create mode 100644 repos/libports/src/lib/pcsc-lite/init.cc create mode 100644 repos/libports/src/lib/pcsc-lite/pcsc-lite.patch create mode 100644 repos/libports/src/test/smartcard/main.cc create mode 100644 repos/libports/src/test/smartcard/target.mk diff --git a/repos/libports/lib/import/import-pcsc-lite.mk b/repos/libports/lib/import/import-pcsc-lite.mk new file mode 100644 index 000000000..63fadc823 --- /dev/null +++ b/repos/libports/lib/import/import-pcsc-lite.mk @@ -0,0 +1 @@ +INC_DIR += $(call select_from_ports,pcsc-lite)/include/PCSC diff --git a/repos/libports/lib/mk/pcsc-lite.mk b/repos/libports/lib/mk/pcsc-lite.mk new file mode 100644 index 000000000..3dea4e724 --- /dev/null +++ b/repos/libports/lib/mk/pcsc-lite.mk @@ -0,0 +1,51 @@ +PCSC_LITE_DIR := $(call select_from_ports,pcsc-lite)/src/lib/pcsc-lite + +include $(call select_from_repositories,lib/import/import-pcsc-lite.mk) + +LIBS += ccid libc + +# find 'config.h' +INC_DIR += $(REP_DIR)/src/lib/pcsc-lite + +INC_DIR += $(PCSC_LITE_DIR)/src + +CC_DEF += -DPCSCLITE_STATIC_DRIVER -DIFDHANDLERv3 -DGENODE + +SRC_C = debug.c \ + error.c \ + winscard_clnt.c \ + simclist.c \ + sys_unix.c \ + utils.c \ + winscard_msg.c \ + auth.c \ + atrhandler.c \ + debuglog.c \ + dyn_unix.c \ + eventhandler.c \ + hotplug_generic.c \ + ifdwrapper.c \ + powermgt_generic.c \ + prothandler.c \ + readerfactory.c \ + winscard.c + +SRC_CC = init.cc + +CC_OPT_winscard = -DSCardEstablishContext=SCardEstablishContextImpl \ + -DSCardReleaseContext=SCardReleaseContextImpl \ + -DSCardConnect=SCardConnectImpl \ + -DSCardReconnect=SCardReconnectImpl \ + -DSCardDisconnect=SCardDisconnectImpl \ + -DSCardBeginTransaction=SCardBeginTransactionImpl \ + -DSCardEndTransaction=SCardEndTransactionImpl \ + -DSCardStatus=SCardStatusImpl \ + -DSCardControl=SCardControlImpl \ + -DSCardGetAttrib=SCardGetAttribImpl \ + -DSCardSetAttrib=SCardSetAttribImpl \ + -DSCardTransmit=SCardTransmitImpl + +vpath %.c $(PCSC_LITE_DIR)/src +vpath %.cc $(REP_DIR)/src/lib/pcsc-lite + +SHARED_LIB = yes diff --git a/repos/libports/ports/pcsc-lite.hash b/repos/libports/ports/pcsc-lite.hash new file mode 100644 index 000000000..9f6ce4e74 --- /dev/null +++ b/repos/libports/ports/pcsc-lite.hash @@ -0,0 +1 @@ +e32624a4145b75f8a2aebe55418fa2fb510faf4b diff --git a/repos/libports/ports/pcsc-lite.port b/repos/libports/ports/pcsc-lite.port new file mode 100644 index 000000000..2122387c0 --- /dev/null +++ b/repos/libports/ports/pcsc-lite.port @@ -0,0 +1,13 @@ +LICENSE := LGPL +DOWNLOADS := pcsc-lite.archive +VERSION := 1.8.18 + +URL(pcsc-lite) := https://alioth.debian.org/frs/download.php/file/4179/pcsc-lite-$(VERSION).tar.bz2 +SHA(pcsc-lite) := 2a2552f7196457f5750efad1b29affd0a9620890 +DIR(pcsc-lite) := src/lib/pcsc-lite + +DIRS := include/PCSC +DIR_CONTENT(include/PCSC) := $(addprefix src/lib/pcsc-lite/src/PCSC/,debuglog.h ifdhandler.h pcsclite.h reader.h winscard.h wintypes.h) + +PATCHES := src/lib/pcsc-lite/pcsc-lite.patch +PATCH_OPT := -p1 -d src/lib/pcsc-lite diff --git a/repos/libports/run/smartcard.run b/repos/libports/run/smartcard.run new file mode 100644 index 000000000..1e456f3ce --- /dev/null +++ b/repos/libports/run/smartcard.run @@ -0,0 +1,124 @@ +# +# Smartcard test +# +# NOTE: The vendor id and product id of the USB card reader to be used must be +# configured for the application and for the USB driver. +# + +if { [have_include "power_on/qemu"] || [have_spec linux] } { + puts "Run script does not support Qemu or Linux" + exit 0 +} + +if { [get_cmd_switch --autopilot] && ![have_spec x86] } { + puts "Run script is only supported in autopilot mode on x86 platforms" + exit 0 +} + +# +# Build +# + +set build_components { + core init + drivers/timer + drivers/usb + test/smartcard +} + +lappend_if [have_spec gpio] build_components drivers/gpio + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +build $build_components + +create_boot_directory + +# +# Generate config +# + +append config { + + + + + + + + + + + + + + + } + +append_if [have_spec gpio] config { + + + + + } + +append_platform_drv_config + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core init timer usb_drv test-smartcard + ld.lib.so pcsc-lite.lib.so ccid.lib.so libusb.lib.so + libc.lib.so libc_pipe.lib.so pthread.lib.so + Info.plist +} + +lappend_if [have_spec gpio] boot_modules gpio_drv + +append_platform_drv_boot_modules + +build_boot_image $boot_modules + +run_genode_until { Response: 62 0A 82 01 38 83 02 3F 00 8A 01 05 90 00} 30 + +exec rm bin/Info.plist diff --git a/repos/libports/src/lib/pcsc-lite/README b/repos/libports/src/lib/pcsc-lite/README new file mode 100644 index 000000000..192f43826 --- /dev/null +++ b/repos/libports/src/lib/pcsc-lite/README @@ -0,0 +1,12 @@ +The USB card reader to be used by an application must be configured with its +vendor id and product id in a file '/config.pcsc-lite': + + + + + + + + + + diff --git a/repos/libports/src/lib/pcsc-lite/config.h b/repos/libports/src/lib/pcsc-lite/config.h new file mode 100644 index 000000000..cb524e3fa --- /dev/null +++ b/repos/libports/src/lib/pcsc-lite/config.h @@ -0,0 +1,245 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* display ATR parsing debug messages. */ +/* #undef ATR_DEBUG */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Filter reader names */ +/* #undef FILTER_NAMES */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +/* undef HAVE_ALLOCA */ + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +/* #undef HAVE_ALLOCA_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DL_H */ + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Libudev is available */ +/* #undef HAVE_LIBUDEV */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBUDEV_H */ + +/* Libusb is available */ +/* #undef HAVE_LIBUSB */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBUSB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Build polkit access control support */ +/* #undef HAVE_POLKIT */ + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Define to 1 if you have the `pthread_cancel' function. */ +#define HAVE_PTHREAD_CANCEL 1 + +/* Have PTHREAD_PRIO_INHERIT. */ +#define HAVE_PTHREAD_PRIO_INHERIT 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +#define HAVE_STRUCT_DIRENT_D_TYPE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Disable logging support */ +/* #undef NO_LOG */ + +/* Name of package */ +#define PACKAGE "pcsc-lite" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "pcsc-lite" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "pcsc-lite 1.8.18" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "pcsc-lite" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.8.18" + +/* pcscd filename */ +#define PCSCD_BINARY "/usr/local/sbin/pcscd" + +/* Enabled PC/SC lite features */ +#define PCSCLITE_FEATURES " Linux x86_64-pc-linux-gnu usbdropdir=/ ipcdir=/var/run/pcscd configdir=/usr/local/etc/reader.conf.d" + +/* directory containing USB drivers */ +#define PCSCLITE_HP_DROPDIR "/" + +/* PC/SC target architecture */ +#define PCSC_ARCH "Linux" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* directory containing IPC files */ +#define USE_IPCDIR "/var/run/pcscd" + +/* Use serial conf file mechanism */ +/* #undef USE_SERIAL */ + +/* Use USB hotplug mechanism */ +/* #undef USE_USB */ + +/* Version number of package */ +#define VERSION "1.8.18" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ diff --git a/repos/libports/src/lib/pcsc-lite/init.cc b/repos/libports/src/lib/pcsc-lite/init.cc new file mode 100644 index 000000000..214b0d3f8 --- /dev/null +++ b/repos/libports/src/lib/pcsc-lite/init.cc @@ -0,0 +1,88 @@ +/* + * \brief pcsc-lite initialization + * \author Christian Prochaska + * \date 2016-10-11 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include + +/* libc includes */ +#include +#include +#include +#include + +/* pcsc-lite includes */ +extern "C" { +#include +#include +} + +static constexpr bool verbose = false; + +struct Pcsc_lite_initializer +{ + Pcsc_lite_initializer() + { + if (verbose) { + /* pcscd -f */ + DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG); + /* pcscd -d */ + DebugLogSetLevel(PCSC_LOG_DEBUG); + /* pcscd -a */ + (void)DebugLogSetCategory(DEBUG_CATEGORY_APDU); + } + + unsigned int vendor_id = 0x0000; + unsigned int product_id = 0x0000; + + int fd = open("/config.pcsc-lite", O_RDONLY); + + if (fd < 0) { + Genode::error("Could not open 'config.pcsc-lite'"); + exit(1); + } + + char config[128]; + if (read(fd, config, sizeof(config)) < 0) { + Genode::error("Could not read 'config.pcsc-lite'"); + exit(1); + } + + try { + + Genode::Xml_node config_node(config); + + vendor_id = config_node.attribute_value("vendor_id", 0U); + product_id = config_node.attribute_value("product_id", 0U); + + } catch (...) { + Genode::error("Error parsing 'config.pcsc-lite'"); + exit(1); + } + + close(fd); + + char device[14]; + + snprintf(device, sizeof(device), "usb:%04x/%04x", vendor_id, product_id); + + RFAllocateReaderSpace(0); + (void)RFAddReader("CCID", 0, "/", device); + } +}; + + +extern "C" void initialize_pcsc_lite() +{ + static Pcsc_lite_initializer pcsc_lite_initializer; +} diff --git a/repos/libports/src/lib/pcsc-lite/pcsc-lite.patch b/repos/libports/src/lib/pcsc-lite/pcsc-lite.patch new file mode 100644 index 000000000..252e90ed0 --- /dev/null +++ b/repos/libports/src/lib/pcsc-lite/pcsc-lite.patch @@ -0,0 +1,760 @@ +pcsc-lite.patch + +From: Christian Prochaska + + +--- + src/debug.c | 3 + src/readerfactory.c | 2 + src/winscard_clnt.c | 377 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 374 insertions(+), 8 deletions(-) + +diff --git a/src/debug.c b/src/debug.c +index d2fb5bf..1f6bccc 100644 +--- a/src/debug.c ++++ b/src/debug.c +@@ -101,6 +101,7 @@ static void log_init(void) + } + } /* log_init */ + ++#ifndef GENODE + void log_msg(const int priority, const char *fmt, ...) + { + char DebugBuffer[DEBUG_BUF_SIZE]; +@@ -150,6 +151,6 @@ void log_msg(const int priority, const char *fmt, ...) + fprintf(stderr, "%s\n", DebugBuffer); + } + } /* log_msg */ +- ++#endif + #endif + +diff --git a/src/readerfactory.c b/src/readerfactory.c +index 4f97892..3bec158 100644 +--- a/src/readerfactory.c ++++ b/src/readerfactory.c +@@ -1399,7 +1399,7 @@ void RFCleanupReaders(void) + * Wait until all connected readers have a chance to power up a possibly + * inserted card. + */ +-#ifdef USE_USB ++#if defined(USE_USB) || defined(GENODE) + void RFWaitForReaderInit(void) + { + int i, need_to_wait; +diff --git a/src/winscard_clnt.c b/src/winscard_clnt.c +index 94d4cf5..bf18c7c 100644 +--- a/src/winscard_clnt.c ++++ b/src/winscard_clnt.c +@@ -113,6 +113,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #include + #include + #include ++#include + + #include "misc.h" + #include "pcscd.h" +@@ -143,6 +144,52 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + static char sharing_shall_block = TRUE; + ++#ifdef GENODE ++ ++static int event_pipe[2]; ++ ++extern void initialize_pcsc_lite(); ++ ++LONG MSGSignalClient(uint32_t filedes, LONG rv) ++{ ++ ssize_t bytes_written = write(filedes, &rv, sizeof(rv)); ++ ++ if (bytes_written == sizeof(rv)) ++ return SCARD_S_SUCCESS; ++ else ++ return SCARD_F_UNKNOWN_ERROR; ++} ++ ++extern LONG SCardEstablishContextImpl(DWORD dwScope, LPCVOID pvReserved1, ++ LPCVOID pvReserved2, ++ LPSCARDCONTEXT phContext); ++extern LONG SCardReleaseContextImpl(SCARDCONTEXT hContext); ++extern LONG SCardConnectImpl(SCARDCONTEXT hContext, LPCSTR szReader, ++ DWORD dwShareMode, DWORD dwPreferredProtocols, ++ LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); ++extern LONG SCardReconnectImpl(SCARDHANDLE hCard, DWORD dwShareMode, ++ DWORD dwPreferredProtocols, DWORD dwInitialization, ++ LPDWORD pdwActiveProtocol); ++extern LONG SCardDisconnectImpl(SCARDHANDLE hCard, DWORD dwDisposition); ++extern LONG SCardBeginTransactionImpl(SCARDHANDLE hCard); ++extern LONG SCardEndTransactionImpl(SCARDHANDLE hCard, DWORD dwDisposition); ++extern LONG SCardStatusImpl(SCARDHANDLE hCard, LPSTR szReaderNames, ++ LPDWORD pcchReaderLen, LPDWORD pdwState, ++ LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen); ++extern LONG SCardControlImpl(SCARDHANDLE hCard, DWORD dwControlCode, ++ LPCVOID pbSendBuffer, DWORD cbSendLength, ++ LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned); ++extern LONG SCardGetAttribImpl(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, ++ LPDWORD pcbAttrLen); ++extern LONG SCardSetAttribImpl(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, ++ DWORD cbAttrLen); ++extern LONG SCardTransmitImpl(SCARDHANDLE hCard, ++ const SCARD_IO_REQUEST *pioSendPci, ++ LPCBYTE pbSendBuffer, DWORD cbSendLength, ++ SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, ++ LPDWORD pcbRecvLength); ++#endif ++ + #define COLOR_RED "\33[01;31m" + #define COLOR_GREEN "\33[32m" + #define COLOR_BLUE "\33[34m" +@@ -355,7 +402,11 @@ static pthread_mutex_t clientMutex = PTHREAD_MUTEX_INITIALIZER; + /** + * Area used to read status information about the readers. + */ ++#ifndef GENODE + static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]; ++#else ++extern READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]; ++#endif + + /** Protocol Control Information for T=0 */ + PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(SCARD_IO_REQUEST) }; +@@ -451,17 +502,22 @@ LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, + API_TRACE_IN("%ld, %p, %p", dwScope, pvReserved1, pvReserved2) + PROFILE_START + ++#ifndef GENODE + /* Check if the server is running */ + rv = SCardCheckDaemonAvailability(); + if (rv != SCARD_S_SUCCESS) + goto end; ++#endif + + (void)SCardLockThread(); + rv = SCardEstablishContextTH(dwScope, pvReserved1, + pvReserved2, phContext); + (void)SCardUnlockThread(); + ++#ifndef GENODE + end: ++#endif ++ + PROFILE_END(rv) + API_TRACE_OUT("%ld", *phContext) + +@@ -548,7 +604,7 @@ static LONG SCardEstablishContextTH(DWORD dwScope, + isExecuted = 1; + } + +- ++#ifndef GENODE + /* Establishes a connection to the server */ + if (ClientSetupSession(&dwClientID) != 0) + { +@@ -582,6 +638,17 @@ static LONG SCardEstablishContextTH(DWORD dwScope, + if (veStr.rv != SCARD_S_SUCCESS) + return veStr.rv; + } ++#else ++ ++ initialize_pcsc_lite(); ++ ++ rv = pipe(event_pipe); ++ if (rv < 0) { ++ fprintf(stderr, "Could not create pipe\n"); ++ return rv; ++ } ++ ++#endif + + again: + /* +@@ -591,6 +658,7 @@ again: + scEstablishStruct.hContext = 0; + scEstablishStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_ESTABLISH_CONTEXT, dwClientID, + sizeof(scEstablishStruct), (void *) &scEstablishStruct); + +@@ -605,6 +673,21 @@ again: + + if (rv != SCARD_S_SUCCESS) + return rv; ++#else ++ ++ struct establish_struct esStr; ++ SCARDCONTEXT hContext; ++ ++ esStr = scEstablishStruct; ++ ++ hContext = esStr.hContext; ++ esStr.rv = SCardEstablishContextImpl(esStr.dwScope, 0, 0, ++ &hContext); ++ esStr.hContext = hContext; ++ ++ scEstablishStruct = esStr; ++ ++#endif + + if (scEstablishStruct.rv != SCARD_S_SUCCESS) + return scEstablishStruct.rv; +@@ -669,6 +752,7 @@ LONG SCardReleaseContext(SCARDCONTEXT hContext) + scReleaseStruct.hContext = hContext; + scReleaseStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_RELEASE_CONTEXT, + currentContextMap->dwClientID, + sizeof(scReleaseStruct), (void *) &scReleaseStruct); +@@ -684,9 +768,23 @@ LONG SCardReleaseContext(SCARDCONTEXT hContext) + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct release_struct reStr; ++ ++ reStr = scReleaseStruct; ++ ++ reStr.rv = SCardReleaseContextImpl(reStr.hContext); ++ ++ scReleaseStruct = reStr; ++ ++#endif + + rv = scReleaseStruct.rv; ++ ++#ifndef GENODE + end: ++#endif + (void)pthread_mutex_unlock(¤tContextMap->mMutex); + + /* +@@ -805,6 +903,8 @@ LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, + scConnectStruct.dwActiveProtocol = 0; + scConnectStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE ++ + rv = MessageSendWithHeader(SCARD_CONNECT, currentContextMap->dwClientID, + sizeof(scConnectStruct), (void *) &scConnectStruct); + +@@ -820,6 +920,29 @@ LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, + if (rv != SCARD_S_SUCCESS) + goto end; + ++#else ++ ++ struct connect_struct coStr; ++ SCARDHANDLE hCard; ++ DWORD dwActiveProtocol; ++ ++ coStr = scConnectStruct; ++ ++ coStr.szReader[sizeof(coStr.szReader)-1] = 0; ++ hCard = coStr.hCard; ++ dwActiveProtocol = coStr.dwActiveProtocol; ++ ++ coStr.rv = SCardConnectImpl(coStr.hContext, coStr.szReader, ++ coStr.dwShareMode, coStr.dwPreferredProtocols, ++ &hCard, &dwActiveProtocol); ++ ++ coStr.hCard = hCard; ++ coStr.dwActiveProtocol = dwActiveProtocol; ++ ++ scConnectStruct = coStr; ++ ++#endif ++ + *phCard = scConnectStruct.hCard; + *pdwActiveProtocol = scConnectStruct.dwActiveProtocol; + +@@ -833,7 +956,10 @@ LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, + else + rv = scConnectStruct.rv; + ++#ifndef GENODE + end: ++#endif ++ + (void)pthread_mutex_unlock(¤tContextMap->mMutex); + + PROFILE_END(rv) +@@ -948,6 +1074,7 @@ retry: + scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol; + scReconnectStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_RECONNECT, currentContextMap->dwClientID, + sizeof(scReconnectStruct), (void *) &scReconnectStruct); + +@@ -962,6 +1089,21 @@ retry: + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct reconnect_struct rcStr; ++ DWORD dwActiveProtocol; ++ ++ rcStr = scReconnectStruct; ++ ++ rcStr.rv = SCardReconnectImpl(rcStr.hCard, rcStr.dwShareMode, ++ rcStr.dwPreferredProtocols, rcStr.dwInitialization, ++ &dwActiveProtocol); ++ rcStr.dwActiveProtocol = dwActiveProtocol; ++ ++ scReconnectStruct = rcStr; ++ ++#endif + + rv = scReconnectStruct.rv; + +@@ -974,7 +1116,9 @@ retry: + + *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol; + ++#ifndef GENODE + end: ++#endif + (void)pthread_mutex_unlock(¤tContextMap->mMutex); + + PROFILE_END(rv) +@@ -1039,6 +1183,7 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) + scDisconnectStruct.dwDisposition = dwDisposition; + scDisconnectStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_DISCONNECT, currentContextMap->dwClientID, + sizeof(scDisconnectStruct), (void *) &scDisconnectStruct); + +@@ -1053,12 +1198,25 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct disconnect_struct diStr; ++ ++ diStr = scDisconnectStruct; ++ ++ diStr.rv = SCardDisconnectImpl(diStr.hCard, diStr.dwDisposition); ++ ++ scDisconnectStruct = diStr; ++ ++#endif + + if (SCARD_S_SUCCESS == scDisconnectStruct.rv) + (void)SCardRemoveHandle(hCard); + rv = scDisconnectStruct.rv; + ++#ifndef GENODE + end: ++#endif + (void)pthread_mutex_unlock(¤tContextMap->mMutex); + + error: +@@ -1132,6 +1290,7 @@ LONG SCardBeginTransaction(SCARDHANDLE hCard) + scBeginStruct.hCard = hCard; + scBeginStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_BEGIN_TRANSACTION, + currentContextMap->dwClientID, + sizeof(scBeginStruct), (void *) &scBeginStruct); +@@ -1147,6 +1306,17 @@ LONG SCardBeginTransaction(SCARDHANDLE hCard) + + if (rv != SCARD_S_SUCCESS) + break; ++#else ++ ++ struct begin_struct beStr; ++ ++ beStr = scBeginStruct; ++ ++ beStr.rv = SCardBeginTransactionImpl(beStr.hCard); ++ ++ scBeginStruct = beStr; ++ ++#endif + + rv = scBeginStruct.rv; + +@@ -1227,6 +1397,7 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) + scEndStruct.dwDisposition = dwDisposition; + scEndStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_END_TRANSACTION, + currentContextMap->dwClientID, + sizeof(scEndStruct), (void *) &scEndStruct); +@@ -1242,6 +1413,18 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct end_struct enStr; ++ ++ enStr = scEndStruct; ++ ++ enStr.rv = SCardEndTransactionImpl(enStr.hCard, ++ enStr.dwDisposition); ++ ++ scEndStruct = enStr; ++ ++#endif + + /* + * This helps prevent starvation +@@ -1250,7 +1433,9 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) + (void)SYS_USleep(randnum); + rv = scEndStruct.rv; + ++#ifndef GENODE + end: ++#endif + (void)pthread_mutex_unlock(¤tContextMap->mMutex); + + PROFILE_END(rv) +@@ -1426,6 +1611,7 @@ retry: + memset(&scStatusStruct, 0, sizeof(scStatusStruct)); + scStatusStruct.hCard = hCard; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID, + sizeof(scStatusStruct), (void *) &scStatusStruct); + +@@ -1440,6 +1626,19 @@ retry: + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct status_struct stStr; ++ ++ stStr = scStatusStruct; ++ ++ /* only hCard and return value are used by the client */ ++ stStr.rv = SCardStatusImpl(stStr.hCard, NULL, NULL, NULL, ++ NULL, 0, NULL); ++ ++ scStatusStruct = stStr; ++ ++#endif + + rv = scStatusStruct.rv; + +@@ -2036,7 +2235,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, + + /* another thread can do SCardCancel() */ + currentContextMap->cancellable = TRUE; +- ++#ifndef GENODE + rv = MessageSendWithHeader(CMD_WAIT_READER_STATE_CHANGE, + currentContextMap->dwClientID, + sizeof(waitStatusStruct), &waitStatusStruct); +@@ -2050,13 +2249,45 @@ LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, + rv = MessageReceiveTimeout(CMD_WAIT_READER_STATE_CHANGE, + &waitStatusStruct, sizeof(waitStatusStruct), + currentContextMap->dwClientID, dwTime); ++#else ++ ++ EHRegisterClientForEvent(event_pipe[1]); ++ ++ fd_set readfds; ++ struct timeval timeout; + ++ timeout.tv_sec = dwTime / 1000; ++ timeout.tv_usec = (dwTime % 1000) * 1000; ++ ++ FD_ZERO(&readfds); ++ FD_SET(event_pipe[0], &readfds); ++ ++ rv = select(event_pipe[0] + 1, &readfds, NULL, NULL, &timeout); ++ ++ if ((rv > 0) && (FD_ISSET(event_pipe[0], &readfds))) { ++ /* got an event */ ++ rv = read(event_pipe[0], &waitStatusStruct.rv, sizeof(waitStatusStruct.rv)); ++ if (rv == sizeof(waitStatusStruct.rv)) { ++ rv = SCARD_S_SUCCESS; ++ } else { ++ fprintf(stderr, "Error reading event from pipe\n"); ++ rv = SCARD_F_UNKNOWN_ERROR; ++ } ++ } else if (rv == 0) { ++ /* timeout */ ++ rv = SCARD_E_TIMEOUT; ++ } else { ++ rv = SCARD_F_UNKNOWN_ERROR; ++ } ++ ++#endif + /* another thread can do SCardCancel() */ + currentContextMap->cancellable = FALSE; + + /* timeout */ + if (SCARD_E_TIMEOUT == rv) + { ++#ifndef GENODE + /* ask server to remove us from the event list */ + rv = MessageSendWithHeader(CMD_STOP_WAITING_READER_STATE_CHANGE, + currentContextMap->dwClientID, +@@ -2072,6 +2303,18 @@ LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct wait_reader_state_change waStr; ++ ++ waStr = waitStatusStruct; ++ ++ /* add the client fd to the list */ ++ waStr.rv = EHUnregisterClientForEvent(event_pipe[1]); ++ ++ waitStatusStruct = waStr; ++ ++#endif + } + + if (rv != SCARD_S_SUCCESS) +@@ -2222,6 +2465,7 @@ LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, + scControlStruct.dwBytesReturned = 0; + scControlStruct.rv = 0; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_CONTROL, currentContextMap->dwClientID, + sizeof(scControlStruct), &scControlStruct); + +@@ -2255,6 +2499,26 @@ LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, + + } + ++#else ++ ++ struct control_struct ctStr; ++ DWORD dwBytesReturned; ++ ++ ctStr = scControlStruct; ++ ++ dwBytesReturned = ctStr.dwBytesReturned; ++ ++ ctStr.rv = SCardControlImpl(ctStr.hCard, ctStr.dwControlCode, ++ pbSendBuffer, ctStr.cbSendLength, ++ pbRecvBuffer, ctStr.cbRecvLength, ++ &dwBytesReturned); ++ ++ ctStr.dwBytesReturned = dwBytesReturned; ++ ++ scControlStruct = ctStr; ++ ++#endif ++ + if (NULL != lpBytesReturned) + *lpBytesReturned = scControlStruct.dwBytesReturned; + +@@ -2519,6 +2783,7 @@ static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId, + /* we can get up to the communication buffer size */ + scGetSetStruct.cbAttrLen = sizeof scGetSetStruct.pbAttr; + ++#ifndef GENODE + rv = MessageSendWithHeader(command, currentContextMap->dwClientID, + sizeof(scGetSetStruct), &scGetSetStruct); + +@@ -2533,6 +2798,38 @@ static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId, + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ if (command == SCARD_GET_ATTRIB) { ++ ++ struct getset_struct gsStr; ++ DWORD cbAttrLen; ++ ++ gsStr = scGetSetStruct; ++ ++ cbAttrLen = gsStr.cbAttrLen; ++ ++ gsStr.rv = SCardGetAttribImpl(gsStr.hCard, gsStr.dwAttrId, ++ gsStr.pbAttr, &cbAttrLen); ++ ++ gsStr.cbAttrLen = cbAttrLen; ++ ++ scGetSetStruct = gsStr; ++ ++ } else if (command == SCARD_SET_ATTRIB) { ++ ++ struct getset_struct gsStr; ++ ++ gsStr = scGetSetStruct; ++ ++ gsStr.rv = SCardSetAttribImpl(gsStr.hCard, gsStr.dwAttrId, ++ gsStr.pbAttr, gsStr.cbAttrLen); ++ ++ scGetSetStruct = gsStr; ++ ++ } ++ ++#endif + + if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command)) + { +@@ -2679,6 +2976,7 @@ retry: + scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST); + } + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_TRANSMIT, currentContextMap->dwClientID, + sizeof(scTransmitStruct), (void *) &scTransmitStruct); + +@@ -2700,16 +2998,51 @@ retry: + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct transmit_struct trStr; ++ SCARD_IO_REQUEST ioSendPci; ++ SCARD_IO_REQUEST ioRecvPci; ++ DWORD cbRecvLength; ++ ++ trStr = scTransmitStruct; ++ ++ ioSendPci.dwProtocol = trStr.ioSendPciProtocol; ++ ioSendPci.cbPciLength = trStr.ioSendPciLength; ++ ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol; ++ ioRecvPci.cbPciLength = trStr.ioRecvPciLength; ++ cbRecvLength = *pcbRecvLength; ++ ++ trStr.rv = SCardTransmitImpl(trStr.hCard, &ioSendPci, ++ pbSendBuffer, trStr.cbSendLength, &ioRecvPci, ++ pbRecvBuffer, &cbRecvLength); ++ ++ if (cbRecvLength > trStr.pcbRecvLength) ++ /* The client buffer is not large enough. ++ * The pbRecvBuffer buffer will NOT be sent a few ++ * lines bellow. So no buffer overflow is expected. */ ++ trStr.rv = SCARD_E_INSUFFICIENT_BUFFER; ++ ++ trStr.ioSendPciProtocol = ioSendPci.dwProtocol; ++ trStr.ioSendPciLength = ioSendPci.cbPciLength; ++ trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol; ++ trStr.ioRecvPciLength = ioRecvPci.cbPciLength; ++ trStr.pcbRecvLength = cbRecvLength; ++ ++ scTransmitStruct = trStr; ++ ++#endif + + if (SCARD_S_SUCCESS == scTransmitStruct.rv) + { ++#ifndef GENODE + /* read the received buffer */ + rv = MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength, + currentContextMap->dwClientID); + + if (rv != SCARD_S_SUCCESS) + goto end; +- ++#endif + if (pioRecvPci) + { + pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol; +@@ -3070,7 +3403,9 @@ LONG SCardCancel(SCARDCONTEXT hContext) + { + SCONTEXTMAP * currentContextMap; + LONG rv = SCARD_S_SUCCESS; ++#ifndef GENODE + uint32_t dwClientID = 0; ++#endif + struct cancel_struct scCancelStruct; + + PROFILE_START +@@ -3092,16 +3427,18 @@ LONG SCardCancel(SCARDCONTEXT hContext) + goto error; + } + ++#ifndef GENODE + /* create a new connection to the server */ + if (ClientSetupSession(&dwClientID) != 0) + { + rv = SCARD_E_NO_SERVICE; + goto error; + } +- ++#endif + scCancelStruct.hContext = hContext; + scCancelStruct.rv = SCARD_S_SUCCESS; + ++#ifndef GENODE + rv = MessageSendWithHeader(SCARD_CANCEL, dwClientID, + sizeof(scCancelStruct), (void *) &scCancelStruct); + +@@ -3115,11 +3452,29 @@ LONG SCardCancel(SCARDCONTEXT hContext) + + if (rv != SCARD_S_SUCCESS) + goto end; ++#else ++ ++ struct cancel_struct caStr; ++ ++ caStr = scCancelStruct; ++ ++ uint32_t fd = event_pipe[1]; ++ caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED); ++ ++ /* the client should not receive the event ++ * notification now the waiting has been cancelled */ ++ EHUnregisterClientForEvent(fd); ++ ++ scCancelStruct = caStr; ++ ++#endif + + rv = scCancelStruct.rv; ++#ifndef GENODE + end: +- ClientCloseSession(dwClientID); + ++ ClientCloseSession(dwClientID); ++#endif + error: + PROFILE_END(rv) + API_TRACE_OUT("") +@@ -3314,7 +3669,12 @@ static LONG SCardCleanContext(SCONTEXTMAP * targetContextMap) + CHANNEL_MAP * currentChannelMap; + + targetContextMap->hContext = 0; ++#ifndef GENODE + (void)ClientCloseSession(targetContextMap->dwClientID); ++#else ++ close(event_pipe[0]); ++ close(event_pipe[1]); ++#endif + targetContextMap->dwClientID = 0; + (void)pthread_mutex_destroy(&targetContextMap->mMutex); + +@@ -3490,6 +3850,7 @@ LONG SCardCheckDaemonAvailability(void) + + static LONG getReaderStates(SCONTEXTMAP * currentContextMap) + { ++#ifndef GENODE + int32_t dwClientID = currentContextMap->dwClientID; + LONG rv; + +@@ -3501,7 +3862,11 @@ static LONG getReaderStates(SCONTEXTMAP * currentContextMap) + rv = MessageReceive(&readerStates, sizeof(readerStates), dwClientID); + if (rv != SCARD_S_SUCCESS) + return rv; ++#else ++ ++ /* wait until all readers are ready */ ++ RFWaitForReaderInit(); + + return SCARD_S_SUCCESS; ++#endif + } +- diff --git a/repos/libports/src/test/smartcard/main.cc b/repos/libports/src/test/smartcard/main.cc new file mode 100644 index 000000000..04efa2293 --- /dev/null +++ b/repos/libports/src/test/smartcard/main.cc @@ -0,0 +1,104 @@ +/* + * \brief pcsc-lite test + * \author Christian Prochaska + * \date 2016-09-19 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include +#include + +#include + +int main() +{ + LONG rv; + + SCARDCONTEXT hContext; + + LPTSTR mszReaders; + DWORD dwReaders; + + SCARD_READERSTATE state; + + SCARDHANDLE hCard; + DWORD dwActiveProtocol; + + SCARD_IO_REQUEST pioSendPci; + + /* SELECT FILE 0x3F00 */ + BYTE cmd[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 }; + + BYTE pbRecvBuffer[256]; + DWORD dwRecvLength; + + rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + + printf("SCardEstablishContext: 0x%lx\n", rv); + + dwReaders = SCARD_AUTOALLOCATE; + rv = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders); + + printf("SCardListreaders: 0x%lx, %lu, %s\n", rv, dwReaders, mszReaders); + + memset(&state, 0, sizeof state); + state.szReader = mszReaders; + rv = SCardGetStatusChange(hContext, 0, &state, 1); + + printf("SCardGetStatusChange(): 0x%lx, %lx\n", rv, state.dwEventState); + + while (state.dwEventState & SCARD_STATE_EMPTY) { + + state.dwCurrentState = state.dwEventState; + + rv = SCardGetStatusChange(hContext, INFINITE, &state, 1); + + printf("SCardGetStatusChange(): 0x%lx, %lx\n", rv, state.dwEventState); + } + + rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + + printf("SCardConnect: 0x%lx, %lu\n", rv, dwActiveProtocol); + + switch (dwActiveProtocol) { + case SCARD_PROTOCOL_T0: + printf("Protocol: T0\n"); + pioSendPci = *SCARD_PCI_T0; + break; + case SCARD_PROTOCOL_T1: + printf("Protocol: T1\n"); + pioSendPci = *SCARD_PCI_T1; + break; + } + + dwRecvLength = sizeof(pbRecvBuffer); + + rv = SCardTransmit(hCard, &pioSendPci, cmd, sizeof(cmd), NULL, pbRecvBuffer, &dwRecvLength); + + printf("SCardTransmit: 0x%lx\n", rv); + + printf("Response: "); + for (unsigned int i=0; i < dwRecvLength; i++) + printf("%02X ", pbRecvBuffer[i]); + printf("\n"); + + rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD); + + printf("SCardDisconnect: 0x%lx\n", rv); + + rv = SCardFreeMemory(hContext, mszReaders); + + printf("SCardFreeMemory: 0x%lx\n", rv); + + rv = SCardReleaseContext(hContext); + + printf("SCardReleaseContext: 0x%lx\n", rv); + + return 0; +} diff --git a/repos/libports/src/test/smartcard/target.mk b/repos/libports/src/test/smartcard/target.mk new file mode 100644 index 000000000..bc161a7ad --- /dev/null +++ b/repos/libports/src/test/smartcard/target.mk @@ -0,0 +1,5 @@ +TARGET = test-smartcard +LIBS = pcsc-lite libc +SRC_CC = main.cc + +vpath main.cc $(PRG_DIR)/.. diff --git a/tool/autopilot.list b/tool/autopilot.list index a306a2d6b..d3faabfc9 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -72,3 +72,4 @@ fs_log cpu_sampler cpu_sampler_noux usb_hid +smartcard