diff --git a/configure.ac b/configure.ac
index 9c2eadc..3812a36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,8 @@ if test x$ac_cv_with_cutter = xyes -a x$ac_cv_use_cutter = xno; then
fi
AM_CONDITIONAL([WITH_CUTTER], [test "$ac_cv_use_cutter" != "no"])
+PKG_CHECK_MODULES(PCSC, libpcsclite)
+
m4_ifdef([AC_CHECK_COVERAGE], [AC_CHECK_COVERAGE])
if test x$cutter_enable_coverage = xyes; then
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 565171e..7ae574e 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,7 +1,7 @@
# $Id$
-AM_CFLAGS = -I. -I$(top_srcdir)/libfreefare @LIBNFC_CFLAGS@
-AM_LDFLAGS = @LIBNFC_LIBS@
+AM_CFLAGS = -I. -I$(top_srcdir)/libfreefare @LIBNFC_CFLAGS@ @PCSC_CFLAGS@
+AM_LDFLAGS = @LIBNFC_LIBS@ @PCSC_LIBS@
bin_PROGRAMS = mifare-classic-format \
mifare-classic-write-ndef \
@@ -13,9 +13,11 @@ bin_PROGRAMS = mifare-classic-format \
mifare-desfire-ev1-configure-random-uid \
mifare-desfire-format \
mifare-desfire-info \
+ mifare-desfire-info-pcsc \
mifare-desfire-read-ndef \
mifare-desfire-write-ndef \
- mifare-ultralight-info
+ mifare-ultralight-info \
+ mifare-ultralight-info-pcsc
mifare_classic_format_SOURCES = mifare-classic-format.c
mifare_classic_format_LDADD = $(top_builddir)/libfreefare/libfreefare.la
@@ -47,6 +49,9 @@ mifare_desfire_format_LDADD = $(top_builddir)/libfreefare/libfreefare.la
mifare_desfire_info_SOURCES = mifare-desfire-info.c
mifare_desfire_info_LDADD = $(top_builddir)/libfreefare/libfreefare.la -lm
+mifare_desfire_info_pcsc_SOURCES = mifare-desfire-info-pcsc.c
+mifare_desfire_info_pcsc_LDADD = $(top_builddir)/libfreefare/libfreefare.la -lm
+
mifare_desfire_read_ndef_SOURCES = mifare-desfire-read-ndef.c
mifare_desfire_read_ndef_LDADD = $(top_builddir)/libfreefare/libfreefare.la
@@ -56,4 +61,7 @@ mifare_desfire_write_ndef_LDADD = $(top_builddir)/libfreefare/libfreefare.la
mifare_ultralight_info_SOURCES = mifare-ultralight-info.c
mifare_ultralight_info_LDADD = $(top_builddir)/libfreefare/libfreefare.la
+mifare_ultralight_info_pcsc_SOURCES = mifare-ultralight-info-pcsc.c
+mifare_ultralight_info_pcsc_LDADD = $(top_builddir)/libfreefare/libfreefare.la
+
CLEANFILES= *.gcno
diff --git a/examples/mifare-desfire-info-pcsc b/examples/mifare-desfire-info-pcsc
new file mode 100755
index 0000000..42cad65
--- /dev/null
+++ b/examples/mifare-desfire-info-pcsc
@@ -0,0 +1,228 @@
+#! /bin/sh
+
+# mifare-desfire-info-pcsc - temporary wrapper script for .libs/mifare-desfire-info-pcsc
+# Generated by libtool (GNU libtool) 2.4.2
+#
+# The mifare-desfire-info-pcsc program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/libfreefare-pcsc/libfreefare/examples; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/vendor_perl:/usr/bin/core_perl; export PATH; gcc -I. -I../libfreefare -pthread -I/home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/build/include -I/usr/include/libusb-1.0 -I/usr/include/PCSC -g -O2 -std=c99 -o \$progdir/\$file mifare-desfire-info-pcsc.o -L/home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/build/lib ../libfreefare/.libs/libfreefare.so /home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/build/lib/libnfc.so -lusb -lpcsclite -lm -lcrypto -pthread -Wl,-rpath -Wl,/home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/libfreefare-pcsc/libfreefare/libfreefare/.libs -Wl,-rpath -Wl,/home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/build/lib -Wl,-rpath -Wl,/home/simon/Dropbox/Uni/Semester_5/PASST/RainerSCT/build/lib)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='2.4.2'
+ notinst_deplibs=' ../libfreefare/libfreefare.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set.
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO="printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+ test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+ lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "mifare-desfire-info-pcsc:mifare-desfire-info-pcsc:${LINENO}: libtool wrapper (GNU libtool) 2.4.2" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ $ECHO "mifare-desfire-info-pcsc:mifare-desfire-info-pcsc:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+ lt_dump_args_N=`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "mifare-desfire-info-pcsc:mifare-desfire-info-pcsc:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ case " $* " in
+ *\ --lt-*)
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done ;;
+ esac
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" = "x$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" != "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+ *) thisdir="$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'`
+ file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+ # special case for '.'
+ if test "$thisdir" = "."; then
+ thisdir=`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;;
+ .libs ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir="$absdir"
+
+ program=lt-'mifare-desfire-info-pcsc'
+ progdir="$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /usr/bin/sed 1q`; \
+ test "X$file" != "X$progdir/$program"; }; then
+
+ file="$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/examples/mifare-desfire-info-pcsc.c b/examples/mifare-desfire-info-pcsc.c
new file mode 100644
index 0000000..bb35f6b
--- /dev/null
+++ b/examples/mifare-desfire-info-pcsc.c
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (C) 2010, Romain Tartiere.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ *
+ * $Id$
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+int
+main(int argc, char *argv[])
+{
+ int error = EXIT_SUCCESS;
+
+ struct pcsc_context *context;
+ MifareTag *tags = NULL;
+ char *str = NULL;
+ char *reader = NULL;
+ LONG err;
+
+ if (argc > 1)
+ errx (EXIT_FAILURE, "usage: %s", argv[0]);
+
+ pcsc_init(&context);
+ if (!context)
+ {
+ fprintf(stderr, "unable to init pcsc context\n");
+ exit(EXIT_FAILURE);
+ }
+
+ err = pcsc_list_devices(context, &str);
+ if (err != SCARD_S_SUCCESS)
+ {
+ fprintf(stderr, "no readers found\n");
+ exit(EXIT_FAILURE);
+ }
+
+ size_t device_count = 0;
+ reader = str;
+ while(*reader != '\0')
+ {
+ printf("Reader %s found\n", reader);
+ device_count++;
+ reader += strlen(reader) + 1;
+ }
+
+ reader = str;
+
+ for (size_t d = 0; d < device_count; d++)
+ {
+ tags = freefare_get_tags_pcsc (context, reader);
+ if (!tags) {
+ pcsc_exit(context);
+ errx (EXIT_FAILURE, "Error listing tags.");
+ }
+
+ for (int i = 0; (!error) && tags[i]; i++) {
+ if (DESFIRE != freefare_get_tag_type (tags[i]))
+ continue;
+
+ int res;
+ char *tag_uid = freefare_get_tag_uid (tags[i]);
+
+ struct mifare_desfire_version_info info;
+
+ res = mifare_desfire_connect (tags[i]);
+ if (res < 0) {
+ warnx ("Can't connect to Mifare DESFire target.");
+ error = 1;
+ break;
+ }
+
+ res = mifare_desfire_get_version (tags[i], &info);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_get_version");
+ error = 1;
+ break;
+ }
+
+ printf ("===> Version information for tag %s:\n", tag_uid);
+ printf ("UID: 0x%02x%02x%02x%02x%02x%02x%02x\n", info.uid[0], info.uid[1], info.uid[2], info.uid[3], info.uid[4], info.uid[5], info.uid[6]);
+ printf ("Batch number: 0x%02x%02x%02x%02x%02x\n", info.batch_number[0], info.batch_number[1], info.batch_number[2], info.batch_number[3], info.batch_number[4]);
+ printf ("Production date: week %x, 20%02x\n", info.production_week, info.production_year);
+ printf ("Hardware Information:\n");
+ printf (" Vendor ID: 0x%02x\n", info.hardware.vendor_id);
+ printf (" Type: 0x%02x\n", info.hardware.type);
+ printf (" Subtype: 0x%02x\n", info.hardware.subtype);
+ printf (" Version: %d.%d\n", info.hardware.version_major, info.hardware.version_minor);
+ printf (" Storage size: 0x%02x (%s%d bytes)\n", info.hardware.storage_size, (info.hardware.storage_size & 1) ? ">" : "=", 1 << (info.hardware.storage_size >> 1));
+ printf (" Protocol: 0x%02x\n", info.hardware.protocol);
+ printf ("Software Information:\n");
+ printf (" Vendor ID: 0x%02x\n", info.software.vendor_id);
+ printf (" Type: 0x%02x\n", info.software.type);
+ printf (" Subtype: 0x%02x\n", info.software.subtype);
+ printf (" Version: %d.%d\n", info.software.version_major, info.software.version_minor);
+ printf (" Storage size: 0x%02x (%s%d bytes)\n", info.software.storage_size, (info.software.storage_size & 1) ? ">" : "=", 1 << (info.software.storage_size >> 1));
+ printf (" Protocol: 0x%02x\n", info.software.protocol);
+
+ uint8_t settings;
+ uint8_t max_keys;
+ res = mifare_desfire_get_key_settings (tags[i], &settings, &max_keys);
+ if (res == 0) {
+ printf ("Master Key settings (0x%02x):\n", settings);
+ printf (" 0x%02x configuration changeable;\n", settings & 0x08);
+ printf (" 0x%02x PICC Master Key not required for create / delete;\n", settings & 0x04);
+ printf (" 0x%02x Free directory list access without PICC Master Key;\n", settings & 0x02);
+ printf (" 0x%02x Allow changing the Master Key;\n", settings & 0x01);
+ } else if (AUTHENTICATION_ERROR == mifare_desfire_last_picc_error (tags[i])) {
+ printf ("Master Key settings: LOCKED\n");
+ } else {
+ freefare_perror (tags[i], "mifare_desfire_get_key_settings");
+ error = 1;
+ break;
+ }
+
+ uint8_t version;
+ mifare_desfire_get_key_version (tags[i], 0, &version);
+ printf ("Master Key version: %d (0x%02x)\n", version, version);
+
+ uint32_t size;
+ res = mifare_desfire_free_mem (tags[i], &size);
+ printf ("Free memory: ");
+ if (0 == res) {
+ printf ("%d bytes\n", size);
+ } else {
+ printf ("unknown\n");
+ }
+
+ printf ("Use random UID: %s\n", (strlen (tag_uid) / 2 == 4) ? "yes" : "no");
+
+ free (tag_uid);
+
+ mifare_desfire_disconnect (tags[i]);
+ }
+
+ while(*reader != '\0') // goto next reader for the next loop
+ {
+ reader += strlen(reader) + 1;
+ }
+
+ freefare_free_tags (tags);
+ }
+
+ pcsc_exit(context);
+ exit (error);
+} /* main() */
+
diff --git a/examples/mifare-ultralight-info-pcsc.c b/examples/mifare-ultralight-info-pcsc.c
new file mode 100644
index 0000000..27bfa52
--- /dev/null
+++ b/examples/mifare-ultralight-info-pcsc.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (C) 2012, Romain Tartiere.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ *
+ * $Id$
+ */
+#include
+#include
+#include
+
+#include
+
+#include
+
+int
+main (int argc, char *argv[])
+{
+ int error = EXIT_SUCCESS;
+ MifareTag *tags = NULL;
+
+ struct pcsc_context *context;
+ char *str = NULL;
+ char *reader;
+ long err;
+
+ if (argc > 1)
+ errx (EXIT_FAILURE, "usage: %s", argv[0]);
+
+ pcsc_init(&context);
+ if (context == NULL)
+ errx(EXIT_FAILURE, "Unable to init pcsc (malloc)");
+
+ err = pcsc_list_devices (context, &str);
+ if (err)
+ errx (EXIT_FAILURE, "No pcsc device found");
+
+ for (reader = str; *reader != '\0'; reader += strlen(reader) + 1) {
+ if (!(tags = freefare_get_tags_pcsc(context, reader))) {
+ /* no tags found on this reader */
+ continue;
+ }
+
+ for (int i = 0; (!error) && tags[i]; i++) {
+ switch (freefare_get_tag_type (tags[i])) {
+ case ULTRALIGHT:
+ case ULTRALIGHT_C:
+ break;
+ default:
+ continue;
+ }
+
+ char *tag_uid = freefare_get_tag_uid (tags[i]);
+ printf ("Tag with UID %s is a %s\n", tag_uid, freefare_get_tag_friendly_name (tags[i]));
+ if (freefare_get_tag_type (tags[i]) == ULTRALIGHT_C) {
+ MifareTag tag = tags[i];
+ int res;
+ MifareDESFireKey key;
+ uint8_t key1_3des_data[16] = { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 };
+ key = mifare_desfire_3des_key_new (key1_3des_data);
+ if (mifare_ultralight_connect (tag) < 0)
+ errx (EXIT_FAILURE, "Error connecting to tag.");
+ res = mifare_ultralightc_authenticate (tag, key);
+ printf ("Authentication with default key: %s\n", res ? "fail" : "success");
+ mifare_desfire_key_free (key);
+ mifare_ultralight_disconnect (tag);
+ }
+ free (tag_uid);
+ }
+
+ freefare_free_tags (tags);
+ }
+
+ pcsc_exit (context);
+ exit(error);
+}
diff --git a/libfreefare/Makefile.am b/libfreefare/Makefile.am
index d530df3..f5ddcf0 100644
--- a/libfreefare/Makefile.am
+++ b/libfreefare/Makefile.am
@@ -1,6 +1,6 @@
# $Id$
-AM_CFLAGS = @LIBNFC_CFLAGS@
+AM_CFLAGS = @LIBNFC_CFLAGS@ @PCSC_CFLAGS@
AM_LDFLAGS = @LIBNFC_LIBS@
lib_LTLIBRARIES = libfreefare.la
diff --git a/libfreefare/freefare.c b/libfreefare/freefare.c
index d9ddc4b..b2e8d4e 100644
--- a/libfreefare/freefare.c
+++ b/libfreefare/freefare.c
@@ -21,9 +21,12 @@
#include
#include
-
+#include
+#include
#include "freefare_internal.h"
+#include "freefare_pcsc_tags.h"
+
#define MAX_CANDIDATES 16
#define NXP_MANUFACTURER_CODE 0x04
@@ -96,7 +99,145 @@ freefare_tag_new (nfc_device *device, nfc_iso14443a_info nai)
return tag;
}
-
+MifareTag
+freefare_tag_new_pcsc (struct pcsc_context *context, const char *reader)
+{
+ struct supported_tag *tag_info = NULL;
+ enum mifare_tag_type tagtype;
+ MifareTag tag;
+ bool found = false;
+ LONG l;
+ LPBYTE pbAttr = NULL;
+ DWORD atrlen = SCARD_AUTOALLOCATE;
+ DWORD dwActiveProtocol;
+ SCARDHANDLE hCard;
+ uint8_t buf[] = { 0xFF, 0xCA, 0x00, 0x00, 0x00 };
+ uint8_t ret[12];
+ SCARD_IO_REQUEST ioreq;
+ DWORD retlen;
+
+ l = SCardConnect(context->context, reader, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
+ if(l != SCARD_S_SUCCESS)
+ {
+ return NULL;
+ }
+
+ /* get and card uid */
+ retlen = sizeof(ret);
+ l = SCardTransmit(hCard, SCARD_PCI_T0, buf, sizeof(buf), &ioreq, ret, &retlen);
+ if (l != SCARD_S_SUCCESS)
+ {
+ fprintf(stderr, "freefare_tag_new_pcsc: getting uid failed\n");
+ return NULL;
+ }
+
+ LONG err;
+ err = SCardGetAttrib ( hCard , SCARD_ATTR_ATR_STRING, (LPBYTE) &pbAttr, &atrlen );
+
+ if (err)
+ {
+ printf("SCardGetAttrib: err=%lx %s\n ", err, pcsc_stringify_error(err));
+ return NULL;
+ }
+
+ found = false;
+ for (int i = 0; pcsc_supported_atrs[i].len != 0; i++){
+ if (atrlen != pcsc_supported_atrs[i].len) {
+ continue;
+ }
+ if ( pcsc_supported_atrs[i].mask == NULL ){
+ /* no bitmask here */
+ if ( ! memcmp(pcsc_supported_atrs[i].tag ,pbAttr ,atrlen) ) {
+ tagtype = pcsc_supported_atrs[i].type;
+ found = true;
+ break;
+ }
+ } else {
+ /* bitmask case */
+ int c;
+ for (c = 0; c < pcsc_supported_atrs[i].len; c++){
+ if (pcsc_supported_atrs[i].tag[c] & pcsc_supported_atrs[i].mask[c] == pbAttr[c] & pcsc_supported_atrs[i].mask[c]){
+ break;
+ }
+ }
+ if (c == pcsc_supported_atrs[i].len) {
+ tagtype = pcsc_supported_atrs[i].type;
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ return NULL;
+ }
+ printf("tagtype: %d\n", tagtype);
+
+ found = false;
+
+
+ for (size_t i = 0; i < sizeof (supported_tags) / sizeof (struct supported_tag); i++) {
+ if(supported_tags[i].type == tagtype) {
+ tag_info = &(supported_tags[i]);
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ return NULL;
+
+ char crc = 0x00;
+ for (int crc_count = 1 /*! 1. Byte wird ignoriert*/ ; crc_count < atrlen; crc_count++ )
+ {
+ crc ^= pbAttr[crc_count];
+ }
+ printf("checking \"CRC\": %s (crc=0x%02x)\n", (crc) ? "fail" : "succeed", crc);
+
+ err = SCardFreeMemory (context->context, pbAttr);
+ if (err)
+ {
+ printf("SCardFreeMemory %lx\n", err);
+ }
+
+
+
+ /* Allocate memory for the found MIFARE target */
+ switch (tag_info->type) {
+ case CLASSIC_1K:
+ case CLASSIC_4K:
+ tag = mifare_classic_tag_new ();
+ break;
+ case DESFIRE:
+ tag = mifare_desfire_tag_new ();
+ break;
+ case ULTRALIGHT:
+ case ULTRALIGHT_C:
+ tag = mifare_ultralight_tag_new ();
+ break;
+ }
+
+ if (!tag)
+ return NULL;
+
+ /*
+ * Initialize common fields
+ * (Target specific fields are initialized in mifare_*_tag_new())
+ */
+ memcpy(tag->info.abtUid, ret, retlen - 2);
+ tag->info.szUidLen = retlen - 2;
+ tag->device = NULL;
+ tag->hContext = context->context;
+ tag->hCard = hCard;
+ tag->active = 0;
+ tag->tag_info = tag_info;
+ FILL_SZREADER(tag, reader);
+
+ tag->lastPCSCerror = SCardDisconnect(tag->hCard, SCARD_LEAVE_CARD);
+
+ return tag;
+}
+
/*
* MIFARE card common functions
*
@@ -160,6 +301,35 @@ freefare_get_tags (nfc_device *device)
return tags;
}
+/*
+ * Get a list of the MIFARE targets near to the provided NFC initiator.
+ * (Usally its just one tag, because pcsc can not detect more)
+ * phContext must be established with SCardEstablishContext before
+ * calling this function.
+ * mszReader is the Name of the SmartCard Reader to use
+ * The list has to be freed using the freefare_free_tags() function.
+ */
+MifareTag *
+freefare_get_tags_pcsc (struct pcsc_context *context, const char *reader)
+{
+ MifareTag *tags = NULL;
+
+ tags = malloc(2*sizeof (MifareTag));
+ if(!tags)
+ {
+ fprintf(stderr, "freefare_get_tags_pcsc: malloc failed !!\n");
+ return NULL;
+ }
+ tags[0] = freefare_tag_new_pcsc(context, reader);
+ tags[1] = NULL;
+ if(tags[0] == NULL)
+ return NULL;
+
+
+
+ return tags;
+}
+
/*
* Returns the type of the provided tag.
*/
@@ -184,10 +354,10 @@ freefare_get_tag_friendly_name (MifareTag tag)
char *
freefare_get_tag_uid (MifareTag tag)
{
- char *res = malloc (2 * tag->info.szUidLen + 1);
- for (size_t i =0; i < tag->info.szUidLen; i++)
- snprintf (res + 2*i, 3, "%02x", tag->info.abtUid[i]);
- return res;
+ char *res = malloc (2 * tag->info.szUidLen + 1);
+ for (size_t i =0; i < tag->info.szUidLen; i++)
+ snprintf (res + 2*i, 3, "%02x", tag->info.abtUid[i]);
+ return res;
}
/*
@@ -197,19 +367,21 @@ void
freefare_free_tag (MifareTag tag)
{
if (tag) {
- switch (tag->tag_info->type) {
- case CLASSIC_1K:
- case CLASSIC_4K:
- mifare_classic_tag_free (tag);
- break;
- case DESFIRE:
- mifare_desfire_tag_free (tag);
- break;
- case ULTRALIGHT:
- case ULTRALIGHT_C:
- mifare_ultralight_tag_free (tag);
- break;
+ switch (tag->tag_info->type)
+ {
+ case CLASSIC_1K:
+ case CLASSIC_4K:
+ mifare_classic_tag_free (tag);
+ break;
+ case DESFIRE:
+ mifare_desfire_tag_free (tag);
+ break;
+ case ULTRALIGHT:
+ case ULTRALIGHT_C:
+ mifare_ultralight_tag_free (tag);
+ break;
}
+ FREE_SZREADER(tag->szReader);
}
}
@@ -217,16 +389,23 @@ const char *
freefare_strerror (MifareTag tag)
{
const char *p = "Unknown error";
- if (nfc_device_get_last_error (tag->device) < 0) {
- p = nfc_strerror (tag->device);
- } else {
- if (tag->tag_info->type == DESFIRE) {
- if (MIFARE_DESFIRE (tag)->last_pcd_error) {
- p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_pcd_error);
- } else if (MIFARE_DESFIRE (tag)->last_picc_error) {
- p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_picc_error);
- }
- }
+ if(tag->device != NULL) // we use libnfc
+ {
+ if (nfc_device_get_last_error (tag->device) < 0) {
+ p = nfc_strerror (tag->device);
+ } else {
+ if (tag->tag_info->type == DESFIRE) {
+ if (MIFARE_DESFIRE (tag)->last_pcd_error) {
+ p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_pcd_error);
+ } else if (MIFARE_DESFIRE (tag)->last_picc_error) {
+ p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_picc_error);
+ }
+ }
+ }
+ }
+ else // we use the pcsc protocol
+ {
+ p = (const char*) pcsc_stringify_error(tag->lastPCSCerror);
}
return p;
}
@@ -257,6 +436,60 @@ freefare_free_tags (MifareTag *tags)
}
}
+/*
+ * create context for pcsc readers
+ */
+
+void
+pcsc_init(struct pcsc_context** context)
+{
+ LONG err;
+ struct pcsc_context *con = malloc(sizeof(struct pcsc_context));
+ err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &con->context);
+ if (err < 0)
+ {
+ *context = NULL;
+ return;
+ }
+ *context = con;
+}
+
+/*
+ * destroy context for pcsc readers
+ */
+void
+pcsc_exit(struct pcsc_context* context)
+{
+ if (context->readers)
+ SCardFreeMemory(context->context, context->readers);
+ SCardReleaseContext(context->context);
+}
+
+/*
+ * list pcsc devices
+ */
+
+LONG
+pcsc_list_devices(struct pcsc_context* context, LPSTR *string)
+{
+ LONG err;
+ LPSTR str = NULL;
+ DWORD size;
+ static char empty[] = "\0";
+ size = SCARD_AUTOALLOCATE;
+ err = SCardListReaders(context->context, NULL, (LPSTR)&str, &size);
+ if (err != SCARD_S_SUCCESS)
+ {
+ context->readers = NULL;
+ *string = empty;
+ }
+ else
+ {
+ *string = str;
+ context->readers = str;
+ }
+ return err;
+}
/*
* Low-level API
diff --git a/libfreefare/freefare.h b/libfreefare/freefare.h
index 2789968..d4c34c3 100644
--- a/libfreefare/freefare.h
+++ b/libfreefare/freefare.h
@@ -25,6 +25,7 @@
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -52,8 +53,19 @@ typedef struct mifare_desfire_key *MifareDESFireKey;
typedef uint8_t MifareUltralightPageNumber;
typedef unsigned char MifareUltralightPage[4];
+struct pcsc_context {
+ SCARDCONTEXT context;
+ LPSTR readers;
+};
+
+void pcsc_init(struct pcsc_context** context);
+void pcsc_exit(struct pcsc_context* context);
+LONG pcsc_list_devices(struct pcsc_context* context, LPSTR* string);
+
MifareTag *freefare_get_tags (nfc_device *device);
+MifareTag *freefare_get_tags_pcsc (struct pcsc_context *context, const char *reader);
MifareTag freefare_tag_new (nfc_device *device, nfc_iso14443a_info nai);
+MifareTag freefare_tag_new_pcsc(struct pcsc_context *context, const char *reader);
enum mifare_tag_type freefare_get_tag_type (MifareTag tag);
const char *freefare_get_tag_friendly_name (MifareTag tag);
char *freefare_get_tag_uid (MifareTag tag);
diff --git a/libfreefare/freefare_internal.h b/libfreefare/freefare_internal.h
index c8e1d6f..47cc9c8 100644
--- a/libfreefare/freefare_internal.h
+++ b/libfreefare/freefare_internal.h
@@ -186,10 +186,37 @@ struct supported_tag {
struct mifare_tag {
nfc_device *device;
nfc_iso14443a_info info;
+ // PCSC things
+ SCARDCONTEXT hContext;
+ SCARDHANDLE hCard;
+ char* szReader;
+ LONG lastPCSCerror;
+ // End of PCSC things
const struct supported_tag *tag_info;
int active;
};
+#define FILL_SZREADER(tag, szRd) \
+ do { \
+ tag->szReader = malloc(strlen(szRd) * sizeof(char) + 1); \
+ if(NULL == tag->szReader) \
+ { \
+ fprintf(stderr, "malloc failed !! (in freefare_get_tags_pcsc)\n"); \
+ } \
+ strcpy(tag->szReader, (const char *)szRd); \
+ } while(0)
+
+#define FREE_SZREADER(szRd) \
+ do { \
+ if(NULL != szRd) \
+ { \
+ free(szRd); \
+ szRd = NULL; \
+ } \
+ } while (0)
+
+
+
struct mifare_classic_tag {
struct mifare_tag __tag;
diff --git a/libfreefare/freefare_pcsc_tags.h b/libfreefare/freefare_pcsc_tags.h
new file mode 100644
index 0000000..7bfece5
--- /dev/null
+++ b/libfreefare/freefare_pcsc_tags.h
@@ -0,0 +1,24 @@
+#ifndef __FREEFARE_PCSC_TAGS_H__
+#define __FREEFARE_PCSC_TAGS_H__
+
+struct pcsc_atr_info {
+
+ enum mifare_tag_type type;
+ int len;
+ unsigned char* tag;
+ unsigned char* mask;
+
+};
+
+struct pcsc_atr_info pcsc_supported_atrs[] = {
+ { DESFIRE , 6, "\x3b\x04\x41\x11\x77\x81", NULL},
+ { DESFIRE , 6, "\x3b\x81\x80\x01\x80\x80", NULL },
+ { CLASSIC_1K , 20, "\x3b\x8f\x80\x01\x80\x4f\x0c\xa0\x00\x00\x03\x06\x03\x00\x01\x00\x00\x00\x00\x6a", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\x00" },
+ { CLASSIC_4K , 20, "\x3b\x8f\x80\x01\x80\x4f\x0c\xa0\x00\x00\x03\x06\x03\x00\x02\x00\x00\x00\x00\x69", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\x00" },
+ { ULTRALIGHT , 20, "\x3b\x8f\x80\x01\x80\x4f\x0c\xa0\x00\x00\x03\x06\x03\x00\x03\x00\x00\x00\x00\x68", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\x00" },
+ { ULTRALIGHT , 20, "\x3b\x8f\x80\x01\x80\x4f\x0c\xa0\x00\x00\x03\x06\x03\x00\x03\x00\x00\x00\x00\x68", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\x00" },
+ { DESFIRE , 0 , NULL, NULL}
+};
+
+#endif /* __FREEFARE_PCSC_TAGS_H__ */
+
diff --git a/libfreefare/mifare_classic.c b/libfreefare/mifare_classic.c
index 71f8c75..bbc92f0 100644
--- a/libfreefare/mifare_classic.c
+++ b/libfreefare/mifare_classic.c
@@ -90,11 +90,30 @@
errno = 0; \
DEBUG_XFER (msg, __##msg##_n, "===> "); \
int _res; \
- if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
- if (disconnect) { \
- tag->active = false; \
+ if (tag->device != NULL) /* nfc way */ \
+ { \
+ if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) \
+ { \
+ if (disconnect) \
+ { \
+ tag->active = false; \
+ } \
+ return errno = EIO, -1; \
} \
- return errno = EIO, -1; \
+ } \
+ else /* pcsc way */ \
+ { \
+ SCARD_IO_REQUEST __pcsc_rcv_pci; \
+ DWORD __pcsc_recv_len = __##res##_size + 1; \
+ if ((SCARD_S_SUCCESS != SCardTransmit(tag->hCard, SCARD_PCI_T0, msg, __##msg##_n, &__pcsc_rcv_pci, (LPBYTE)&_res, &__pcsc_recv_len)) < 0) \
+ { \
+ if (disconnect) \
+ { \
+ tag->active = false; \
+ } \
+ return errno = EIO, -1; \
+ } \
+ _res = __pcsc_recv_len; \
} \
__##res##_n = _res; \
DEBUG_XFER (res, __##res##_n, "<=== "); \
@@ -230,16 +249,33 @@ mifare_classic_connect (MifareTag tag)
ASSERT_INACTIVE (tag);
ASSERT_MIFARE_CLASSIC (tag);
- nfc_target pnti;
- nfc_modulation modulation = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106
- };
- if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, &pnti) >= 0) {
+ if(NULL != tag->device) // nfc way
+ {
+ nfc_target pnti;
+ nfc_modulation modulation = {
+ .nmt = NMT_ISO14443A,
+ .nbr = NBR_106
+ };
+ if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, &pnti) >= 0) {
+ tag->active = 1;
+ } else {
+ errno = EIO;
+ return -1;
+ }
+ }
+ else // pcsc way
+ {
+ DWORD dwActiveProtocol;
+ tag->lastPCSCerror = SCardConnect(tag->hContext, tag->szReader, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0, &(tag->hCard), &dwActiveProtocol);
+ if(SCARD_S_SUCCESS != tag->lastPCSCerror)
+ {
+ errno = EIO;
+ fprintf(stderr, "borked %lx\n", tag->lastPCSCerror);
+ return -1;
+ }
tag->active = 1;
- } else {
- errno = EIO;
- return -1;
+
}
return 0;
}
@@ -253,12 +289,28 @@ mifare_classic_disconnect (MifareTag tag)
ASSERT_ACTIVE (tag);
ASSERT_MIFARE_CLASSIC (tag);
- if (nfc_initiator_deselect_target (tag->device) >= 0) {
- tag->active = 0;
- } else {
- errno = EIO;
- return -1;
+ if(NULL != tag->device) // nfclib way
+ {
+ if (nfc_initiator_deselect_target (tag->device) >= 0) {
+ tag->active = 0;
+ } else {
+ errno = EIO;
+ return -1;
+ }
}
+ else // pcsc way
+ {
+ tag->lastPCSCerror = SCardDisconnect(tag->hCard, SCARD_LEAVE_CARD);
+ if(SCARD_S_SUCCESS == tag->lastPCSCerror)
+ {
+ tag->active = 0;
+ }
+ else {
+ errno = EIO;
+ return -1;
+ }
+ }
+
return 0;
}
diff --git a/libfreefare/mifare_desfire.c b/libfreefare/mifare_desfire.c
index 3083fea..d154fe0 100644
--- a/libfreefare/mifare_desfire.c
+++ b/libfreefare/mifare_desfire.c
@@ -137,7 +137,6 @@ static ssize_t read_data (MifareTag tag, uint8_t command, uint8_t file_no, off_
} \
} while (0)
-
/*
* Convenience macros.
*/
@@ -184,8 +183,18 @@ static ssize_t read_data (MifareTag tag, uint8_t command, uint8_t file_no, off_
MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK; \
DEBUG_XFER (__msg, __len, "===> "); \
int _res; \
- if ((_res = nfc_initiator_transceive_bytes (tag->device, __msg, __len, __res, __##res##_size + 1, 0)) < 0) { \
- return errno = EIO, -1; \
+ if (tag->device == NULL) { /* pcsc branch */ \
+ SCARD_IO_REQUEST __pcsc_rcv_pci; \
+ DWORD __pcsc_recv_len = __##res##_size + 1; \
+ if ((SCARD_S_SUCCESS != SCardTransmit(tag->hCard, SCARD_PCI_T0, __msg, __len, &__pcsc_rcv_pci, __res, &__pcsc_recv_len)) < 0) { \
+ return errno = EIO, -1; \
+ } \
+ _res = __pcsc_recv_len; \
+ } \
+ else { /* nfc branch */ \
+ if ((_res = nfc_initiator_transceive_bytes (tag->device, __msg, __len, __res, __##res##_size + 1, 0)) < 0) { \
+ return errno = EIO, -1; \
+ } \
} \
__##res##_n = _res; \
DEBUG_XFER (__res, __##res##_n, "<=== "); \
@@ -197,7 +206,8 @@ static ssize_t read_data (MifareTag tag, uint8_t command, uint8_t file_no, off_
memcpy (res, __res, __##res##_n - 1); \
} while (0)
-
+
+
/*
* Miscellaneous low-level memory manipulation functions.
*/
@@ -238,7 +248,7 @@ le24toh (uint8_t data[3])
return (data[2] << 16) | (data[1] << 8) | data[0];
}
-
+
/*
* Memory management functions.
*/
@@ -271,7 +281,6 @@ mifare_desfire_tag_free (MifareTag tag)
free (tag);
}
-
/*
* MIFARE card communication preparation functions
*
@@ -289,23 +298,45 @@ mifare_desfire_connect (MifareTag tag)
ASSERT_INACTIVE (tag);
ASSERT_MIFARE_DESFIRE (tag);
- nfc_target pnti;
- nfc_modulation modulation = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106
- };
- if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, &pnti) >= 0) {
- tag->active = 1;
- free (MIFARE_DESFIRE (tag)->session_key);
- MIFARE_DESFIRE (tag)->session_key = NULL;
- MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
- MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK;
- MIFARE_DESFIRE (tag)->authenticated_key_no = NOT_YET_AUTHENTICATED;
- MIFARE_DESFIRE (tag)->selected_application = 0;
- } else {
- errno = EIO;
- return -1;
+ if(NULL != tag->device) // nfc way
+ {
+ nfc_target pnti;
+ nfc_modulation modulation = {
+ .nmt = NMT_ISO14443A,
+ .nbr = NBR_106
+ };
+ int ret = nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, &pnti);
+ if( !(ret >= 0 )) // selecting a pasive target got some error
+ {
+ errno = EIO;
+ return -1;
+ }
+ }
+ else // pcsc way
+ {
+ DWORD dwActiveProtocol;
+
+ tag->lastPCSCerror = SCardConnect(tag->hContext, tag->szReader, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0, &(tag->hCard), &dwActiveProtocol);
+
+ if(SCARD_S_SUCCESS != tag->lastPCSCerror)
+ {
+ errno = EIO;
+ fprintf(stderr, "szReader: %s\n", tag->szReader);
+ fprintf(stderr, "borked %lx\n", tag->lastPCSCerror);
+ return -1;
+ }
+
}
+
+ tag->active = 1;
+ free (MIFARE_DESFIRE (tag)->session_key);
+ MIFARE_DESFIRE (tag)->session_key = NULL;
+ MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
+ MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK;
+ MIFARE_DESFIRE (tag)->authenticated_key_no = NOT_YET_AUTHENTICATED;
+ MIFARE_DESFIRE (tag)->selected_application = 0;
+
return 0;
}
@@ -320,15 +351,27 @@ mifare_desfire_disconnect (MifareTag tag)
free (MIFARE_DESFIRE (tag)->session_key);
MIFARE_DESFIRE(tag)->session_key = NULL;
-
- if (nfc_initiator_deselect_target (tag->device) >= 0) {
- tag->active = 0;
+
+ if(NULL != tag->device) // nfclib way
+ {
+ if (nfc_initiator_deselect_target (tag->device) >= 0) {
+ tag->active = 0;
+ }
+ }
+ else // pcsc way
+ {
+ tag->lastPCSCerror = SCardDisconnect(tag->hCard, SCARD_LEAVE_CARD);
+ if(SCARD_S_SUCCESS == tag->lastPCSCerror)
+ {
+ tag->active = 0;
+ }
}
+
+
+
return 0;
}
-
-
#define AUTHENTICATE_LEGACY 0x0A
#define AUTHENTICATE_ISO 0x1A
#define AUTHENTICATE_AES 0xAA
@@ -648,7 +691,6 @@ mifare_desfire_get_key_version (MifareTag tag, uint8_t key_no, uint8_t *version)
return 0;
}
-
static int
create_application (MifareTag tag, MifareDESFireAID aid, uint8_t settings1, uint8_t settings2, int want_iso_application, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len)
@@ -1136,7 +1178,6 @@ mifare_desfire_get_card_uid (MifareTag tag, char **uid)
return 0;
}
-
/* Application level commands */
@@ -1502,7 +1543,6 @@ mifare_desfire_delete_file (MifareTag tag, uint8_t file_no)
return 0;
}
-
/*
* Data manipulation commands.
*/
diff --git a/libfreefare/mifare_ultralight.c b/libfreefare/mifare_ultralight.c
index b442aa4..30ecc1a 100644
--- a/libfreefare/mifare_ultralight.c
+++ b/libfreefare/mifare_ultralight.c
@@ -61,37 +61,51 @@
#define ULTRALIGHT_TRANSCEIVE(tag, msg, res) \
do { \
errno = 0; \
+ int _res ; \
DEBUG_XFER (msg, __##msg##_n, "===> "); \
- int _res; \
- if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
- return errno = EIO, -1; \
+ if (tag->device == NULL) {\
+ /* PCSC branch */\
+ SCARD_IO_REQUEST __pcsc_rcv_pci; \
+ DWORD __pcsc_recv_len = __##res##_size; \
+ if ((SCARD_S_SUCCESS != SCardTransmit(tag->hCard, SCARD_PCI_T0, msg, __##msg##_n, &__pcsc_rcv_pci, res, &__pcsc_recv_len)) < 0) { \
+ return errno = EIO, -1; \
+ } \
+ _res = __pcsc_recv_len; \
+ } else { \
+ /* nfc branch */ \
+ if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
+ return errno = EIO, -1; \
+ } \
+ __##res##_n = _res; \
+ DEBUG_XFER (res, __##res##_n, "<=== "); \
} \
- __##res##_n = _res; \
- DEBUG_XFER (res, __##res##_n, "<=== "); \
} while (0)
#define ULTRALIGHT_TRANSCEIVE_RAW(tag, msg, res) \
- do { \
- errno = 0; \
- if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, false) < 0) { \
- errno = EIO; \
- return -1; \
- } \
- DEBUG_XFER (msg, __##msg##_n, "===> "); \
- int _res; \
- if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
- nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true); \
- return errno = EIO, -1; \
- } \
- __##res##_n = _res; \
- DEBUG_XFER (res, __##res##_n, "<=== "); \
- if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true) < 0) { \
+do { \
+ if (tag->device == NULL){\
+ ULTRALIGHT_TRANSCEIVE(tag, msg, res); \
+ } else { \
+ errno = 0; \
+ if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, false) < 0) { \
errno = EIO; \
return -1; \
+ } \
+ DEBUG_XFER (msg, __##msg##_n, "===> "); \
+ int _res; \
+ if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
+ nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true); \
+ return errno = EIO, -1; \
+ } \
+ __##res##_n = _res; \
+ DEBUG_XFER (res, __##res##_n, "<=== "); \
+ if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true) < 0) { \
+ errno = EIO; \
+ return -1; \
+ } \
} \
- } while (0)
+} while (0)
-
/*
* Memory management functions.
*/
@@ -133,18 +147,35 @@ mifare_ultralight_connect (MifareTag tag)
ASSERT_INACTIVE (tag);
ASSERT_MIFARE_ULTRALIGHT (tag);
- nfc_target pnti;
- nfc_modulation modulation = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106
- };
- if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, &pnti) >= 0) {
+ if (tag->device == NULL) { /* pcsc branch */
+
+ DWORD dwActiveProtocol;
+
+ tag->lastPCSCerror = SCardConnect(tag->hContext, tag->szReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &(tag->hCard), &dwActiveProtocol);
+ if(SCARD_S_SUCCESS != tag->lastPCSCerror){
+ return errno = EIO, -1;
+ }
+
tag->active = 1;
for (int i = 0; i < MIFARE_ULTRALIGHT_MAX_PAGE_COUNT; i++)
MIFARE_ULTRALIGHT(tag)->cached_pages[i] = 0;
- } else {
- errno = EIO;
- return -1;
+
+ }
+ else { /* nfc branch */
+ nfc_target pnti;
+ nfc_modulation modulation = {
+ .nmt = NMT_ISO14443A,
+ .nbr = NBR_106
+ };
+ if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, &pnti) >= 0) {
+ tag->active = 1;
+ for (int i = 0; i < MIFARE_ULTRALIGHT_MAX_PAGE_COUNT; i++)
+ MIFARE_ULTRALIGHT(tag)->cached_pages[i] = 0;
+ } else {
+ errno = EIO;
+ return -1;
+ }
+
}
return 0;
}
@@ -158,16 +189,34 @@ mifare_ultralight_disconnect (MifareTag tag)
ASSERT_ACTIVE (tag);
ASSERT_MIFARE_ULTRALIGHT (tag);
- if (nfc_initiator_deselect_target (tag->device) >= 0) {
- tag->active = 0;
- } else {
- errno = EIO;
- return -1;
+ if (tag->device == NULL) {
+ /* pcsc branch */
+
+ if ( (tag->lastPCSCerror = SCardDisconnect (tag->hCard, SCARD_LEAVE_CARD) ) == SCARD_S_SUCCESS )
+ {
+ tag->active = 0;
+ return 0;
+ }
+ else
+ {
+ errno = EIO;
+ return -1;
+ }
+
+ }
+ else /* nfc branch */
+ {
+ if (nfc_initiator_deselect_target (tag->device) >= 0) {
+ tag->active = 0;
+ } else {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
}
- return 0;
}
-
+
/*
* Card manipulation functions
*