diff --git a/.gitignore b/.gitignore
index 3a49783..c0baedf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@
 *.lo
 *.o
 *~
+.vs/
+CMakeSettings.json
 Doxyfile
 INSTALL
 aclocal.m4
diff --git a/.travis.yml b/.travis.yml
index b331309..79d024b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,20 +1,81 @@
 language: c
 
-compiler:
-  - clang
-  - gcc
+matrix:
+  include:
+    - os: windows
+      compiler:
+        - clang
+      before_install:
+        - mkdir build && cd build && wget "https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/libusb-win32-bin-1.2.6.0.zip" && 7z x libusb-win32-bin-1.2.6.0.zip -o"$PROGRAMFILES" && mv "$PROGRAMFILES/libusb-win32-bin-1.2.6.0" "$PROGRAMFILES/libusb-win32"
+      install:
+        choco install doxygen.install ninja
+      script:
+        cmake -GNinja .. && cmake --build .
 
-env:
-  - BLD=cmake
-  - BLD=autoconf
+    - os: linux
+      dist: bionic
+      compiler:
+        - clang
+      addons:
+        apt:
+          packages:
+            - libusb-dev
+            - doxygen
+            - cmake
+      script:
+        - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
+        
+    - os: linux
+      dist: bionic
+      compiler:
+        - clang
+      addons:
+        apt:
+          packages:
+            - libusb-dev
+            - doxygen
+      script:
+        - autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
 
-addons:
-  apt:
-    packages:
-    - libusb-dev
-    - doxygen
-    - cmake
+    - os: linux
+      dist: bionic
+      compiler:
+        - gcc
+      addons:
+        apt:
+          packages:
+            - libusb-dev
+            - doxygen
+            - cmake
+      script:
+        - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
 
-script:
-  - if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi
-  - if [ $BLD == cmake ];    then mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install; fi
+    - os: linux
+      dist: bionic
+      compiler:
+        - gcc
+      addons:
+        apt:
+          packages:
+            - libusb-dev
+            - doxygen
+      script:
+        - autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
+
+    - os: osx
+      osx_image: xcode12
+      compiler:
+        - clang
+      before_install:
+        - brew install doxygen libusb-compat
+      script:
+        - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
+
+    - os: osx
+      osx_image: xcode12
+      compiler:
+        - clang
+      before_install:
+        - brew install doxygen libusb-compat m4
+      script:
+        - autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48db870..05104a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,9 +18,12 @@ SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 
 # config.h
 IF(WIN32)
+  SET(LIBNFC_SYSCONFDIR "./config" CACHE PATH "libnfc configuration directory")
   CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
-  SET(LIBNFC_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/config" CACHE PATH "libnfc configuration directory")
   INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32)
+    IF(NOT MINGW)
+      SET(CMAKE_C_FLAGS "-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE ${CMAKE_C_FLAGS}")
+    ENDIF(NOT MINGW)
 ELSE(WIN32)
   SET(_XOPEN_SOURCE 600)
   SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
@@ -138,9 +141,12 @@ IF(NOT WIN32)
   IF(LIBNFC_DRIVER_PN53X_USB)
     SET(PKG_REQ ${PKG_REQ} "libusb")
   ENDIF(LIBNFC_DRIVER_PN53X_USB)
+  IF(LIBNFC_DRIVER_ACR122_USB)
+    SET(PKG_REQ ${PKG_REQ} "libusb")
+  ENDIF(LIBNFC_DRIVER_ACR122_USB)
   IF(LIBNFC_DRIVER_PCSC)
     SET(PKG_REQ ${PKG_REQ} "libpcsclite")
-  ENDIF(LIBNFC_DRIVER_ACR122)
+  ENDIF(LIBNFC_DRIVER_PCSC)
   IF(LIBNFC_DRIVER_ACR122_PCSC)
     SET(PKG_REQ ${PKG_REQ} "libpcsclite")
   ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
@@ -201,7 +207,8 @@ IF(WIN32)
   SET(RC_COMMENT "${PACKAGE_NAME} library")
   SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}")
   SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll)
-  SET(RC_FILE_TYPE VFT_DLL)
+  # RC_FILE_TYPE: VFT_DLL
+  SET(RC_FILE_TYPE 0x00000002L)
   CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/windows/libnfc.rc @ONLY)
 ENDIF(WIN32)
 
diff --git a/Makefile.am b/Makefile.am
index d2f6fc8..516ebee 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,13 @@ ACLOCAL_AMFLAGS = -I m4
 
 AM_CFLAGS = $(LIBNFC_CFLAGS)
 
-SUBDIRS = libnfc utils examples include contrib cmake test
+SUBDIRS = libnfc utils
+
+if EXAMPLE_ENABLED
+SUBDIRS += examples
+endif
+
+SUBDIRS += include contrib cmake test
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libnfc.pc
diff --git a/README.md b/README.md
index 7a9bb44..1f4b502 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ Some NFC drivers depend on third party software:
 
 * acr122_pcsc:
   
-  - pcsc-lite http://pcsclite.alioth.debian.org/
+  - pcsc-lite https://pcsclite.apdu.fr/
 - pcsc:
   
   - Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test.
diff --git a/cmake/modules/FindLIBUSB.cmake b/cmake/modules/FindLIBUSB.cmake
index 14b5f98..4afd8af 100644
--- a/cmake/modules/FindLIBUSB.cmake
+++ b/cmake/modules/FindLIBUSB.cmake
@@ -26,9 +26,15 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
 
 IF(NOT LIBUSB_FOUND)
   IF(WIN32)
-    FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramFiles}/LibUSB-Win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
-    FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramFiles}/LibUSB-Win32/lib/gcc")
-    SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramFiles}/LibUSB-Win32/bin/x86/")
+    IF(MINGW)
+      FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
+      FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/lib/gcc")
+      SET(LIBUSB_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/bin/x86/")
+    ELSE(MINGW)
+      FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramW6432}/libusb-win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
+      FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64")
+      SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramW6432}/libusb-win32/bin/amd64/")
+    ENDIF(MINGW)
     # Must fix up variable to avoid backslashes during packaging
     STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR})
   ELSE(WIN32)
diff --git a/cmake/modules/LibnfcDrivers.cmake b/cmake/modules/LibnfcDrivers.cmake
index e3806d4..7dc2503 100644
--- a/cmake/modules/LibnfcDrivers.cmake
+++ b/cmake/modules/LibnfcDrivers.cmake
@@ -3,13 +3,13 @@ SET(LIBNFC_DRIVER_ACR122_PCSC OFF CACHE BOOL "Enable ACR122 support (Depends on
 SET(LIBNFC_DRIVER_ACR122_USB ON CACHE BOOL "Enable ACR122 support (Direct USB connection)")
 SET(LIBNFC_DRIVER_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)")
 SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)")
-IF(WIN32)
-  SET(LIBNFC_DRIVER_PN532_I2C OFF CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
-  SET(LIBNFC_DRIVER_PN532_SPI OFF CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
-ELSE(WIN32)
+IF(UNIX AND NOT APPLE)
   SET(LIBNFC_DRIVER_PN532_I2C ON CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
   SET(LIBNFC_DRIVER_PN532_SPI ON CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
-ENDIF(WIN32)
+ELSE(UNIX AND NOT APPLE)
+  SET(LIBNFC_DRIVER_PN532_I2C OFF CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
+  SET(LIBNFC_DRIVER_PN532_SPI OFF CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
+ENDIF(UNIX AND NOT APPLE)
 SET(LIBNFC_DRIVER_PN532_UART ON CACHE BOOL "Enable PN532 UART support (Use serial port)")
 SET(LIBNFC_DRIVER_PN53X_USB ON CACHE BOOL "Enable PN531 and PN531 USB support (Depends on libusb)")
 
@@ -68,4 +68,11 @@ IF(LIBNFC_DRIVER_PN53X_USB)
   SET(USB_REQUIRED TRUE)
 ENDIF(LIBNFC_DRIVER_PN53X_USB)
 
+IF(LIBNFC_DRIVER_ACR122_USB)
+  FIND_PACKAGE(LIBUSB REQUIRED)
+  ADD_DEFINITIONS("-DDRIVER_ACR122_USB_ENABLED")
+  SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122_usb")
+  SET(USB_REQUIRED TRUE)
+ENDIF(LIBNFC_DRIVER_ACR122_USB)
+
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers)
diff --git a/configure.ac b/configure.ac
index 280a6d0..46b65d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,14 @@ then
 fi
 AM_CONDITIONAL(DOC_ENABLED, [test x"$enable_doc" = xyes])
 
+# Example build (default: yes)
+AC_ARG_ENABLE([example],AS_HELP_STRING([--enable-example],[Enable example build.]),[enable_example=$enableval],[enable_example="yes"])
+
+AC_MSG_CHECKING(for example build)
+AC_MSG_RESULT($enable_example)
+
+AM_CONDITIONAL(EXAMPLE_ENABLED, [test x"$enable_example" = xyes])
+
 # Dependencies
 PKG_CONFIG_REQUIRES=""
 
@@ -175,7 +183,10 @@ 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"])
 
+if test x"$enable_example" = "xyes"
+then
 AC_CHECK_READLINE
+fi
 
 # Help us to write great code ;-)
 CFLAGS="$CFLAGS -Wall -pedantic -Wextra"
diff --git a/contrib/win32/dirent.h b/contrib/win32/dirent.h
new file mode 100644
index 0000000..9cd7556
--- /dev/null
+++ b/contrib/win32/dirent.h
@@ -0,0 +1,870 @@
+/*
+ * Dirent interface for Microsoft Visual Studio
+ *
+ * Copyright (C) 2006-2012 Toni Ronkko
+ * This file is part of dirent.  Dirent may be freely distributed
+ * under the MIT license.  For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/*
+ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
+ * Windows Sockets 2.0.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+#   define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat(), general mask */
+#if !defined(S_IFMT)
+#   define S_IFMT _S_IFMT
+#endif
+
+/* Directory bit */
+#if !defined(S_IFDIR)
+#   define S_IFDIR _S_IFDIR
+#endif
+
+/* Character device bit */
+#if !defined(S_IFCHR)
+#   define S_IFCHR _S_IFCHR
+#endif
+
+/* Pipe bit */
+#if !defined(S_IFFIFO)
+#   define S_IFFIFO _S_IFFIFO
+#endif
+
+/* Regular file bit */
+#if !defined(S_IFREG)
+#   define S_IFREG _S_IFREG
+#endif
+
+/* Read permission */
+#if !defined(S_IREAD)
+#   define S_IREAD _S_IREAD
+#endif
+
+/* Write permission */
+#if !defined(S_IWRITE)
+#   define S_IWRITE _S_IWRITE
+#endif
+
+/* Execute permission */
+#if !defined(S_IEXEC)
+#   define S_IEXEC _S_IEXEC
+#endif
+
+/* Pipe */
+#if !defined(S_IFIFO)
+#   define S_IFIFO _S_IFIFO
+#endif
+
+/* Block device */
+#if !defined(S_IFBLK)
+#   define S_IFBLK 0
+#endif
+
+/* Link */
+#if !defined(S_IFLNK)
+#   define S_IFLNK 0
+#endif
+
+/* Socket */
+#if !defined(S_IFSOCK)
+#   define S_IFSOCK 0
+#endif
+
+/* Read user permission */
+#if !defined(S_IRUSR)
+#   define S_IRUSR S_IREAD
+#endif
+
+/* Write user permission */
+#if !defined(S_IWUSR)
+#   define S_IWUSR S_IWRITE
+#endif
+
+/* Execute user permission */
+#if !defined(S_IXUSR)
+#   define S_IXUSR 0
+#endif
+
+/* Read group permission */
+#if !defined(S_IRGRP)
+#   define S_IRGRP 0
+#endif
+
+/* Write group permission */
+#if !defined(S_IWGRP)
+#   define S_IWGRP 0
+#endif
+
+/* Execute group permission */
+#if !defined(S_IXGRP)
+#   define S_IXGRP 0
+#endif
+
+/* Read others permission */
+#if !defined(S_IROTH)
+#   define S_IROTH 0
+#endif
+
+/* Write others permission */
+#if !defined(S_IWOTH)
+#   define S_IWOTH 0
+#endif
+
+/* Execute others permission */
+#if !defined(S_IXOTH)
+#   define S_IXOTH 0
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+#   define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+#   define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+#   define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN 0
+#define DT_REG S_IFREG
+#define DT_DIR S_IFDIR
+#define DT_FIFO S_IFIFO
+#define DT_SOCK S_IFSOCK
+#define DT_CHR S_IFCHR
+#define DT_BLK S_IFBLK
+#define DT_LNK S_IFLNK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#if !defined(S_ISFIFO)
+#   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISDIR)
+#   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG)
+#   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK)
+#   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK)
+#   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISCHR)
+#   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISBLK)
+#   define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Return the exact length of the file name without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return the maximum size of a file name */
+#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+    /* Always zero */
+    long d_ino;
+
+    /* File position within stream */
+    long d_off;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    wchar_t d_name[PATH_MAX+1];
+};
+typedef struct _wdirent _wdirent;
+
+struct _WDIR {
+    /* Current directory entry */
+    struct _wdirent ent;
+
+    /* Private file data */
+    WIN32_FIND_DATAW data;
+
+    /* True if data is valid */
+    int cached;
+
+    /* Win32 search handle */
+    HANDLE handle;
+
+    /* Initial directory name */
+    wchar_t *patt;
+};
+typedef struct _WDIR _WDIR;
+
+/* Multi-byte character version */
+struct dirent {
+    /* Always zero */
+    long d_ino;
+
+    /* File position within stream */
+    long d_off;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    char d_name[PATH_MAX+1];
+};
+typedef struct dirent dirent;
+
+struct DIR {
+    struct dirent ent;
+    struct _WDIR *wdirp;
+};
+typedef struct DIR DIR;
+
+
+/* Dirent functions */
+static DIR *opendir (const char *dirname);
+static _WDIR *_wopendir (const wchar_t *dirname);
+
+static struct dirent *readdir (DIR *dirp);
+
+static int readdir_r(
+    DIR *dirp, struct dirent *entry, struct dirent **result);
+
+static int closedir (DIR *dirp);
+static int _wclosedir (_WDIR *dirp);
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
+
+static int dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count);
+
+static int dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes,
+    const wchar_t *wcstr,
+    size_t count);
+
+static void dirent_set_errno (int error);
+
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR*
+_wopendir(
+    const wchar_t *dirname)
+{
+    _WDIR *dirp = NULL;
+    int error;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate new _WDIR structure */
+    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
+    if (dirp != NULL) {
+        DWORD n;
+
+        /* Reset _WDIR structure */
+        dirp->handle = INVALID_HANDLE_VALUE;
+        dirp->patt = NULL;
+        dirp->cached = 0;
+
+        /* Compute the length of full path plus zero terminator
+         *
+         * Note that on WinRT there's no way to convert relative paths
+         * into absolute paths, so just assume it is an absolute path.
+         */
+#       if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+            n = wcslen(dirname);
+#       else
+            n = GetFullPathNameW (dirname, 0, NULL, NULL);
+#       endif
+
+        /* Allocate room for absolute directory name and search pattern */
+        dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
+        if (dirp->patt) {
+
+            /*
+             * Convert relative directory name to an absolute one.  This
+             * allows rewinddir() to function correctly even when current
+             * working directory is changed between opendir() and rewinddir().
+             *
+             * Note that on WinRT there's no way to convert relative paths
+             * into absolute paths, so just assume it is an absolute path.
+             */
+#           if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+                wcsncpy_s(dirp->patt, n+1, dirname, n);
+#           else
+                n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
+#           endif
+            if (n > 0) {
+                wchar_t *p;
+
+                /* Append search pattern \* to the directory name */
+                p = dirp->patt + n;
+                if (dirp->patt < p) {
+                    switch (p[-1]) {
+                    case '\\':
+                    case '/':
+                    case ':':
+                        /* Directory ends in path separator, e.g. c:\temp\ */
+                        /*NOP*/;
+                        break;
+
+                    default:
+                        /* Directory name doesn't end in path separator */
+                        *p++ = '\\';
+                    }
+                }
+                *p++ = '*';
+                *p = '\0';
+
+                /* Open directory stream and retrieve the first entry */
+                if (dirent_first (dirp)) {
+                    /* Directory stream opened successfully */
+                    error = 0;
+                } else {
+                    /* Cannot retrieve first entry */
+                    error = 1;
+                    dirent_set_errno (ENOENT);
+                }
+
+            } else {
+                /* Cannot retrieve full path name */
+                dirent_set_errno (ENOENT);
+                error = 1;
+            }
+
+        } else {
+            /* Cannot allocate memory for search pattern */
+            error = 1;
+        }
+
+    } else {
+        /* Cannot allocate _WDIR structure */
+        error = 1;
+    }
+
+    /* Clean up in case of error */
+    if (error  &&  dirp) {
+        _wclosedir (dirp);
+        dirp = NULL;
+    }
+
+    return dirp;
+}
+
+/*
+ * Close directory stream opened by opendir() function.  This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int
+_wclosedir(
+    _WDIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Release search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+        }
+
+        /* Release search pattern */
+        if (dirp->patt) {
+            free (dirp->patt);
+            dirp->patt = NULL;
+        }
+
+        /* Release directory structure */
+        free (dirp);
+        ok = /*success*/0;
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/* Get first directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_first(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Open directory and retrieve the first entry */
+    dirp->handle = FindFirstFileExW(
+        dirp->patt, FindExInfoStandard, &dirp->data,
+        FindExSearchNameMatch, NULL, 0);
+    if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* a directory entry is now waiting in memory */
+        datap = &dirp->data;
+        dirp->cached = 1;
+
+    } else {
+
+        /* Failed to re-open directory: no directory entry in memory */
+        dirp->cached = 0;
+        datap = NULL;
+
+    }
+    return datap;
+}
+
+/*
+ * Get next directory entry (internal).
+ *
+ * Returns 
+ */
+static WIN32_FIND_DATAW*
+dirent_next(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *p;
+
+    /* Get next directory entry */
+    if (dirp->cached != 0) {
+
+        /* A valid directory entry already in memory */
+        p = &dirp->data;
+        dirp->cached = 0;
+
+    } else if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* Get the next directory entry from stream */
+        if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
+            /* Got a file */
+            p = &dirp->data;
+        } else {
+            /* The very last entry has been processed or an error occurred */
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+            p = NULL;
+        }
+
+    } else {
+
+        /* End of directory stream reached */
+        p = NULL;
+
+    }
+
+    return p;
+}
+
+/*
+ * Open directory stream using plain old C-string.
+ */
+static DIR*
+opendir(
+    const char *dirname) 
+{
+    struct DIR *dirp;
+    int error;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate memory for DIR structure */
+    dirp = (DIR*) malloc (sizeof (struct DIR));
+    if (dirp) {
+        wchar_t wname[PATH_MAX + 1];
+        size_t n;
+
+        /* Convert directory name to wide-character string */
+        error = dirent_mbstowcs_s(
+            &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
+        if (!error) {
+
+            /* Open directory stream using wide-character name */
+            dirp->wdirp = _wopendir (wname);
+            if (dirp->wdirp) {
+                /* Directory stream opened */
+                error = 0;
+            } else {
+                /* Failed to open directory stream */
+                error = 1;
+            }
+
+        } else {
+            /*
+             * Cannot convert file name to wide-character string.  This
+             * occurs if the string contains invalid multi-byte sequences or
+             * the output buffer is too small to contain the resulting
+             * string.
+             */
+            error = 1;
+        }
+
+    } else {
+        /* Cannot allocate DIR structure */
+        error = 1;
+    }
+
+    /* Clean up in case of error */
+    if (error  &&  dirp) {
+        free (dirp);
+        dirp = NULL;
+    }
+
+    return dirp;
+}
+
+/*
+ * Read next directory entry.
+ */
+static struct dirent*
+readdir(
+    DIR *dirp)
+{
+    struct dirent *entry;
+
+    /*
+     * Read directory entry to buffer.  We can safely ignore the return value
+     * as entry will be set to NULL in case of error.
+     */
+    (void) readdir_r (dirp, &dirp->ent, &entry);
+
+    /* Return pointer to statically allocated directory entry */
+    return entry;
+}
+
+/*
+ * Read next directory entry into called-allocated buffer.
+ *
+ * Returns zero on success.  If the end of directory stream is reached, then
+ * sets result to NULL and returns zero.
+ */
+static int
+readdir_r(
+    DIR *dirp,
+    struct dirent *entry,
+    struct dirent **result)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp->wdirp);
+    if (datap) {
+        size_t n;
+        int error;
+
+        /* Attempt to convert file name to multi-byte string */
+        error = dirent_wcstombs_s(
+            &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
+
+        /*
+         * If the file name cannot be represented by a multi-byte string,
+         * then attempt to use old 8+3 file name.  This allows traditional
+         * Unix-code to access some file names despite of unicode
+         * characters, although file names may seem unfamiliar to the user.
+         *
+         * Be ware that the code below cannot come up with a short file
+         * name unless the file system provides one.  At least
+         * VirtualBox shared folders fail to do this.
+         */
+        if (error  &&  datap->cAlternateFileName[0] != '\0') {
+            error = dirent_wcstombs_s(
+                &n, entry->d_name, PATH_MAX + 1,
+                datap->cAlternateFileName, PATH_MAX + 1);
+        }
+
+        if (!error) {
+            DWORD attr;
+
+            /* Length of file name excluding zero terminator */
+            entry->d_namlen = n - 1;
+
+            /* File attributes */
+            attr = datap->dwFileAttributes;
+            if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+                entry->d_type = DT_CHR;
+            } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+                entry->d_type = DT_DIR;
+            } else {
+                entry->d_type = DT_REG;
+            }
+
+            /* Reset dummy fields */
+            entry->d_ino = 0;
+            entry->d_off = 0;
+            entry->d_reclen = sizeof (struct dirent);
+
+        } else {
+
+            /*
+             * Cannot convert file name to multi-byte string so construct
+             * an erroneous directory entry and return that.  Note that
+             * we cannot return NULL as that would stop the processing
+             * of directory entries completely.
+             */
+            entry->d_name[0] = '?';
+            entry->d_name[1] = '\0';
+            entry->d_namlen = 1;
+            entry->d_type = DT_UNKNOWN;
+            entry->d_ino = 0;
+            entry->d_off = -1;
+            entry->d_reclen = 0;
+
+        }
+
+        /* Return pointer to directory entry */
+        *result = entry;
+
+    } else {
+
+        /* No more directory entries */
+        *result = NULL;
+
+    }
+
+    return /*OK*/0;
+}
+
+/*
+ * Close directory stream.
+ */
+static int
+closedir(
+    DIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Close wide-character directory stream */
+        ok = _wclosedir (dirp->wdirp);
+        dirp->wdirp = NULL;
+
+        /* Release multi-byte character version */
+        free (dirp);
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/* Convert multi-byte string to wide character string */
+static int
+dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to wide-character string (or count characters) */
+    n = mbstowcs (wcstr, mbstr, sizeInWords);
+    if (!wcstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (wcstr  &&  sizeInWords) {
+            if (n >= sizeInWords) {
+                n = sizeInWords - 1;
+            }
+            wcstr[n] = 0;
+        }
+
+        /* Length of resulting multi-byte string WITH zero terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Could not convert string */
+        error = 1;
+
+    }
+
+#endif
+
+    return error;
+}
+
+/* Convert wide-character string to multi-byte string */
+static int
+dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes, /* max size of mbstr */
+    const wchar_t *wcstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to multi-byte string (or count the number of bytes needed) */
+    n = wcstombs (mbstr, wcstr, sizeInBytes);
+    if (!mbstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (mbstr  &&  sizeInBytes) {
+            if (n >= sizeInBytes) {
+                n = sizeInBytes - 1;
+            }
+            mbstr[n] = '\0';
+        }
+
+        /* Length of resulting multi-bytes string WITH zero-terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Cannot convert string */
+        error = 1;
+
+    }
+
+#endif
+
+    return error;
+}
+
+/* Set errno variable */
+static void
+dirent_set_errno(
+    int error)
+{
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 and later */
+    _set_errno (error);
+
+#else
+
+    /* Non-Microsoft compiler or older Microsoft compiler */
+    errno = error;
+
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
+
diff --git a/contrib/win32/getopt.c b/contrib/win32/getopt.c
new file mode 100644
index 0000000..808be80
--- /dev/null
+++ b/contrib/win32/getopt.c
@@ -0,0 +1,106 @@
+#include "getopt.h" // make sure you construct the header file as dictated above
+
+/*
+* Copyright (c) 1987, 1993, 1994
+*      The Regents of the University of California.  All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+* 3. All advertising materials mentioning features or use of this software
+*    must display the following acknowledgement:
+*      This product includes software developed by the University of
+*      California, Berkeley and its contributors.
+* 4. Neither the name of the University nor the names of its contributors
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+* SUCH DAMAGE.
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+int     opterr = 1,             /* if error message should be printed */
+        optind = 1,             /* index into parent argv vector */
+        optopt,                 /* character checked for validity */
+        optreset;               /* reset getopt */
+char    *optarg;                /* argument associated with option */
+
+#define BADCH   (int)'?'
+#define BADARG  (int)':'
+#define EMSG    ""
+
+/*
+ * getopt --
+ *      Parse argc/argv argument vector.
+ */
+int getopt(int nargc, char * const nargv[], const char *ostr)
+{
+  static char *place = EMSG;              /* option letter processing */
+  const char *oli;                              /* option letter list index */
+
+  if (optreset || !*place) {              /* update scanning pointer */
+    optreset = 0;
+    if (optind >= nargc || *(place = nargv[optind]) != '-') {
+      place = EMSG;
+      return (-1);
+    }
+    if (place[1] && *++place == '-') {      /* found "--" */
+      ++optind;
+      place = EMSG;
+      return (-1);
+    }
+  }                                       /* option letter okay? */
+  if ((optopt = (int)*place++) == (int)':' ||
+    !(oli = strchr(ostr, optopt))) {
+      /*
+      * if the user didn't specify '-' as an option,
+      * assume it means -1.
+      */
+      if (optopt == (int)'-')
+        return (-1);
+      if (!*place)
+        ++optind;
+      if (opterr && *ostr != ':')
+        (void)printf("illegal option -- %c\n", optopt);
+      return (BADCH);
+  }
+  if (*++oli != ':') {                    /* don't need argument */
+    optarg = NULL;
+    if (!*place)
+      ++optind;
+  }
+  else {                                  /* need an argument */
+    if (*place)                     /* no white space */
+      optarg = place;
+    else if (nargc <= ++optind) {   /* no arg */
+      place = EMSG;
+      if (*ostr == ':')
+        return (BADARG);
+      if (opterr)
+        (void)printf("option requires an argument -- %c\n", optopt);
+      return (BADCH);
+    }
+    else                            /* white space */
+      optarg = nargv[optind];
+    place = EMSG;
+    ++optind;
+  }
+  return (optopt);                        /* dump back option letter */
+}
diff --git a/contrib/win32/getopt.h b/contrib/win32/getopt.h
new file mode 100644
index 0000000..c895616
--- /dev/null
+++ b/contrib/win32/getopt.h
@@ -0,0 +1,13 @@
+#ifndef GETOPT_H
+
+#define GETOPT_H
+
+extern int opterr;		/* if error message should be printed */
+extern int optind;		/* index into parent argv vector */
+extern int optopt;		/* character checked for validity */
+extern int optreset;  	/* reset getopt  */
+extern char *optarg;	/* argument associated with option */
+
+int getopt(int nargc, char * const nargv[], const char *ostr);
+
+#endif
diff --git a/contrib/win32/libnfc/buses/uart.c b/contrib/win32/libnfc/buses/uart.c
index a109d5e..ba7ddfe 100644
--- a/contrib/win32/libnfc/buses/uart.c
+++ b/contrib/win32/libnfc/buses/uart.c
@@ -183,7 +183,7 @@ uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, i
   log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Timeouts are set to %lu ms", timeout_ms);
 
   // TODO Enhance the reception method
-  // - According to MSDN, it could be better to implement nfc_abort_command() mecanism using Cancello()
+  // - According to MSDN, it could be better to implement nfc_abort_command() mechanism using Cancello()
   volatile bool *abort_flag_p = (volatile bool *)abort_p;
   do {
     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ReadFile");
diff --git a/contrib/win32/nfc.def b/contrib/win32/nfc.def
index 5ed4097..2259817 100644
--- a/contrib/win32/nfc.def
+++ b/contrib/win32/nfc.def
@@ -39,6 +39,7 @@ EXPORTS
   nfc_device_get_supported_baud_rate_target_mode
   nfc_device_set_property_int
   nfc_device_set_property_bool
+  nfc_emulate_target
   iso14443a_crc
   iso14443a_crc_append
   iso14443b_crc
@@ -50,3 +51,7 @@ EXPORTS
   str_nfc_modulation_type
   str_nfc_baud_rate
   str_nfc_target
+  pn53x_transceive
+  pn532_SAMConfiguration
+  pn53x_read_register
+  pn53x_write_register
diff --git a/contrib/win32/nfc_msvc.def b/contrib/win32/nfc_msvc.def
new file mode 100644
index 0000000..ec4dc80
--- /dev/null
+++ b/contrib/win32/nfc_msvc.def
@@ -0,0 +1,57 @@
+LIBRARY nfc
+VERSION 1.7
+
+EXPORTS
+  nfc_init
+  nfc_exit
+  nfc_register_driver
+  nfc_open
+  nfc_close
+  nfc_abort_command
+  nfc_list_devices
+  nfc_idle
+  nfc_initiator_init
+  nfc_initiator_init_secure_element
+  nfc_initiator_select_passive_target
+  nfc_initiator_list_passive_targets
+  nfc_initiator_poll_target
+  nfc_initiator_select_dep_target
+  nfc_initiator_poll_dep_target
+  nfc_initiator_deselect_target
+  nfc_initiator_transceive_bytes
+  nfc_initiator_transceive_bits
+  nfc_initiator_transceive_bytes_timed
+  nfc_initiator_transceive_bits_timed
+  nfc_initiator_target_is_present
+  nfc_target_init
+  nfc_target_send_bytes
+  nfc_target_receive_bytes
+  nfc_target_send_bits
+  nfc_target_receive_bits
+  nfc_strerror
+  nfc_strerror_r
+  nfc_perror
+  nfc_device_get_last_error
+  nfc_device_get_name
+  nfc_device_get_connstring
+  nfc_device_get_supported_modulation
+  nfc_device_get_supported_baud_rate
+  nfc_device_get_supported_baud_rate_target_mode
+  nfc_device_set_property_int
+  nfc_device_set_property_bool
+  nfc_emulate_target
+  iso14443a_crc
+  iso14443a_crc_append
+  iso14443b_crc
+  iso14443b_crc_append
+  iso14443a_locate_historical_bytes
+  nfc_free
+  nfc_version
+  nfc_device_get_information_about
+  str_nfc_modulation_type
+  str_nfc_baud_rate
+  str_nfc_target
+  pn53x_transceive
+  pn532_SAMConfiguration
+  pn53x_read_register
+  pn53x_write_register
diff --git a/contrib/win32/version.rc.in b/contrib/win32/version.rc.in
index 473d579..30f7b83 100644
--- a/contrib/win32/version.rc.in
+++ b/contrib/win32/version.rc.in
@@ -1,15 +1,9 @@
-#include "windows.h"
-
 1 VERSIONINFO
  FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
  PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
  FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS VS_FF_DEBUG|VS_FF_PRERELEASE
-#else
- FILEFLAGS 0L
-#endif
- FILEOS VOS_NT_WINDOWS32
+ FILEFLAGS 0x0L
+ FILEOS 0x00040004L
  FILETYPE @RC_FILE_TYPE@
  FILESUBTYPE 0x0L
 BEGIN
diff --git a/contrib/windows.h b/contrib/windows.h
index 88817db..3928d6e 100644
--- a/contrib/windows.h
+++ b/contrib/windows.h
@@ -48,7 +48,9 @@
 #    define ENOTSUP       WSAEOPNOTSUPP
 #    define ECONNABORTED  WSAECONNABORTED
 #  else
+#ifndef _MSC_VER
 #    define snprintf sprintf_s
+#endif
 #    define strdup _strdup
 #  endif
 
diff --git a/debian/changelog b/debian/changelog
index e6e0efc..b9cc66b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+libnfc (1.8.0+git20210122.1.2b5ad9c-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 06 Jun 2021 11:39:08 -0000
+
 libnfc (1.8.0-2) unstable; urgency=medium
 
   * new build to do a source only upload
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 35a852b..469fea8 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -23,7 +23,8 @@ FOREACH(source ${EXAMPLES-SOURCES})
     SET(RC_COMMENT "${PACKAGE_NAME} example")
     SET(RC_INTERNAL_NAME ${source})
     SET(RC_ORIGINAL_NAME ${source}.exe)
-    SET(RC_FILE_TYPE VFT_APP)
+    # RC_FILE_TYPE: VFT_APP
+    SET(RC_FILE_TYPE 0x00000001L)
     CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
     LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
   ENDIF(WIN32)
diff --git a/libnfc/CMakeLists.txt b/libnfc/CMakeLists.txt
index 514f60d..2867d4e 100644
--- a/libnfc/CMakeLists.txt
+++ b/libnfc/CMakeLists.txt
@@ -5,6 +5,9 @@ IF(WIN32)
 
   # Add in the rc for version information in the dll
   LIST(APPEND WINDOWS_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/../windows/libnfc.rc)
+  IF (NOT MINGW)
+    LIST(APPEND WINDOWS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc_msvc.def)
+  ENDIF()
 ENDIF(WIN32)
 
 # Library's chips
@@ -26,23 +29,23 @@ IF(UART_REQUIRED)
 ENDIF(UART_REQUIRED)
 
 IF(I2C_REQUIRED)
-  IF(WIN32)
-    # Windows is not supported at the moment
-    #LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/i2c)
-    MESSAGE( FATAL_ERROR "I2C not (yet) supported under Windows!" )
-  ELSE(WIN32)
+  IF(UNIX AND NOT APPLE)
     LIST(APPEND BUSES_SOURCES buses/i2c)
-  ENDIF(WIN32)
+  ELSE(UNIX AND NOT APPLE)
+    # Only Linux is supported at the moment
+    #LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/i2c)
+    MESSAGE( FATAL_ERROR "I2C is only (yet) supported in Linux!" )
+  ENDIF(UNIX AND NOT APPLE)
 ENDIF(I2C_REQUIRED)
 
 IF(SPI_REQUIRED)
-  IF(WIN32)
-    # Windows is not supported at the moment
-    #LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/spi)
-    MESSAGE( FATAL_ERROR "SPI not (yet) supported under Windows!" )
-  ELSE(WIN32)
+  IF(UNIX AND NOT APPLE)
     LIST(APPEND BUSES_SOURCES buses/spi)
-  ENDIF(WIN32)
+  ELSE(UNIX AND NOT APPLE)
+    # Only Linux is supported at the moment
+    #LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/spi)
+    MESSAGE( FATAL_ERROR "SPI is only (yet) supported in Linux!" )
+  ENDIF(UNIX AND NOT APPLE)
 ENDIF(SPI_REQUIRED)
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses)
@@ -63,7 +66,9 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
 
 IF(LIBNFC_LOG)
   IF(WIN32)
-    SET(CMAKE_C_FLAGS "-fgnu89-inline ${CMAKE_C_FLAGS}")
+    IF(MINGW)
+      SET(CMAKE_C_FLAGS "-fgnu89-inline ${CMAKE_C_FLAGS}")
+    ENDIF(MINGW)
     LIST(APPEND LIBRARY_SOURCES log ../contrib/win32/libnfc/log-internal)
   ELSE(WIN32)
     LIST(APPEND LIBRARY_SOURCES log log-internal)
@@ -88,13 +93,16 @@ SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 6 VERSION 6.0.0)
 IF(WIN32)
   # Libraries that are windows specific
   TARGET_LINK_LIBRARIES(nfc wsock32)
-
-  ADD_CUSTOM_COMMAND(
-    OUTPUT libnfc.lib
-    COMMAND ${DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll
-    DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def
-  )
-  ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib)
+  IF(MINGW)
+    ADD_CUSTOM_COMMAND(
+      OUTPUT libnfc.lib
+      COMMAND ${DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll
+      DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def
+    )
+    ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib)
+  ELSE()
+    ADD_LIBRARY(win32lib ALIAS nfc)
+  ENDIF()
 
   # On Windows the shared (runtime) library should be either in the same 
   # directory as the excutables or in the path, we add it to same directory
diff --git a/libnfc/buses/uart.h b/libnfc/buses/uart.h
index 49b822a..39d8d2f 100644
--- a/libnfc/buses/uart.h
+++ b/libnfc/buses/uart.h
@@ -33,7 +33,9 @@
 #ifndef __NFC_BUS_UART_H__
 #  define __NFC_BUS_UART_H__
 
+#if !defined(_MSC_VER)
 #  include <sys/time.h>
+#endif
 
 #  include <stdio.h>
 #  include <string.h>
diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c
index abf6682..d2b9396 100644
--- a/libnfc/chips/pn53x.c
+++ b/libnfc/chips/pn53x.c
@@ -1208,7 +1208,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd,
         // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response
         uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL
         uint8_t abtAnticol[11];
-        if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout)) < 0) {
+        if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout) < 0) {
           log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all");
           //if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
           //  continue;
@@ -2064,7 +2064,7 @@ static int pn53x_ISO14443A_Barcode_is_present(struct nfc_device *pnd)
     }
     uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
     uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
