diff --git a/ccid/Doxyfile b/ccid/Doxyfile
new file mode 100644
index 0000000..8e1c660
--- /dev/null
+++ b/ccid/Doxyfile
@@ -0,0 +1,23 @@
+PROJECT_NAME = $(PROJECT)
+PROJECT_NUMBER = $(VERSION)
+OUTPUT_DIRECTORY = $(DOCDIR)
+STRIP_FROM_INC_PATH = $(SRCDIR)/src
+STRIP_FROM_PATH = $(SRCDIR)/src
+INPUT = $(SRCDIR)/src
+FILE_PATTERNS = *.c *.h
+RECURSIVE = YES
+EXAMPLE_PATH = $(SRCDIR)/src
+GENERATE_HTML = $(GENERATE_HTML)
+GENERATE_HTMLHELP = $(GENERATE_CHM)
+CHM_FILE = ../$(PROJECT).chm
+HHC_LOCATION = $(HHC_PATH)
+GENERATE_CHI = $(GENERATE_CHI)
+GENERATE_LATEX = $(GENERATE_LATEX)
+PAPER_TYPE = $(PAPER_SIZE)
+GENERATE_RTF = $(GENERATE_RTF)
+GENERATE_MAN = $(GENERATE_MAN)
+GENERATE_XML = $(GENERATE_XML)
+GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
+PERL_PATH = $(PERL_PATH)
+HAVE_DOT = $(HAVE_DOT)
+DOT_PATH = $(DOT_PATH)
diff --git a/ccid/Makefile.am b/ccid/Makefile.am
index ad27830..7bcdc3d 100644
--- a/ccid/Makefile.am
+++ b/ccid/Makefile.am
@@ -1,6 +1,12 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src m4 patches
+include doxygen.am
+
+MOSTLYCLEANFILES = $(DX_CLEANFILES)
+
+EXTRA_DIST = $(DX_CONFIG)
+
if WITH_PACE
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libpace.pc
diff --git a/ccid/configure.ac b/ccid/configure.ac
index ad16051..d50be97 100644
--- a/ccid/configure.ac
+++ b/ccid/configure.ac
@@ -133,6 +133,17 @@ fi
AM_CONDITIONAL(WITH_CATS, test "${enable_ccid}" != "no")
+DX_HTML_FEATURE(ON)
+DX_CHM_FEATURE(OFF)
+DX_CHI_FEATURE(OFF)
+DX_MAN_FEATURE(ON)
+DX_RTF_FEATURE(OFF)
+DX_XML_FEATURE(OFF)
+DX_PDF_FEATURE(OFF)
+DX_PS_FEATURE(OFF)
+DX_INIT_DOXYGEN(ccid-emulator, Doxyfile, doc)
+
+
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h fcntl.h memory.h stdint.h stdlib.h string.h sys/ioctl.h unistd.h])
diff --git a/ccid/doxygen.am b/ccid/doxygen.am
new file mode 100644
index 0000000..420049e
--- /dev/null
+++ b/ccid/doxygen.am
@@ -0,0 +1,186 @@
+# Copyright (C) 2004 Oren Ben-Kiki
+# This file is distributed under the same terms as the Automake macro files.
+
+# Generate automatic documentation using Doxygen. Goals and variables values
+# are controlled by the various DX_COND_??? conditionals set by autoconf.
+#
+# The provided goals are:
+# doxygen-doc: Generate all doxygen documentation.
+# doxygen-run: Run doxygen, which will generate some of the documentation
+# (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
+# processing required for the rest of it (PS, PDF, and some MAN).
+# doxygen-man: Rename some doxygen generated man pages.
+# doxygen-ps: Generate doxygen PostScript documentation.
+# doxygen-pdf: Generate doxygen PDF documentation.
+#
+# Note that by default these are not integrated into the automake goals. If
+# doxygen is used to generate man pages, you can achieve this integration by
+# setting man3_MANS to the list of man pages generated and then adding the
+# dependency:
+#
+# $(man3_MANS): doxygen-doc
+#
+# This will cause make to run doxygen and generate all the documentation.
+#
+# The following variable is intended for use in Makefile.am:
+#
+# DX_CLEANFILES = everything to clean.
+#
+# This is usually added to MOSTLYCLEANFILES.
+
+## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+if DX_COND_doc
+
+## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+if DX_COND_html
+
+DX_CLEAN_HTML = @DX_DOCDIR@/html
+
+endif DX_COND_html
+
+## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+if DX_COND_chm
+
+DX_CLEAN_CHM = @DX_DOCDIR@/chm
+
+if DX_COND_chi
+
+DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
+
+endif DX_COND_chi
+
+endif DX_COND_chm
+
+## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+if DX_COND_man
+
+DX_CLEAN_MAN = @DX_DOCDIR@/man
+
+endif DX_COND_man
+
+## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+if DX_COND_rtf
+
+DX_CLEAN_RTF = @DX_DOCDIR@/rtf
+
+endif DX_COND_rtf
+
+## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+if DX_COND_xml
+
+DX_CLEAN_XML = @DX_DOCDIR@/xml
+
+endif DX_COND_xml
+
+## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+if DX_COND_ps
+
+DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
+
+@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_LATEX) refman.tex; \
+ $(MAKEINDEX_PATH) refman.idx; \
+ $(DX_LATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_LATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
+
+endif DX_COND_ps
+
+## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+if DX_COND_pdf
+
+DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
+
+@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_PDFLATEX) refman.tex; \
+ $(DX_MAKEINDEX) refman.idx; \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ mv refman.pdf ../@PACKAGE@.pdf
+
+endif DX_COND_pdf
+
+## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+if DX_COND_latex
+
+DX_CLEAN_LATEX = @DX_DOCDIR@/latex
+
+endif DX_COND_latex
+
+.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
+
+doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
+ rm -rf @DX_DOCDIR@
+ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
+
+DX_CLEANFILES = \
+ @DX_DOCDIR@/@PACKAGE@.tag \
+ -r \
+ $(DX_CLEAN_HTML) \
+ $(DX_CLEAN_CHM) \
+ $(DX_CLEAN_CHI) \
+ $(DX_CLEAN_MAN) \
+ $(DX_CLEAN_RTF) \
+ $(DX_CLEAN_XML) \
+ $(DX_CLEAN_PS) \
+ $(DX_CLEAN_PDF) \
+ $(DX_CLEAN_LATEX)
+
+endif DX_COND_doc
diff --git a/ccid/m4/doxygen.m4 b/ccid/m4/doxygen.m4
new file mode 100644
index 0000000..e9c56c2
--- /dev/null
+++ b/ccid/m4/doxygen.m4
@@ -0,0 +1,312 @@
+# This file is part of Autoconf. -*- Autoconf -*-
+
+# Copyright (C) 2004 Oren Ben-Kiki
+# This file is distributed under the same terms as the Autoconf macro files.
+
+# Generate automatic documentation using Doxygen. Works in concert with the
+# aminclude.m4 file and a compatible doxygen configuration file. Defines the
+# following public macros:
+#
+# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature.
+# Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics,
+# 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI'
+# for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',
+# 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment
+# variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide'
+# paper size.
+#
+# By default, HTML, PDF and PS documentation is generated as this seems to be
+# the most popular and portable combination. MAN pages created by Doxygen are
+# usually problematic, though by picking an appropriate subset and doing some
+# massaging they might be better than nothing. CHM and RTF are specific for MS
+# (note that you can't generate both HTML and CHM at the same time). The XML is
+# rather useless unless you apply specialized post-processing to it.
+#
+# The macro mainly controls the default state of the feature. The use can
+# override the default by specifying --enable or --disable. The macros ensure
+# that contradictory flags are not given (e.g., --enable-doxygen-html and
+# --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.)
+# Finally, each feature will be automatically disabled (with a warning) if the
+# required programs are missing.
+#
+# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with
+# the following parameters: a one-word name for the project for use as a
+# filename base etc., an optional configuration file name (the default is
+# 'Doxyfile', the same as Doxygen's default), and an optional output directory
+# name (the default is 'doxygen-doc').
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc], ON)
+AC_DEFUN([DX_FEATURE_dot], ON)
+AC_DEFUN([DX_FEATURE_man], OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm], OFF)
+AC_DEFUN([DX_FEATURE_chi], OFF)
+AC_DEFUN([DX_FEATURE_rtf], OFF)
+AC_DEFUN([DX_FEATURE_xml], OFF)
+AC_DEFUN([DX_FEATURE_pdf], ON)
+AC_DEFUN([DX_FEATURE_ps], ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
+AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+ [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
+ AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+ AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+ requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+# CHECK_DEPEND, CLEAR_DEPEND,
+# REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+ AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+ AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+ AC_ARG_ENABLE(doxygen-$1,
+ [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+ [--enable-doxygen-$1]),
+ DX_IF_FEATURE([$1], [don't $2], [$2]))],
+ [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+ AC_SUBST([DX_FLAG_$1], 1)
+ $3
+;; #(
+n|N|no|No|NO)
+ AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+ AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+ $5
+ :
+fi
+if DX_TEST_FEATURE([$1]); then
+ AM_CONDITIONAL(DX_COND_$1, :)
+ $6
+ :
+else
+ AM_CONDITIONAL(DX_COND_$1, false)
+ $7
+ :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
+AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
+AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
+AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
+AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
+AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
+# ---------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
+AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+ [],
+ [],
+ [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+ DX_REQUIRE_PROG([DX_PERL], perl)],
+ [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_DOT], dot)],
+ [DX_ENV_APPEND(HAVE_DOT, YES)
+ DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+ [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_MAN, YES)],
+ [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_RTF, YES)],
+ [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_XML, YES)],
+ [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_HHC], hhc)],
+ [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+ DX_ENV_APPEND(GENERATE_HTML, YES)
+ DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+ [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Seperate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
+ [DX_CHECK_DEPEND(chm, 1)],
+ [DX_CLEAR_DEPEND(chm, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_CHI, YES)],
+ [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+ [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+ [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+ [],
+ [DX_ENV_APPEND(GENERATE_HTML, YES)],
+ [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_LATEX], latex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_DVIPS], dvips)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+ AM_CONDITIONAL(DX_COND_latex, :)
+ DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+ AM_CONDITIONAL(DX_COND_latex, false)
+ DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+ [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+ AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+ DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+ AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
diff --git a/ccid/src/ccid.h b/ccid/src/ccid.h
index 164786b..23ec15b 100644
--- a/ccid/src/ccid.h
+++ b/ccid/src/ccid.h
@@ -16,6 +16,9 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
+/**
+ * @file
+ */
#ifndef _CCID_H
#define _CCID_H
@@ -32,36 +35,36 @@ extern "C" {
#define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x02
#define CCID_CONTROL_GET_DATA_RATES 0x03
-#define CCID_BERROR_CMD_ABORTED 0xff /* Host aborted the current activity */
-#define CCID_BERROR_ICC_MUTE 0xfe /* CCID timed out while talking to the ICC */
-#define CCID_BERROR_XFR_PARITY_ERROR 0xfd /* Parity error while talking to the ICC */
-#define CCID_BERROR_XFR_OVERRUN 0xfc /* Overrun error while talking to the ICC */
-#define CCID_BERROR_HW_ERROR 0xfb /* An all inclusive hardware error occurred */
+#define CCID_BERROR_CMD_ABORTED 0xff /** Host aborted the current activity */
+#define CCID_BERROR_ICC_MUTE 0xfe /** CCID timed out while talking to the ICC */
+#define CCID_BERROR_XFR_PARITY_ERROR 0xfd /** Parity error while talking to the ICC */
+#define CCID_BERROR_XFR_OVERRUN 0xfc /** Overrun error while talking to the ICC */
+#define CCID_BERROR_HW_ERROR 0xfb /** An all inclusive hardware error occurred */
#define CCID_BERROR_BAD_ATR_TS 0xf
#define CCID_BERROR_BAD_ATR_TCK 0xf
#define CCID_BERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xf6
#define CCID_BERROR_ICC_CLASS_NOT_SUPPORTED 0xf5
#define CCID_BERROR_PROCEDURE_BYTE_CONFLICT 0xf4
#define CCID_BERROR_DEACTIVATED_PROTOCOL 0xf3
-#define CCID_BERROR_BUSY_WITH_AUTO_SEQUENCE 0xf2 /* Automatic Sequence Ongoing */
+#define CCID_BERROR_BUSY_WITH_AUTO_SEQUENCE 0xf2 /** Automatic Sequence Ongoing */
#define CCID_BERROR_PIN_TIMEOUT 0xf0
#define CCID_BERROR_PIN_CANCELLED 0xef
-#define CCID_BERROR_CMD_SLOT_BUSY 0xe0 /* A second command was sent to a slot which was already processing a command. */
+#define CCID_BERROR_CMD_SLOT_BUSY 0xe0 /** A second command was sent to a slot which was already processing a command. */
#define CCID_BERROR_CMD_NOT_SUPPORTED 0x00
#define CCID_BERROR_OK 0x00
-#define CCID_BSTATUS_OK_ACTIVE 0x00 /* No error. An ICC is present and active */
-#define CCID_BSTATUS_OK_INACTIVE 0x01 /* No error. ICC is present and inactive */
-#define CCID_BSTATUS_OK_NOICC 0x02 /* No error. No ICC is present */
-#define CCID_BSTATUS_ERROR_ACTIVE 0x40 /* Failed. An ICC is present and active */
-#define CCID_BSTATUS_ERROR_INACTIVE 0x41 /* Failed. ICC is present and inactive */
-#define CCID_BSTATUS_ERROR_NOICC 0x42 /* Failed. No ICC is present */
+#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */
+#define CCID_BSTATUS_OK_INACTIVE 0x01 /** No error. ICC is present and inactive */
+#define CCID_BSTATUS_OK_NOICC 0x02 /** No error. No ICC is present */
+#define CCID_BSTATUS_ERROR_ACTIVE 0x40 /** Failed. An ICC is present and active */
+#define CCID_BSTATUS_ERROR_INACTIVE 0x41 /** Failed. ICC is present and inactive */
+#define CCID_BSTATUS_ERROR_NOICC 0x42 /** Failed. No ICC is present */
-#define CCID_WLEVEL_DIRECT __constant_cpu_to_le16(0) /* APDU begins and ends with this command */
-#define CCID_WLEVEL_CHAIN_NEXT_XFRBLOCK __constant_cpu_to_le16(1) /* APDU begins with this command, and continue in the next PC_to_RDR_XfrBlock */
-#define CCID_WLEVEL_CHAIN_END __constant_cpu_to_le16(2) /* abData field continues a command APDU and ends the APDU command */
-#define CCID_WLEVEL_CHAIN_CONTINUE __constant_cpu_to_le16(3) /* abData field continues a command APDU and another block is to follow */
-#define CCID_WLEVEL_RESPONSE_IN_DATABLOCK __constant_cpu_to_le16(0x10) /* empty abData field, continuation of response APDU is expected in the next RDR_to_PC_DataBlock */
+#define CCID_WLEVEL_DIRECT __constant_cpu_to_le16(0) /** APDU begins and ends with this command */
+#define CCID_WLEVEL_CHAIN_NEXT_XFRBLOCK __constant_cpu_to_le16(1) /** APDU begins with this command, and continue in the next PC_to_RDR_XfrBlock */
+#define CCID_WLEVEL_CHAIN_END __constant_cpu_to_le16(2) /** abData field continues a command APDU and ends the APDU command */
+#define CCID_WLEVEL_CHAIN_CONTINUE __constant_cpu_to_le16(3) /** abData field continues a command APDU and another block is to follow */
+#define CCID_WLEVEL_RESPONSE_IN_DATABLOCK __constant_cpu_to_le16(0x10) /** empty abData field, continuation of response APDU is expected in the next RDR_to_PC_DataBlock */
#define CCID_PIN_ENCODING_BIN 0x00
#define CCID_PIN_ENCODING_BCD 0x01
@@ -275,7 +278,7 @@ struct hid_class_descriptor {
* @param[in] cdriver Card driver to be used (optional)
* @param[in] verbose Verbosity level passed to \c sc_context_t
*
- * @return \c SC_SUCCESS or error code if an error occurred
+ * @return \c SC_SUCCESS or error code if an error occurred
*/
int ccid_initialize(int reader_id, const char *cdriver, int verbose);
@@ -293,7 +296,7 @@ void ccid_shutdown();
*
* @param[in] inbuf input buffer (command pipe bulk-OUT message)
* @param[in] inlen length of \a inbuf
- * @param[in,out] outbuf where to save the output buffer (resoponse pipe bulk-IN message), memory is reused via realloc()
+ * @param[in,out] outbuf where to save the output buffer (resoponse pipe bulk-IN message), memory is reused via \c realloc()
*
* @return length of \a outbuf or -1 if an error occurred
*/
@@ -305,7 +308,7 @@ int ccid_parse_bulkout(const __u8* inbuf, size_t inlen, __u8** outbuf);
* Parses CCID class-specific requests according to CCID Rev 1.1 section 5.3
*
* @param[in] setup input from control pipe
- * @param[in,out] outbuf where to save the output buffer, memory is reused via realloc()
+ * @param[in,out] outbuf where to save the output buffer, memory is reused via \c realloc()
*
* @return length of \a outbuf or -1 if an error occurred
*/
@@ -316,7 +319,7 @@ int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf);
*
* @param[in,out] slotchange where to save the output
* @param[in] timeout currently not used
- * @note ccid_state_changed() must be called periodically. Because the OpenSC implementation of sc_wait_for_event() blocks all other operations with the reader, it can't be used for slot state detection.
+ * @note ccid_state_changed() must be called periodically. Because the OpenSC implementation of \c sc_wait_for_event() blocks all other operations with the reader, it can't be used for slot state detection.
*
* @return 1 if a card is present and/or the state is changed or 0
*/
diff --git a/ccid/src/pace/pace.h b/ccid/src/pace/pace.h
index 3485ac0..fa080e7 100644
--- a/ccid/src/pace/pace.h
+++ b/ccid/src/pace/pace.h
@@ -16,6 +16,9 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
+/**
+ * @file
+ */
#ifndef _CCID_PACE_H
#define _CCID_PACE_H
@@ -67,19 +70,32 @@ extern "C" {
const char *pace_secret_name(enum s_type pin_id);
+/**
+ * Input data for EstablishPACEChannel()
+ */
struct establish_pace_channel_input {
+ /** Type of secret. You may use enum s_type from \c */
unsigned char pin_id;
+ /** Length of card holder authorization template */
size_t chat_length;
+ /** Card holder authorization template */
const unsigned char *chat;
+ /** Length of secret */
size_t pin_length;
+ /** Secret */
const unsigned char *pin;
+ /** Length of certificate description */
size_t certificate_description_length;
+ /** Certificate description */
const unsigned char *certificate_description;
};
+/**
+ * Output data for EstablishPACEChannel()
+ */
struct establish_pace_channel_output {
unsigned int result;
diff --git a/ccid/src/pace/pace_lib.h b/ccid/src/pace/pace_lib.h
index 5b33eec..253a03c 100644
--- a/ccid/src/pace/pace_lib.h
+++ b/ccid/src/pace/pace_lib.h
@@ -16,6 +16,9 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
+/**
+ * @file
+ */
#ifndef _CCID_PACE_LIB_H
#define _CCID_PACE_LIB_H
@@ -25,17 +28,47 @@
extern "C" {
#endif
+/** PACE secure messaging context */
struct pace_sm_ctx {
+ /** Send sequence counter */
BIGNUM *ssc;
+ /** Key for message authentication code */
const BUF_MEM *key_mac;
+ /** Key for encryption and decryption */
const BUF_MEM *key_enc;
+ /** PACE context */
PACE_CTX *ctx;
};
+/**
+ * @brief Creates a PACE SM object
+ *
+ * @param[in] key_mac Key for message authentication code
+ * @param[in] key_enc Key for encryption and decryption
+ * @param[in] ctx PACE context
+ *
+ * @return Initialized PACE SM object or NULL, if an error occurred
+ */
struct pace_sm_ctx * pace_sm_ctx_create(const BUF_MEM *key_mac,
const BUF_MEM *key_enc, PACE_CTX *ctx);
+
+/**
+ * @brief Frees a PACE SM object
+ *
+ * Frees memory allocated for \a ctx and its send sequence counter
+ *
+ * @param[in] ctx object to be freed
+ */
void pace_sm_ctx_free(struct pace_sm_ctx *ctx);
+
+/**
+ * @brief Frees a PACE SM object and all its components
+ *
+ * Frees memory allocated for \a ctx and its send sequence counter, keys and PACE context
+ *
+ * @param[in] ctx object to be freed
+ */
void pace_sm_ctx_clear_free(struct pace_sm_ctx *ctx);
#ifdef __cplusplus
diff --git a/ccid/src/pace/scutil.h b/ccid/src/pace/scutil.h
index 3306dee..b01b34f 100644
--- a/ccid/src/pace/scutil.h
+++ b/ccid/src/pace/scutil.h
@@ -16,23 +16,77 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
+/**
+ * @file
+ */
#ifndef _CCID_SCUTIL_H
#define _CCID_SCUTIL_H
#include
+/**
+ * @brief Initializes smart card context and reader
+ *
+ * @param[in] reader_id Index to the reader to be used (optional). Set to -1 to use a reader with a inserted card.
+ * @param[in] cdriver Card driver to be used (optional)
+ * @param[in] verbose verbosity level passed to \c sc_context_t
+ * @param[in,out] ctx Where to write the sc context
+ * @param[in,out] reader Where to write the reader context
+ *
+ * @return
+ */
int initialize(int reader_id, const char *cdriver, int verbose,
sc_context_t **ctx, sc_reader_t **reader);
+/**
+ * @brief Parse an APDU buffer
+ *
+ * @param[in] ctx sc context
+ * @param[in] buf Buffer of APDU
+ * @param[in] len Length of \a buf
+ * @param [in,out] apdu Where to write the initialized APDU
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
+ */
int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu);
+/**
+ * @brief Print binary data to a file stream
+ *
+ * @param[in] file File for printing
+ * @param[in] label Label to prepend to the buffer
+ * @param[in] data Binary data
+ * @param[in] len Length of \a data
+ */
#define bin_print(file, label, data, len) \
_bin_log(NULL, 0, NULL, 0, NULL, label, data, len, file)
+/**
+ * @brief Log binary data to a sc context
+ *
+ * @param[in] ctx Context for logging
+ * @param[in] label Label to prepend to the buffer
+ * @param[in] data Binary data
+ * @param[in] len Length of \a data
+ */
#define bin_log(ctx, label, data, len) \
_bin_log(ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, label, data, len, NULL)
+/**
+ * @brief Log binary data
+ *
+ * Either choose \a ctx or \a file for logging
+ *
+ * @param[in] ctx (optional) Context for logging
+ * @param[in] type Debug level
+ * @param[in] file File name to be prepended
+ * @param[in] line Line to be prepended
+ * @param[in] func Function to be prepended
+ * @param[in] label label to prepend to the buffer
+ * @param[in] data binary data
+ * @param[in] len length of \a data
+ * @param[in] f (optional) File for printing
+ */
void _bin_log(sc_context_t *ctx, int type, const char *file, int line,
const char *func, const char *label, const u8 *data, size_t len,
FILE *f);
#endif
-
diff --git a/ccid/src/pace/sm.h b/ccid/src/pace/sm.h
index 98db359..4b2f0d3 100644
--- a/ccid/src/pace/sm.h
+++ b/ccid/src/pace/sm.h
@@ -16,6 +16,9 @@
* You should have received a copy of the GNU General Public License along with
* ccid. If not, see .
*/
+/**
+ * @file
+ */
#ifndef _CCID_SM_H
#define _CCID_SM_H
@@ -40,25 +43,52 @@ struct sm_ctx {
/** Pad to this block length */
size_t block_length;
+ /** Authentication context for the specific authentication implementation */
void *authentication_ctx;
+ /** Call back function for authentication of data */
int (*authenticate)(sc_card_t *card, const struct sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **outdata);
+ /** Call back function for verifying authentication data */
int (*verify_authentication)(sc_card_t *card, const struct sm_ctx *ctx,
const u8 *mac, size_t maclen,
const u8 *macdata, size_t macdatalen);
+ /** Cipher context for the specific cipher implementation */
void *cipher_ctx;
+ /** Call back function for encryption of data */
int (*encrypt)(sc_card_t *card, const struct sm_ctx *ctx,
const u8 *data, size_t datalen, u8 **enc);
+ /** Call back function for decryption of data */
int (*decrypt)(sc_card_t *card, const struct sm_ctx *ctx,
const u8 *enc, size_t enclen, u8 **data);
+ /** Call back function for actions before encoding and encryption of \a apdu */
int (*pre_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *apdu);
+ /** Call back function for actions before decryption and decoding of \a sm_apdu */
int (*post_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *sm_apdu);
};
+/**
+ * @brief Secure messaging wrapper for sc_transmit_apdu()
+ *
+ * If secure messaging (SM) is activated in \a sctx and \a apdu is not already
+ * SM protected, \a apdu is processed with the following steps:
+ * \li call to \a sctx->pre_transmit
+ * \li encrypt \a apdu calling \a sctx->encrypt
+ * \li authenticate \a apdu calling \a sctx->authenticate
+ * \li transmit SM protected \a apdu
+ * \li verify SM protected \a apdu calling \a sctx->verify_authentication
+ * \li decrypt SM protected \a apdu calling \a sctx->decrypt
+ * \li copy decrypted/authenticated data and status bytes to \a apdu
+ *
+ * @param[in] sctx
+ * @param[in] card
+ * @param[in,out] apdu
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
+ */
int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
sc_apdu_t *apdu);
diff --git a/ccid/src/sm.c b/ccid/src/sm.c
index 2c2a65e..0f046da 100644
--- a/ccid/src/sm.c
+++ b/ccid/src/sm.c
@@ -564,8 +564,6 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
apdu->resp, apdu->resplen);
}
- /* XXX verify mac */
-
r = SC_SUCCESS;
err: