libports: add pcsc-lite library

Fixes #2145
This commit is contained in:
Christian Prochaska 2016-10-20 15:47:19 +02:00 committed by Christian Helmuth
parent 9ed69d8b47
commit 9d84541e6f
12 changed files with 1405 additions and 0 deletions

View File

@ -0,0 +1 @@
INC_DIR += $(call select_from_ports,pcsc-lite)/include/PCSC

View File

@ -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

View File

@ -0,0 +1 @@
e32624a4145b75f8a2aebe55418fa2fb510faf4b

View File

@ -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

View File

@ -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 {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>}
append_if [have_spec gpio] config {
<start name="gpio_drv">
<resource name="RAM" quantum="4M"/>
<provides><service name="Gpio"/></provides>
<config/>
</start>}
append_platform_drv_config
append config {
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="usb_drv">
<resource name="RAM" quantum="16M"/>
<provides><service name="Usb"/></provides>
<config uhci="yes" ehci="yes" xhci="yes" bios_handoff="no">
<raw>
<policy label="test-smartcard -> usb_device" vendor_id="0x04e6" product_id="0x5116"/>
</raw>
</config>
</start>
<start name="test-smartcard">
<resource name="RAM" quantum="4M"/>
<config>
<libc stdout="/dev/log" stderr="/dev/log">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="ifd-ccid.bundle">
<dir name="Contents">
<rom name="Info.plist"/>
</dir>
</dir>
<inline name="config.pcsc-lite">
<config vendor_id="0x04e6" product_id="0x5116"/>
</inline>
</vfs>
</libc>
</config>
</start>
</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

View File

@ -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':
<config>
<libc>
<vfs>
<inline name="config.pcsc-lite">
<config vendor_id="0xXXXX" product_id="0xXXXX"/>
</inline>
</vfs>
</libc>
</config>

View File

@ -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 <alloca.h> and it should be used (not on Ultrix).
*/
/* #undef HAVE_ALLOCA_H */
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#define HAVE_DIRENT_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <dl.h> 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 <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <getopt.h> 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 <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Libudev is available */
/* #undef HAVE_LIBUDEV */
/* Define to 1 if you have the <libudev.h> header file. */
/* #undef HAVE_LIBUDEV_H */
/* Libusb is available */
/* #undef HAVE_LIBUSB */
/* Define to 1 if you have the <libusb.h> header file. */
/* #undef HAVE_LIBUSB_H */
/* Define to 1 if you have the <memory.h> 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 <ndir.h> 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 <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> 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 <syslog.h> header file. */
#define HAVE_SYSLOG_H 1
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_DIR_H */
/* Define to 1 if you have the <sys/filio.h> header file. */
/* #undef HAVE_SYS_FILIO_H */
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_NDIR_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#define HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <unistd.h> 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 <sys/time.h> and <time.h>. */
#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 <sys/types.h> 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 <sys/types.h> does not define. */
/* #undef size_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */

View File

@ -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 <base/log.h>
#include <util/xml_node.h>
/* libc includes */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* pcsc-lite includes */
extern "C" {
#include <debuglog.h>
#include <readerfactory.h>
}
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;
}

View File

@ -0,0 +1,760 @@
pcsc-lite.patch
From: Christian Prochaska <christian.prochaska@genode-labs.com>
---
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 <sys/time.h>
#include <pthread.h>
#include <sys/wait.h>
+#include <stdio.h>
#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(&currentContextMap->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(&currentContextMap->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(&currentContextMap->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(&currentContextMap->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(&currentContextMap->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
}
-

View File

@ -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 <stdio.h>
#include <string.h>
#include <winscard.h>
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;
}

View File

@ -0,0 +1,5 @@
TARGET = test-smartcard
LIBS = pcsc-lite libc
SRC_CC = main.cc
vpath main.cc $(PRG_DIR)/..

View File

@ -72,3 +72,4 @@ fs_log
cpu_sampler
cpu_sampler_noux
usb_hid
smartcard