-    if ((ret = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 1) {
+    if (nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar) < 1) {
       failures++;
     } else {
       nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);
diff --git a/libnfc/conf.c b/libnfc/conf.c
index 85a49cf..785c310 100644
--- a/libnfc/conf.c
+++ b/libnfc/conf.c
@@ -195,6 +195,8 @@ conf_parse_file(const char *filename,
           free(key);
           free(value);
         } else {
+          free(key);
+          free(value);
           log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line);
         }
       }
diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c
index b42af0e..a9c73a1 100644
--- a/libnfc/drivers/acr122_usb.c
+++ b/libnfc/drivers/acr122_usb.c
@@ -60,7 +60,9 @@ Thanks to d18c7db and Okko for example code
 #include <sys/select.h>
 #include <errno.h>
 #include <string.h>
-
+#ifdef _MSC_VER
+#include <sys/types.h>
+#endif
 #include <nfc/nfc.h>
 
 #include "nfc-internal.h"
@@ -596,7 +598,7 @@ read:
   if (timeout == USB_INFINITE_TIMEOUT) {
     usb_timeout = USB_TIMEOUT_PER_PASS;
   } else {
-    // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
+    // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
     remaining_time -= USB_TIMEOUT_PER_PASS;
     if (remaining_time <= 0) {
       pnd->last_error = NFC_ETIMEOUT;
diff --git a/libnfc/drivers/acr122s.c b/libnfc/drivers/acr122s.c
index 322a26c..7a6a9f4 100644
--- a/libnfc/drivers/acr122s.c
+++ b/libnfc/drivers/acr122s.c
@@ -527,7 +527,7 @@ acr122s_close(nfc_device *pnd)
   uart_close(DRIVER_DATA(pnd)->port);
 
 #ifndef WIN32
-  // Release file descriptors used for abort mecanism
+  // Release file descriptors used for abort mechanism
   close(DRIVER_DATA(pnd)->abort_fds[0]);
   close(DRIVER_DATA(pnd)->abort_fds[1]);
 #endif
diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c
index 4eba6b2..acaab46 100644
--- a/libnfc/drivers/arygon.c
+++ b/libnfc/drivers/arygon.c
@@ -158,7 +158,7 @@ arygon_scan(const nfc_context *context, nfc_connstring connstrings[], const size
       }
 
 #ifndef WIN32
-      // pipe-based abort mecanism
+      // pipe-based abort mechanism
       if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
         uart_close(DRIVER_DATA(pnd)->port);
         pn53x_data_free(pnd);
@@ -211,7 +211,7 @@ arygon_close_step2(nfc_device *pnd)
   uart_close(DRIVER_DATA(pnd)->port);
 
 #ifndef WIN32
-  // Release file descriptors used for abort mecanism
+  // Release file descriptors used for abort mechanism
   close(DRIVER_DATA(pnd)->iAbortFds[0]);
   close(DRIVER_DATA(pnd)->iAbortFds[1]);
 #endif
@@ -304,7 +304,7 @@ arygon_open(const nfc_context *context, const nfc_connstring connstring)
   pnd->driver = &arygon_driver;
 
 #ifndef WIN32
-  // pipe-based abort mecanism
+  // pipe-based abort mechanism
   if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
     uart_close(DRIVER_DATA(pnd)->port);
     pn53x_data_free(pnd);
diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c
index e9ad7dc..200a11d 100644
--- a/libnfc/drivers/pcsc.c
+++ b/libnfc/drivers/pcsc.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2019      Frank Morgner
  * See AUTHORS file for a more comprehensive list of contributors.
  * Additional contributors of this file:
- *
+ * Copyright (C) 2020      Feitian Technologies
  * 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
@@ -72,6 +72,11 @@
 #include <winscard.h>
 #endif
 
+#ifdef WIN32
+#include <windows.h>
+#define usleep(x) Sleep((x + 999) / 1000)
+#endif
+
 #define PCSC_DRIVER_NAME "pcsc"
 
 #include <nfc/nfc.h>
@@ -138,8 +143,14 @@ static int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t
   DWORD dw_rx_len = *rx_len;
   //in libfreefare, tx_len = 1, and it leads to 0x80100008 error, with PC/SC reader, the input tx_len at least two bytes for the SW value
   //so if found the reader is Feitian reader, we set to 2
-  if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) {
-    dw_rx_len = 2;
+  if (is_pcsc_reader_vendor_feitian(pnd))
+  {
+    if (dw_rx_len == 1)
+    {
+      dw_rx_len = 2;
+    } else {
+      dw_rx_len += 2;//in libfreefare, some data length send not include sw1 and sw2, so add it.
+    }
   }
 
   LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len);
@@ -252,7 +263,7 @@ static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
   if (pnd->last_error != NFC_SUCCESS)
     return pnd->last_error;
 
-  if (resp_len < 2) {
+  if (resp_len <= 2) {
     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS");
     pnd->last_error = NFC_EDEVNOTSUPP;
     return pnd->last_error;
@@ -263,8 +274,7 @@ static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
     return pnd->last_error;
   }
 
-  //memcpy(ats, resp + 1, resp_len - 2 - 1);
-  memcpy(ats, resp + 1, resp[0] - 1);
+  memcpy(ats, resp + 1, resp_len - 2 - 1);//data expect TL and SW1SW2
   return resp_len - 2 - 1;
 }
 
@@ -341,17 +351,23 @@ static int pcsc_props_to_target(struct nfc_device *pnd, uint8_t it, const uint8_
           if (is_pcsc_reader_vendor_feitian(pnd)) {
             uint8_t atqa[2];
             pcsc_get_atqa(pnd, atqa, sizeof(atqa));
-            //memcpy(pnt->nti.nai.abtAtqa,atqa,2);
-            pnt->nti.nai.abtAtqa[0] = atqa[1];
-            pnt->nti.nai.abtAtqa[1] = atqa[0];
+            //ATQA Coding of NXP Contactless Card ICs
+            if(atqa[0] = 0x00 || atqa[0] == 0x03)
+            {
+              memcpy(pnt->nti.nai.abtAtqa,atqa,2);
+            }else {
+              pnt->nti.nai.abtAtqa[0] = atqa[1];
+              pnt->nti.nai.abtAtqa[1] = atqa[0];
+            }
+
             uint8_t sak[1];
             pcsc_get_sak(pnd, sak, sizeof(sak));
             pnt->nti.nai.btSak = sak[0];
             uint8_t ats[256];
             int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats));
+            ats_len = (ats_len > 0 ? ats_len : 0);//The reader may not support to get ATS
             memcpy(pnt->nti.nai.abtAts, ats, ats_len);
-            //memcpy(pnt->nti.nai.abtAts + ats_len, patr + 4, (uint8_t)(szatr - 5));
-            pnt->nti.nai.szAtsLen = ats_len;// + szatr - 5;
+            pnt->nti.nai.szAtsLen = ats_len;
           } else {
             /* SAK_ISO14443_4_COMPLIANT */
             pnt->nti.nai.btSak = 0x20;
@@ -521,7 +537,7 @@ pcsc_open(const nfc_context *context, const nfc_connstring connstring)
   // Test if context succeeded
   if (!(pscc = pcsc_get_scardcontext()))
     goto error;
-  DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
+  DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0 | 1, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
   if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) {
     // We can not connect to this device.
     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed");
@@ -797,6 +813,21 @@ static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t
       memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
       send_size = 5 + szTx - 2;
     } else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A) { //Auth command
+      //load pin first
+      {
+        apdu_data[0] = 0xFF;
+        apdu_data[1] = 0x82;
+        apdu_data[2] = 0x00;
+        apdu_data[3] = 0x01;
+        apdu_data[4] = 0x06;
+        memcpy(apdu_data + 5, pbtTx + 2, 6);
+        send_size = 11;
+        pnd->last_error = pcsc_transmit(pnd, apdu_data, send_size, resp, &resp_len);
+        memset(apdu_data, 0, sizeof(apdu_data));
+        memset(resp, 0, sizeof(resp));
+        usleep(500000);//delay 500ms
+      }
+      // then auth
       apdu_data[0] = 0xFF;
       apdu_data[1] = 0x86;
       apdu_data[2] = 0x00;
@@ -884,6 +915,9 @@ static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_prope
       // ignore
       return NFC_SUCCESS;
     case NP_AUTO_ISO14443_4:
+      if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
+        return NFC_SUCCESS;
+      break;
     case NP_EASY_FRAMING:
       if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
         return NFC_SUCCESS;
@@ -936,8 +970,13 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf)
 {
   struct pcsc_data *data = pnd->driver_data;
   LPBYTE   name = NULL, version = NULL, type = NULL, serial = NULL;
+#ifdef __APPLE__
+  DWORD    name_len = 0, version_len = 0,
+           type_len = 0, serial_len = 0;
+#else
   DWORD    name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE,
            type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE;
+#endif
   int res = NFC_SUCCESS;
   SCARDCONTEXT *pscc;
 
diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c
index 6dd4a21..d82051d 100644
--- a/libnfc/drivers/pn532_uart.c
+++ b/libnfc/drivers/pn532_uart.c
@@ -136,7 +136,7 @@ pn532_uart_scan(const nfc_context *context, nfc_connstring connstrings[], const
       CHIP_DATA(pnd)->power_mode = LOWVBAT;
 
 #ifndef WIN32
-      // pipe-based abort mecanism
+      // pipe-based abort mechanism
       if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
         uart_close(DRIVER_DATA(pnd)->port);
         pn53x_data_free(pnd);
@@ -191,7 +191,7 @@ pn532_uart_close(nfc_device *pnd)
   uart_close(DRIVER_DATA(pnd)->port);
 
 #ifndef WIN32
-  // Release file descriptors used for abort mecanism
+  // Release file descriptors used for abort mechanism
   close(DRIVER_DATA(pnd)->iAbortFds[0]);
   close(DRIVER_DATA(pnd)->iAbortFds[1]);
 #endif
@@ -277,7 +277,7 @@ pn532_uart_open(const nfc_context *context, const nfc_connstring connstring)
   pnd->driver = &pn532_uart_driver;
 
 #ifndef WIN32
-  // pipe-based abort mecanism
+  // pipe-based abort mechanism
   if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
     uart_close(DRIVER_DATA(pnd)->port);
     pn53x_data_free(pnd);
diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c
index d179666..52c40f0 100644
--- a/libnfc/drivers/pn53x_usb.c
+++ b/libnfc/drivers/pn53x_usb.c
@@ -43,7 +43,9 @@ Thanks to d18c7db and Okko for example code
 #include <sys/select.h>
 #include <errno.h>
 #include <string.h>
-
+#ifdef _MSC_VER
+#include <sys/types.h>
+#endif
 #include <nfc/nfc.h>
 
 #include "nfc-internal.h"
@@ -621,7 +623,7 @@ read:
   if (timeout == USB_INFINITE_TIMEOUT) {
     usb_timeout = USB_TIMEOUT_PER_PASS;
   } else {
-    // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
+    // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
     remaining_time -= USB_TIMEOUT_PER_PASS;
     if (remaining_time <= 0) {
       pnd->last_error = NFC_ETIMEOUT;
@@ -817,7 +819,7 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const
       if (NP_ACTIVATE_FIELD == property) {
         /* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
         log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Switch progressive field %s", bEnable ? "On" : "Off");
-        if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31))) < 0)
+        if (pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31)) < 0)
           return NFC_ECHIP;
       }
       break;
diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h
index 4fa2fc2..e9015ff 100644
--- a/libnfc/nfc-internal.h
+++ b/libnfc/nfc-internal.h
@@ -34,7 +34,9 @@
 
 #include <stdbool.h>
 #include <err.h>
+#if !defined(_MSC_VER)
 #  include <sys/time.h>
+#endif
 
 #include "nfc/nfc.h"
 
diff --git a/libnfc/nfc.c b/libnfc/nfc.c
index 2d56bf6..6f58a71 100644
--- a/libnfc/nfc.c
+++ b/libnfc/nfc.c
@@ -565,24 +565,30 @@ nfc_initiator_select_passive_target(nfc_device *pnd,
                                     nfc_target *pnt)
 {
   uint8_t *abtInit = NULL;
-  uint8_t abtTmpInit[MAX(12, szInitData)];
+  uint8_t maxAbt = MAX(12, szInitData);
+  uint8_t *abtTmpInit = malloc(sizeof(uint8_t) * maxAbt);
   size_t  szInit = 0;
   int res;
-  if ((res = nfc_device_validate_modulation(pnd, N_INITIATOR, &nm)) != NFC_SUCCESS)
+  if ((res = nfc_device_validate_modulation(pnd, N_INITIATOR, &nm)) != NFC_SUCCESS) {
+    free(abtTmpInit);
     return res;
+  }
   if (szInitData == 0) {
     // Provide default values, if any
     prepare_initiator_data(nm, &abtInit, &szInit);
+    free(abtTmpInit);
   } else if (nm.nmt == NMT_ISO14443A) {
     abtInit = abtTmpInit;
     iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit);
   } else {
     abtInit = abtTmpInit;
     memcpy(abtInit, pbtInitData, szInitData);
+    free(abtTmpInit);
     szInit = szInitData;
   }
-
   HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt);
+
+  free(abtTmpInit);
 }
 
 /** @ingroup initiator
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 0e03880..273466b 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -23,7 +23,8 @@ FOREACH(source ${UTILS-SOURCES})
     SET(RC_COMMENT "${PACKAGE_NAME} utility")
     SET(RC_INTERNAL_NAME ${source})
     SET(RC_ORIGINAL_NAME ${source}.exe)
-    SET(RC_FILE_TYPE VFT_APP)
+    # RC_FILE_TYPE: VFT_APP
+    SET(RC_FILE_TYPE 0x00000001L)
     CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
     LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
   ENDIF(WIN32)
@@ -41,6 +42,9 @@ FOREACH(source ${UTILS-SOURCES})
       LIST(APPEND TARGETS ../contrib/win32/stdlib)
       INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32)
     ENDIF(${source} MATCHES "nfc-scan-device")
+    IF(${source} MATCHES "nfc-read-forum-tag3")
+      LIST(APPEND TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/getopt.c)
+    ENDIF()
   ENDIF(WIN32)
 
   ADD_EXECUTABLE(${source} ${TARGETS})
diff --git a/utils/nfc-list.c b/utils/nfc-list.c
index 9b20517..53dcf61 100644
--- a/utils/nfc-list.c
+++ b/utils/nfc-list.c
@@ -97,10 +97,6 @@ main(int argc, const char *argv[])
     exit(EXIT_FAILURE);
   }
 
-  // Display libnfc version
-  acLibnfcVersion = nfc_version();
-  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
-
   // Get commandline options
   for (arg = 1; arg < argc; arg++) {
     if (0 == strcmp(argv[arg], "-h")) {
@@ -126,6 +122,13 @@ main(int argc, const char *argv[])
     }
   }
 
+  // Display libnfc version
+  if (verbose) {
+    acLibnfcVersion = nfc_version();
+    printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
+  }
+
+
   /* Lazy way to open an NFC device */
 #if 0
   pnd = nfc_open(context, NULL);
diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c
index 6530224..244af45 100644
--- a/utils/nfc-mfclassic.c
+++ b/utils/nfc-mfclassic.c
@@ -54,6 +54,12 @@
 #include <string.h>
 #include <ctype.h>
 
+#ifndef _WIN32
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
 #include <nfc/nfc.h>
 
 #include "mifare.h"
@@ -70,8 +76,7 @@ static bool bUseKeyFile;
 static bool bForceKeyFile;
 static bool bTolerateFailures;
 static bool bFormatCard;
-static bool magic2 = false;
-static bool magic3 = false;
+static bool dWrite = false;
 static bool unlocked = false;
 static uint8_t uiBlocks;
 static uint8_t keys[] = {
@@ -211,15 +216,6 @@ authenticate(uint32_t uiBlock)
     if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
       return true;
 
-  } else if (magic3) {
-    //If it's a One Time Write card, we're gonna authenticate with the default keys
-    memcpy(mp.mpa.abtKey, default_key, sizeof(default_key));
-
-
-    // Try to authenticate for the current sector
-    if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
-      return true;
-    }
     // If formatting or not using key file, try to guess the right key
   } else if (bFormatCard || !bUseKeyFile) {
     for (size_t key_index = 0; key_index < num_keys; key_index++) {
@@ -242,7 +238,7 @@ authenticate(uint32_t uiBlock)
 }
 
 static bool
-unlock_card(void)
+unlock_card(bool write)
 {
   // Configure the CRC
   if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
@@ -260,6 +256,10 @@ unlock_card(void)
   // now send unlock
   if (!transmit_bits(abtUnlock1, 7)) {
     printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
+    dWrite = true;
+    if (write) {
+      printf("Trying to rewrite block 0 on a direct write tag.\n");
+    }
   } else {
     if (transmit_bytes(abtUnlock2, 1)) {
       printf("Card unlocked\n");
@@ -270,6 +270,15 @@ unlock_card(void)
   }
 
   // reset reader
+  if (!unlocked) {
+    if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
+      printf("Error: tag was removed\n");
+      nfc_close(pnd);
+      nfc_exit(context);
+      exit(EXIT_FAILURE);
+    }
+    return true;
+  }
   // Configure the CRC
   if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
     nfc_perror(pnd, "nfc_device_set_property_bool");
@@ -316,23 +325,19 @@ get_rats(void)
 }
 
 static bool
-read_card(int read_unlocked)
+read_card(bool read_unlocked)
 {
   int32_t iBlock;
   bool bFailure = false;
   uint32_t uiReadBlocks = 0;
 
   if (read_unlocked) {
+    unlock_card(false);
     //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
     //need to use the R mode. We'll trigger a warning and let them proceed.
-    if (magic2) {
-      printf("Note: This card does not require an unlocked read (R) \n");
+    if (dWrite) {
+      printf("Note: This card can't do an unlocked read (R) \n");
       read_unlocked = 0;
-    } else {
-      //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out.
-      if (!unlock_card()) {
-        return false;
-      }
     }
   }
 
@@ -362,18 +367,11 @@ read_card(int read_unlocked)
         if (read_unlocked) {
           memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
         } else {
-          //If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL
-          if (magic3) {
-            memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key));
-            memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
-            memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key));
-          } else {
-            // Copy the keys over from our key dump and store the retrieved access bits
-            memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
-            memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
-            memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
+           // Copy the keys over from our key dump and store the retrieved access bits
+           memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
+           memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
+           memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
           }
-        }
       } else {
         printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
         bFailure = true;
@@ -403,7 +401,7 @@ read_card(int read_unlocked)
 }
 
 static bool
-write_card(int write_block_zero)
+write_card(bool write_block_zero)
 {
   uint32_t uiBlock;
   bool bFailure = false;
@@ -411,24 +409,18 @@ write_card(int write_block_zero)
 
   //Determine if we have to unlock the card
   if (write_block_zero) {
-    //If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
-    //need to use the W mode. We'll trigger a warning and let them proceed.
-    if (magic2) {
-      printf("Note: This card does not require an unlocked write (W) \n");
-      write_block_zero = 0;
-    } else {
-      //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out.
-      if (!unlock_card()) {
-        return false;
-      }
-    }
+    unlock_card(true);
   }
 
-  printf("Writing %d blocks |", uiBlocks + 1);
-  // Completely write the card, end to start, but skipping block 0
-  for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
+  printf("Writing %d blocks |", uiBlocks + write_block_zero);
+  // Completely write the card, but skipping block 0 if we don't need to write on it
+  for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
+    //Determine if we have to write block 0
+    if (!write_block_zero && uiBlock == 0) {
+      continue;
+    }
     // Authenticate everytime we reach the first sector of a new block
-    if (is_first_block(uiBlock)) {
+    if (uiBlock == 1 || is_first_block(uiBlock)) {
       if (bFailure) {
         // When a failure occured we need to redo the anti-collision
         if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
@@ -442,14 +434,15 @@ write_card(int write_block_zero)
 
       // Try to authenticate for the current sector
       // If we are are writing to a chinese magic card, we've already unlocked
-      // If we're writing to a One Time Write card, we need to authenticate
+      // If we're writing to a direct write card, we need to authenticate
       // If we're writing something else, we'll need to authenticate
-      if ((write_block_zero && magic3) || !write_block_zero) {
+      if ((write_block_zero && dWrite) || !write_block_zero) {
         if (!authenticate(uiBlock) && !bTolerateFailures) {
           printf("!\nError: authentication failed for block %02x\n", uiBlock);
           return false;
         }
       }
+    }
 
       if (is_trailer_block(uiBlock)) {
         if (bFormatCard) {
@@ -470,10 +463,6 @@ write_card(int write_block_zero)
           bFailure = true;
         }
       } else {
-        // The first block 0x00 is read only, skip this
-        if (uiBlock == 0 && !write_block_zero && !magic2)
-          continue;
-
         // Make sure a earlier write did not fail
         if (!bFailure) {
           // Try to write the data block
@@ -484,7 +473,7 @@ write_card(int write_block_zero)
             memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
           // do not write a block 0 with incorrect BCC - card will be made invalid!
           if (uiBlock == 0) {
-            if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
+            if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) {
               printf("!\nError: incorrect BCC in MFD file!\n");
               printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
               return false;
@@ -494,88 +483,29 @@ write_card(int write_block_zero)
             bFailure = true;
             printf("Failure to write to data block %i\n", uiBlock);
           }
-
+          if (uiBlock == 0 && dWrite) {
+            if (nfc_initiator_init(pnd) < 0) {
+              nfc_perror(pnd, "nfc_initiator_init");
+              nfc_close(pnd);
+              nfc_exit(context);
+              exit(EXIT_FAILURE);
+            };
+            if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
+              printf("!\nError: tag was removed\n");
+              return false;
+            }
+          }
         } else {
           printf("Failure during write process.\n");
         }
       }
-    }
+    //}
     // Show if the write went well for each block
     print_success_or_failure(bFailure, &uiWriteBlocks);
     if ((! bTolerateFailures) && bFailure)
       return false;
   }
 
-  //Write Block 0 if necessary
-  if (write_block_zero || magic2 || magic3) {
-    for (uiBlock = 0; uiBlock < 4; uiBlock++) {
-
-      // The first block 0x00 is read only, skip this
-      if (uiBlock == 0) {
-        //If the card is not magic, we're gonna skip over
-        if (write_block_zero || magic2 || magic3) {
-          //NOP
-        } else {
-          continue;
-        }
-      }
-
-      if (is_first_block(uiBlock)) {
-        if (bFailure) {
-          // When a failure occured we need to redo the anti-collision
-          if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
-            printf("!\nError: tag was removed\n");
-            return false;
-          }
-          bFailure = false;
-        }
-
-        fflush(stdout);
-        // Try to authenticate for the current sector
-        // If we are are writing to a chinese magic card, we've already unlocked
-        // If we're writing to a One Time Write, we need to authenticate
-        // If we're writing something else, we'll need to authenticate
-        if ((write_block_zero && magic3) || !write_block_zero) {
-          if (!authenticate(uiBlock) && !bTolerateFailures) {
-            printf("!\nError: authentication failed for block %02x\n", uiBlock);
-            return false;
-          }
-        }
-      }
-
-      // Make sure a earlier write did not fail
-      if (!bFailure) {
-        // Try to write the data block
-        if (bFormatCard && uiBlock)
-          memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
-        else
-          memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
-        // do not write a block 0 with incorrect BCC - card will be made invalid!
-        if (uiBlock == 0) {
-          if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
-            printf("!\nError: incorrect BCC in MFD file!\n");
-            printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
-            return false;
-          }
-        }
-        if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
-          bFailure = true;
-          printf("Failure to write to data block %i\n", uiBlock);
-        }
-
-      } else {
-        printf("Failure during write process.\n");
-      }
-
-      // Show if the write went well for each block
-      print_success_or_failure(bFailure, &uiWriteBlocks);
-      if ((! bTolerateFailures) && bFailure)
-        return false;
-
-    }
-
-  }
-
   printf("|\n");
   printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
   fflush(stdout);
@@ -593,18 +523,24 @@ static void
 print_usage(const char *pcProgramName)
 {
   printf("Usage: ");
+  #ifndef _WIN32
+  printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f] [v]]\n", pcProgramName);
+  #else
   printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
-  printf("  f|r|R|w|W     - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");
+  #endif
+  printf("  f|r|R|w|W     - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or block 0 write to (W) card\n");
   printf("                  *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
   printf("                  *** unlocked read does not require authentication and will reveal A and B keys\n");
-  printf("                  *** note that unlocked write will attempt to overwrite block 0 including UID\n");
-  printf("                  *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
+  printf("                  *** note that block 0 write will attempt to overwrite block 0 including UID\n");
+  printf("                  *** block 0 write only works with special Mifare cards (Chinese clones)\n");
   printf("  a|A|b|B       - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
   printf("  u|U           - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
   printf("  <dump.mfd>    - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
   printf("  <keys.mfd>    - MiFare Dump (MFD) that contain the keys (optional)\n");
   printf("  f             - Force using the keyfile even if UID does not match (optional)\n");
-
+  #ifndef _WIN32
+  printf("  v             - Sends libnfc log output to console (optional)\n");
+  #endif
   printf("Examples: \n\n");
   printf("  Read card to file, using key A:\n\n");
   printf("    %s r a u mycard.mfd\n\n", pcProgramName);
@@ -620,54 +556,6 @@ print_usage(const char *pcProgramName)
 }
 
 
-static bool is_directwrite(void)
-{
-  printf("Checking if Badge is DirectWrite...\n");
-
-  // Set default keys
-  memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key));
-  memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
-  memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key));
-
-  // Temporarly override bUseKeyFile
-  bool orig_bUseKeyFile = bUseKeyFile;
-  bUseKeyFile = false;
-  // Try to authenticate for the current sector
-  if (!authenticate(0)) {
-    printf("!\nError: authentication failed for block 0x%02x\n", 0);
-    bUseKeyFile = orig_bUseKeyFile;
-    return false;
-  }
-  // restore bUseKeyFile
-  bUseKeyFile = orig_bUseKeyFile;
-
-  // Try to read block 0
-  uint8_t original_b0[16];
-  if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
-    memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData));
-    printf(" Original Block 0: ");
-    for (int i = 0; i < 16; i++) {
-      printf("%02x", original_b0[i]);
-    }
-    printf("\n");
-    printf(" Original UID: %02x%02x%02x%02x\n",
-           original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
-  } else {
-    printf("!\nError: unable to read block 0x%02x\n", 0);
-    return false;
-  }
-
-  printf(" Attempt to write Block 0 ...\n");
-  memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
-  if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
-    printf("Failure to write to data block %i\n", 0);
-    return false;
-  }
-  printf(" Block 0 written successfully\n");
-
-  return true;
-}
-
 int
 main(int argc, const char *argv[])
 {
@@ -676,7 +564,7 @@ main(int argc, const char *argv[])
   uint8_t _tag_uid[4];
   uint8_t *tag_uid = _tag_uid;
 
-  int    unlock = 0;
+  bool    unlock = false;
 
   if (argc < 2) {
     print_usage(argv[0]);
@@ -691,19 +579,19 @@ main(int argc, const char *argv[])
   if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
     atAction = ACTION_READ;
     if (strcmp(command, "R") == 0)
-      unlock = 1;
+      unlock = true;
     bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
     bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
-    bUseKeyFile = (argc > 5);
+    bUseKeyFile = (argc > 5) && strcmp(argv[5], "v");
     bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
   } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
     atAction = ACTION_WRITE;
     if (strcmp(command, "W") == 0)
-      unlock = 1;
+      unlock = true;
     bFormatCard = (strcmp(command, "f") == 0);
     bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
     bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
-    bUseKeyFile = (argc > 5);
+    bUseKeyFile = (argc > 5) && strcmp(argv[5], "v");
     bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
   }
   if (argv[3][0] == 'U') {
@@ -725,6 +613,21 @@ main(int argc, const char *argv[])
     tag_uid = NULL;
   }
 
+  #ifndef _WIN32
+    // Send noise from lib to /dev/null
+    bool verbose = false;
+    if (argv[7]) {
+      if (strcmp(argv[7], "v") == 0) verbose = true;
+    } else {
+      if ((strcmp(argv[6], "v")) || (strcmp(argv[5], "v")) == 0) verbose = true;
+    }
+    if (!verbose) {
+      int fd = open("/dev/null", O_WRONLY);
+      dup2(fd, 2);
+      close(fd);
+    }
+  #endif
+
   if (atAction == ACTION_USAGE) {
     print_usage(argv[0]);
     exit(EXIT_FAILURE);
@@ -764,6 +667,14 @@ main(int argc, const char *argv[])
     exit(EXIT_FAILURE);
   };
 
+  // Drop the field for a while, so can be reset
+  if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, true) < 0) {
+    nfc_perror(pnd, "nfc_device_set_property_bool activate field");
+    nfc_close(pnd);
+    nfc_exit(context);
+    exit(EXIT_FAILURE);
+  }
+
 // Let the reader only try once to find a tag
   if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
     nfc_perror(pnd, "nfc_device_set_property_bool");
@@ -779,11 +690,24 @@ main(int argc, const char *argv[])
     exit(EXIT_FAILURE);
   }
 
+  // Configure the CRC and Parity settings
+  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
+    nfc_perror(pnd, "nfc_device_set_property_bool crc");
+    nfc_close(pnd);
+    nfc_exit(context);
+    exit(EXIT_FAILURE);
+  }
+  if (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true) < 0) {
+    nfc_perror(pnd, "nfc_device_set_property_bool parity");
+    nfc_close(pnd);
+    nfc_exit(context);
+    exit(EXIT_FAILURE);
+  }
+
   printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
 
 // Try to find a MIFARE Classic tag
   int tags;
-
   tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
   if (tags <= 0) {
     printf("Error: no tag was found\n");
@@ -792,7 +716,8 @@ main(int argc, const char *argv[])
     exit(EXIT_FAILURE);
   }
 // Test if we are dealing with a MIFARE compatible tag
-  if ((nt.nti.nai.btSak & 0x08) == 0) {
+  if (((nt.nti.nai.btSak & 0x08) == 0) && (nt.nti.nai.btSak != 0x01)) {
+//  if ((nt.nti.nai.btSak & 0x08) == 0) {
     printf("Warning: tag is probably not a MFC!\n");
   }
 
@@ -839,35 +764,10 @@ main(int argc, const char *argv[])
       // MIFARE Plus 2K
       uiBlocks = 0x7f;
     }
-    // Chinese magic emulation card, ATS=0978009102:dabc1910
-    if ((res == 9)  && (abtRx[5] == 0xda) && (abtRx[6] == 0xbc)
-        && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
-      magic2 = true;
-    }
   } else
     printf("RATS support: no\n");
   printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block)));
 
-  //If size is 4k check for direct-write card
-  if (uiBlocks == 0xff) {
-    if (is_directwrite()) {
-      printf("Card is DirectWrite\n");
-      magic3 = true;
-      unlock = 0;
-    } else {
-      printf("Card is not DirectWrite\n");
-    }
-  }
-
-  //Check to see if we have a One Time Write badge (magic3)
-  if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 &&
-      pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
-    printf("Card appears to be a One Time Write Card..\n");
-    magic3 = true;
-    unlock = 0;
-  }
-
-
   if (bUseKeyFile) {
     FILE *pfKeys = fopen(argv[5], "rb");
     if (pfKeys == NULL) {
@@ -922,9 +822,17 @@ main(int argc, const char *argv[])
       }
       printf("Done.\n");
       fclose(pfDump);
+    } else {
+      nfc_close(pnd);
+      nfc_exit(context);
+      exit(EXIT_FAILURE);
     }
   } else if (atAction == ACTION_WRITE) {
-    write_card(unlock);
+    if (!write_card(unlock)) {
+      nfc_close(pnd);
+      nfc_exit(context);
+      exit(EXIT_FAILURE);
+    }
   }
 
   nfc_close(pnd);
diff --git a/utils/nfc-read-forum-tag3.c b/utils/nfc-read-forum-tag3.c
index bfa372b..52c6c2f 100644
--- a/utils/nfc-read-forum-tag3.c
+++ b/utils/nfc-read-forum-tag3.c
@@ -62,7 +62,7 @@
 
 #include "nfc-utils.h"
 
-#if defined(WIN32) && defined(__GNUC__) /* mingw compiler */
+#if defined(WIN32) /* mingw compiler */
 #include <getopt.h>
 #endif