Compare commits

..

No commits in common. "master" and "libnfc-1.8.0" have entirely different histories.

35 changed files with 324 additions and 2096 deletions

2
.gitignore vendored
View File

@ -7,8 +7,6 @@
*.lo *.lo
*.o *.o
*~ *~
.vs/
CMakeSettings.json
Doxyfile Doxyfile
INSTALL INSTALL
aclocal.m4 aclocal.m4

View File

@ -1,81 +1,20 @@
language: c language: c
matrix: compiler:
include: - clang
- os: windows - gcc
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 .
- os: linux env:
dist: bionic - BLD=cmake
compiler: - BLD=autoconf
- clang
addons:
apt:
packages:
- libusb-dev
- doxygen
- cmake
script:
- mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
- os: linux addons:
dist: bionic apt:
compiler: packages:
- clang - libusb-dev
addons: - doxygen
apt: - cmake
packages:
- libusb-dev
- doxygen
script:
- autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
- os: linux script:
dist: bionic - if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi
compiler: - if [ $BLD == cmake ]; then mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install; fi
- gcc
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:
- 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

View File

@ -18,12 +18,9 @@ SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
# config.h # config.h
IF(WIN32) 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) 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) 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) ELSE(WIN32)
SET(_XOPEN_SOURCE 600) SET(_XOPEN_SOURCE 600)
SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory") SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
@ -141,12 +138,9 @@ IF(NOT WIN32)
IF(LIBNFC_DRIVER_PN53X_USB) IF(LIBNFC_DRIVER_PN53X_USB)
SET(PKG_REQ ${PKG_REQ} "libusb") SET(PKG_REQ ${PKG_REQ} "libusb")
ENDIF(LIBNFC_DRIVER_PN53X_USB) 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) IF(LIBNFC_DRIVER_PCSC)
SET(PKG_REQ ${PKG_REQ} "libpcsclite") SET(PKG_REQ ${PKG_REQ} "libpcsclite")
ENDIF(LIBNFC_DRIVER_PCSC) ENDIF(LIBNFC_DRIVER_ACR122)
IF(LIBNFC_DRIVER_ACR122_PCSC) IF(LIBNFC_DRIVER_ACR122_PCSC)
SET(PKG_REQ ${PKG_REQ} "libpcsclite") SET(PKG_REQ ${PKG_REQ} "libpcsclite")
ENDIF(LIBNFC_DRIVER_ACR122_PCSC) ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
@ -158,7 +152,7 @@ ENDIF(NOT WIN32)
INCLUDE(LibnfcDrivers) INCLUDE(LibnfcDrivers)
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") IF(UNIX AND NOT APPLE)
IF(I2C_REQUIRED) IF(I2C_REQUIRED)
# Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html # Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html
INCLUDE (CheckFunctionExists) INCLUDE (CheckFunctionExists)
@ -172,7 +166,7 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
ENDIF (HAVE_CLOCK_GETTIME_IN_RT) ENDIF (HAVE_CLOCK_GETTIME_IN_RT)
ENDIF (NOT HAVE_CLOCK_GETTIME) ENDIF (NOT HAVE_CLOCK_GETTIME)
ENDIF(I2C_REQUIRED) ENDIF(I2C_REQUIRED)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") ENDIF(UNIX AND NOT APPLE)
IF(PCSC_INCLUDE_DIRS) IF(PCSC_INCLUDE_DIRS)
INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS})
@ -207,8 +201,7 @@ IF(WIN32)
SET(RC_COMMENT "${PACKAGE_NAME} library") SET(RC_COMMENT "${PACKAGE_NAME} library")
SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}") SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}")
SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll) SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll)
# RC_FILE_TYPE: VFT_DLL SET(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) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/windows/libnfc.rc @ONLY)
ENDIF(WIN32) ENDIF(WIN32)

View File

@ -2,13 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = $(LIBNFC_CFLAGS) AM_CFLAGS = $(LIBNFC_CFLAGS)
SUBDIRS = libnfc utils SUBDIRS = libnfc utils examples include contrib cmake test
if EXAMPLE_ENABLED
SUBDIRS += examples
endif
SUBDIRS += include contrib cmake test
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libnfc.pc pkgconfig_DATA = libnfc.pc

View File

@ -40,7 +40,7 @@ Some NFC drivers depend on third party software:
* acr122_pcsc: * acr122_pcsc:
- pcsc-lite https://pcsclite.apdu.fr/ - pcsc-lite http://pcsclite.alioth.debian.org/
- pcsc: - pcsc:
- Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test. - Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test.
@ -48,29 +48,12 @@ Some NFC drivers depend on third party software:
The regression test suite depends on the cutter framework: The regression test suite depends on the cutter framework:
http://cutter.sf.net http://cutter.sf.net
Building
========
Note: If working directly from a git clone of the repository, some of the files need to be generated first. To do this run
`autoreconf -vis`
Alternatively use a .tar.bz2 version of a packaged release (which already contains ./configure):
https://github.com/nfc-tools/libnfc/releases/
The build should be as simple as running these commands:
./configure
make
To build with specific driver(s), see option `--with-drivers=...` detailed in `./configure --help`.
Installation Installation
============ ============
make install See the file `INSTALL` for configure, build and install details.
You may need to grant permissions to your user to drive your device. Additionnally, you may need to grant permissions to your user to drive your device.
Under GNU/Linux systems, if you use udev, you could use the provided udev rules. Under GNU/Linux systems, if you use udev, you could use the provided udev rules.
e.g. under Debian, Ubuntu, etc. e.g. under Debian, Ubuntu, etc.
@ -102,17 +85,6 @@ file per device in a nfc/devices.d directory:
printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf
printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf
Environment Variables
=====================
You can override certain configuration options at runtime using the following environment variables:
+ `LIBNFC_DEFAULT_DEVICE=<connstring>`: `LIBNFC_DEFAULT_DEVICE=pn532_uart:/dev/ttyACM0` will use pn532 on /dev/ttyACM0 as default device
+ `LIBNFC_DEVICE=<connstring>` will ignore all devices in the config files and use only the one defined in the variable
+ `LIBNFC_AUTO_SCAN=<true|false>` overrides `allow_autoscan` option in the config file
+ `LIBNFC_INTRUSIVE_SCAN=<true|false>` overrides `allow_intrusive_scan` option in the config file
+ `LIBNFC_LOG_LEVEL=<0|1|2|3>` overrides `log_level` option in the config file
To obtain the connstring of a recognized device, you can use `nfc-scan-device`: `LIBNFC_AUTO_SCAN=true nfc-scan-device` will show the names & connstrings of all found devices.
How to report bugs How to report bugs
================== ==================
@ -168,6 +140,18 @@ Patches can be posted to https://github.com/nfc-tools/libnfc/issues
If the patch fixes a bug, it is usually a good idea to include If the patch fixes a bug, it is usually a good idea to include
all the information described in "How to Report Bugs". all the information described in "How to Report Bugs".
Building
========
It should be as simple as running these two commands:
./configure
make
To build with specific driver(s), see option `--with-drivers=...` detailed in `./configure --help`.
Note: if you're using directly the development repository and not the release sources, you will have to execute firstly `autoreconf -vis`.
Troubleshooting Troubleshooting
=============== ===============

View File

@ -26,15 +26,9 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
IF(NOT LIBUSB_FOUND) IF(NOT LIBUSB_FOUND)
IF(WIN32) IF(WIN32)
IF(MINGW) FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramFiles}/LibUSB-Win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
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 "$ENV{ProgramFiles}/LibUSB-Win32/lib/gcc")
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/lib/gcc") SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramFiles}/LibUSB-Win32/bin/x86/")
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 # Must fix up variable to avoid backslashes during packaging
STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR}) STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR})
ELSE(WIN32) ELSE(WIN32)

View File

@ -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_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_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)")
SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)") SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)")
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") IF(WIN32)
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)")
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
SET(LIBNFC_DRIVER_PN532_I2C OFF CACHE BOOL "Enable PN532 I2C support (Use I2C bus)") 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)") SET(LIBNFC_DRIVER_PN532_SPI OFF CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") ELSE(WIN32)
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)
SET(LIBNFC_DRIVER_PN532_UART ON CACHE BOOL "Enable PN532 UART support (Use serial port)") 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)") SET(LIBNFC_DRIVER_PN53X_USB ON CACHE BOOL "Enable PN531 and PN531 USB support (Depends on libusb)")
@ -68,11 +68,4 @@ IF(LIBNFC_DRIVER_PN53X_USB)
SET(USB_REQUIRED TRUE) SET(USB_REQUIRED TRUE)
ENDIF(LIBNFC_DRIVER_PN53X_USB) 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) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers)

View File

@ -157,14 +157,6 @@ then
fi fi
AM_CONDITIONAL(DOC_ENABLED, [test x"$enable_doc" = xyes]) 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 # Dependencies
PKG_CONFIG_REQUIRES="" PKG_CONFIG_REQUIRES=""
@ -183,10 +175,7 @@ if test x$ac_cv_with_cutter = xyes -a x$ac_cv_use_cutter = xno; then
fi fi
AM_CONDITIONAL([WITH_CUTTER], [test "$ac_cv_use_cutter" != "no"]) AM_CONDITIONAL([WITH_CUTTER], [test "$ac_cv_use_cutter" != "no"])
if test x"$enable_example" = "xyes"
then
AC_CHECK_READLINE AC_CHECK_READLINE
fi
# Help us to write great code ;-) # Help us to write great code ;-)
CFLAGS="$CFLAGS -Wall -pedantic -Wextra" CFLAGS="$CFLAGS -Wall -pedantic -Wextra"

View File

@ -1,870 +0,0 @@
/*
* 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*/

View File

@ -1,106 +0,0 @@
#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 */
}

View File

@ -1,13 +0,0 @@
#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

View File

@ -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); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Timeouts are set to %lu ms", timeout_ms);
// TODO Enhance the reception method // TODO Enhance the reception method
// - According to MSDN, it could be better to implement nfc_abort_command() mechanism using Cancello() // - According to MSDN, it could be better to implement nfc_abort_command() mecanism using Cancello()
volatile bool *abort_flag_p = (volatile bool *)abort_p; volatile bool *abort_flag_p = (volatile bool *)abort_p;
do { do {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ReadFile"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ReadFile");

View File

@ -39,7 +39,6 @@ EXPORTS
nfc_device_get_supported_baud_rate_target_mode nfc_device_get_supported_baud_rate_target_mode
nfc_device_set_property_int nfc_device_set_property_int
nfc_device_set_property_bool nfc_device_set_property_bool
nfc_emulate_target
iso14443a_crc iso14443a_crc
iso14443a_crc_append iso14443a_crc_append
iso14443b_crc iso14443b_crc
@ -51,7 +50,3 @@ EXPORTS
str_nfc_modulation_type str_nfc_modulation_type
str_nfc_baud_rate str_nfc_baud_rate
str_nfc_target str_nfc_target
pn53x_transceive
pn532_SAMConfiguration
pn53x_read_register
pn53x_write_register

View File

@ -1,57 +0,0 @@
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

View File

@ -1,9 +1,15 @@
#include "windows.h"
1 VERSIONINFO 1 VERSIONINFO
FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0 FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0 PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L #ifdef _DEBUG
FILEOS 0x00040004L FILEFLAGS VS_FF_DEBUG|VS_FF_PRERELEASE
#else
FILEFLAGS 0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE @RC_FILE_TYPE@ FILETYPE @RC_FILE_TYPE@
FILESUBTYPE 0x0L FILESUBTYPE 0x0L
BEGIN BEGIN

View File

@ -48,9 +48,7 @@
# define ENOTSUP WSAEOPNOTSUPP # define ENOTSUP WSAEOPNOTSUPP
# define ECONNABORTED WSAECONNABORTED # define ECONNABORTED WSAECONNABORTED
# else # else
#ifndef _MSC_VER
# define snprintf sprintf_s # define snprintf sprintf_s
#endif
# define strdup _strdup # define strdup _strdup
# endif # endif

View File

@ -8,7 +8,6 @@ SET(EXAMPLES-SOURCES
nfc-mfsetuid nfc-mfsetuid
nfc-poll nfc-poll
nfc-relay nfc-relay
nfc-st25tb
pn53x-diagnose pn53x-diagnose
pn53x-sam pn53x-sam
pn53x-tamashell pn53x-tamashell
@ -24,15 +23,9 @@ FOREACH(source ${EXAMPLES-SOURCES})
SET(RC_COMMENT "${PACKAGE_NAME} example") SET(RC_COMMENT "${PACKAGE_NAME} example")
SET(RC_INTERNAL_NAME ${source}) SET(RC_INTERNAL_NAME ${source})
SET(RC_ORIGINAL_NAME ${source}.exe) SET(RC_ORIGINAL_NAME ${source}.exe)
# RC_FILE_TYPE: VFT_APP SET(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) 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) LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
IF(${source} MATCHES "nfc-st25tb")
LIST(APPEND TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/getopt.c)
ENDIF()
ENDIF(WIN32) ENDIF(WIN32)
ADD_EXECUTABLE(${source} ${TARGETS}) ADD_EXECUTABLE(${source} ${TARGETS})

View File

@ -10,7 +10,6 @@ bin_PROGRAMS = \
nfc-mfsetuid \ nfc-mfsetuid \
nfc-poll \ nfc-poll \
nfc-relay \ nfc-relay \
nfc-st25tb \
pn53x-diagnose \ pn53x-diagnose \
pn53x-sam pn53x-sam
@ -64,9 +63,6 @@ nfc_mfsetuid_SOURCES = nfc-mfsetuid.c
nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.la \ nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.la \
$(top_builddir)/utils/libnfcutils.la $(top_builddir)/utils/libnfcutils.la
nfc_st25tb_SOURCES = nfc-st25tb.c
nfc_st25tb_LDADD = $(top_builddir)/libnfc/libnfc.la
pn53x_diagnose_SOURCES = pn53x-diagnose.c pn53x_diagnose_SOURCES = pn53x-diagnose.c
pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \ pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \
$(top_builddir)/utils/libnfcutils.la $(top_builddir)/utils/libnfcutils.la

View File

@ -1,600 +0,0 @@
/*-
* Free/Libre Near Field Communication (NFC) library
*
* Libnfc historical contributors:
* Copyright (C) 2009 Roel Verdult
* Copyright (C) 2009-2013 Romuald Conty
* Copyright (C) 2010-2012 Romain Tartière
* Copyright (C) 2010-2013 Philippe Teuwen
* Copyright (C) 2012-2013 Ludovic Rousseau
* See AUTHORS file for a more comprehensive list of contributors.
* Additional contributors of this file:
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-st25tb.c
* @brief Tool to operate on ISO-14443-B ST25TB* and legacy SR* cards
*/
/* Benjamin DELPY `gentilkiwi`
* https://blog.gentilkiwi.com
* benjamin@gentilkiwi.com
* Licence : https://creativecommons.org/licenses/by/4.0/
* Rely on : libnfc - https://github.com/nfc-tools/libnfc
*
* $ gcc -Wall -lnfc -o nfc-st25tb nfc-st25tb.c
* $ ./nfc-st25tb -h
*
* Tested with
* - ST25TB512-AC - (BE/Brussels/STIB ; AliExpress ones)
* - ST25TB512-AT - (FR/Lille/Ilevia ; FR/Reims/Citura ; FR/Dijon/Divia ; FR/Strasbourg/CTS)
* - SRT512 - legacy - (FR/Bordeaux/TBM)
* - SRI512 - legacy - (anonymous vending machine)
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <nfc/nfc.h>
#if defined(WIN32) /* mingw compiler */
#include <getopt.h>
#endif
#define ST25TB_SR_BLOCK_MAX_SIZE ((uint8_t) 4) // for static arrays
typedef void(*get_info_specific) (uint8_t * systemArea);
typedef struct _st_data {
uint8_t chipId;
bool bIsLegacy;
const char *szName;
const char *szDatasheetUrl;
uint8_t blockSize;
uint8_t nbNormalBlock;
uint8_t bnSystem;
get_info_specific pfnGetInfo;
} st_data;
bool get_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt);
bool set_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt);
bool set_block_at_confirmed(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt);
const st_data * get_info(const nfc_target *pnt, bool bPrintIt);
void display_system_info(nfc_device *pnd, const st_data * stdata);
void print_hex(const uint8_t *pbtData, const size_t szBytes);
int main(int argc, char *argv[])
{
nfc_context *context = NULL;
nfc_device *pnd = NULL;
nfc_target nt = {0};
nfc_modulation nm = {NMT_ISO14443B2SR, NBR_106};
const st_data * stcurrent;
int opt, res;
bool bIsBlock = false, bIsRead = false, bIsWrite = false, bIsBadCli = false;
uint8_t i, blockNumber = 0, data[ST25TB_SR_BLOCK_MAX_SIZE] = {0xff, 0xff, 0xff, 0xff}; // just in case...
size_t cbData = 0;
while(!bIsBadCli && ((opt = getopt(argc, argv, ":hib:rw:")) != -1))
{
switch(opt)
{
case 'i':
break;
case 'b':
if(optarg)
{
bIsBlock = true;
blockNumber = strtoul(optarg, NULL, 0);
}
else bIsBadCli = true;
break;
case 'r':
bIsRead = true;
break;
case 'w':
if(optarg)
{
cbData = strlen(optarg);
if((cbData == (2*2)) || ((cbData == (4*2))))
{
cbData >>= 1;
if(cbData == 2) // sr176
{
res = sscanf(optarg, "%02hhx%02hhx", data, data + 1);
}
else // all others
{
res = sscanf(optarg, "%02hhx%02hhx%02hhx%02hhx", data, data + 1, data + 2, data + 3);
}
if(res == (int) cbData)
{
bIsWrite = true;
}
}
if(!bIsWrite)
{
bIsBadCli = true;
}
}
break;
default: // includes -h
bIsBadCli = true;
}
}
if(!bIsBadCli)
{
if(bIsBlock && (bIsRead || bIsWrite))
{
if(bIsRead && bIsWrite)
{
printf("|mode : read then write\n");
}
else if(bIsRead)
{
printf("|mode : read\n");
}
else if(bIsWrite)
{
printf("|mode : write\n");
}
printf("|blk num: 0x%02hhx\n", blockNumber);
if(bIsWrite)
{
printf("|data : ");
print_hex(data, cbData);
printf("\n");
}
}
else if(!bIsRead && !bIsWrite && !bIsBlock)
{
printf("|mode : info\n");
}
else bIsBadCli = true;
}
if(!bIsBadCli)
{
nfc_init(&context);
if(context)
{
pnd = nfc_open(context, NULL);
if(pnd)
{
res = nfc_initiator_init(pnd);
if(res == NFC_SUCCESS)
{
printf("Reader : %s - via %s\n ...wait for card...\n", nfc_device_get_name(pnd), nfc_device_get_connstring(pnd));
if (nfc_initiator_select_passive_target(pnd, nm, NULL, 0, &nt) > 0)
{
stcurrent = get_info(&nt, true);
if(stcurrent)
{
printf("\n");
if(bIsBlock && (bIsRead || bIsWrite))
{
if(bIsRead)
{
get_block_at(pnd, blockNumber, NULL, 0, true);
}
if(bIsWrite)
{
set_block_at_confirmed(pnd, blockNumber, data, cbData, true);
}
}
else if(!bIsRead && !bIsWrite && !bIsBlock)
{
for(i = 0; i < stcurrent->nbNormalBlock; i++)
{
get_block_at(pnd, i, NULL, 0, true);
}
display_system_info(pnd, stcurrent);
}
}
}
}
else printf("ERROR - nfc_initiator_init: %i\n", res);
nfc_close(pnd);
}
else printf("ERROR - nfc_open\n");
nfc_exit(context);
}
else printf("ERROR - nfc_init\n");
}
else
{
printf(
"Usage:\n"
" %s [-i]\n"
" %s -b N -r\n"
" %s -b N [-r] -w ABCD[EF01]\n %s -h\n"
"Options:\n"
" -i (default) information mode - will try to dump the tag content and display informations\n"
" -b N specify block number to operate on (tag dependent), needed for read (-r) and write (-w) modes\n"
" -r read mode - will try to read block (specified with -b N parameter)\n"
" -w ABCD[EF01] write mode - will try to write specicied data (2 or 4 bytes depending on tag) to block (specified with -b N parameter)\n"
" -h this help\n"
"Examples:\n"
" %s -i\n"
" Display all tag informations\n"
" %s -b 0x0e -r\n"
" Read block 0x0e (14) of the tag\n"
" %s -b 0x0d -w 0123abcd\n"
" Write block 0x0d (13) of the tag with hexadecimal value '01 23 ab cd'\n"
" %s -b 0x0c -r -w 0123abcd\n"
" Read, then write block 0x0c (12) of the tag with hexadecimal value '01 23 ab cd'\n"
"Warnings:\n"
" Be careful with: system area, counters & otp, bytes order.\n"
, argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0]);
}
return 0;
}
bool get_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
{
bool bRet = false;
uint8_t tx[2] = {0x08, block}, rx[ST25TB_SR_BLOCK_MAX_SIZE]; // 4 is the maximum, SR176 (only 2) will fit
int res;
res = nfc_initiator_transceive_bytes(pnd, tx, sizeof(tx), rx, sizeof(rx), 0);
if((res == 2) || (res == 4))
{
if(data)
{
if(cbData == res)
{
memcpy(data, rx, res);
bRet = true;
}
else printf("ERROR - We got %i bytes for a %hhu buffer size?\n", res, cbData);
}
else bRet = true;
if(bPrintIt)
{
printf("[0x%02hhx] ", block);
print_hex(rx, res);
printf("\n");
}
}
else if(res > 0)
{
printf("ERROR - We got %i bytes?\n", res);
}
else printf("ERROR - nfc_initiator_transceive_bytes(get): %i\n", res);
return bRet;
}
bool set_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
{
bool bRet = false;
uint8_t tx[2 + ST25TB_SR_BLOCK_MAX_SIZE] = {0x09, block}; // 4 is the maximum, SR176 (only 2) will fit
int res;
if(cbData <= ST25TB_SR_BLOCK_MAX_SIZE)
{
memcpy(tx + 2, data, cbData);
if(bPrintIt)
{
printf(">0x%02hhx> ", block);
print_hex(data, cbData);
printf("\n");
}
res = nfc_initiator_transceive_bytes(pnd, tx, 2 + cbData, NULL, 0, 0);
if(res == NFC_ERFTRANS) // ? :')
{
bRet = true;
}
else printf("ERROR - nfc_initiator_transceive_bytes(set): %i\n", res);
}
else printf("ERROR - Wanted to write %hhu bytes, but maximum is %hhu\n", cbData, ST25TB_SR_BLOCK_MAX_SIZE);
return bRet;
}
bool set_block_at_confirmed(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
{
bool bRet = false;
uint8_t buffer[ST25TB_SR_BLOCK_MAX_SIZE]; // maximum size will be checked in set_block_at
if(set_block_at(pnd, block, data, cbData, bPrintIt))
{
if(get_block_at(pnd, block, buffer, cbData, bPrintIt))
{
if(memcmp(data, buffer, cbData) == 0)
{
bRet = true;
}
else if(bPrintIt)
{
printf("WARNING - not same value readed after write\n");
}
}
}
return bRet;
}
void get_info_st25tb512(uint8_t * systemArea)
{
uint8_t b, i;
b = ((*(uint32_t *) systemArea) >> 15) & 1;
printf(" | ST reserved : ");
for(i = 0; i < 15; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ? "not " : "");
for(i = 16; i < 32; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n");
for(i = 16; i < 32; i++)
{
if(!(((*(uint32_t *) systemArea) >> i) & 1))
{
printf(" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
}
}
}
void get_info_st25tb2k_4k(uint8_t * systemArea)
{
uint8_t b, i;
b = ((*(uint32_t *) systemArea) >> 15) & 1;
printf(" | ST reserved : ");
for(i = 0; i < 15; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_RegU: ", b, b ? "not " : "");
for(i = 16; i < 24; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n | OTP_Lock_Reg : ");
for(i = 24; i < 32; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n");
if(!(((*(uint32_t *) systemArea) >> 24) & 1))
{
printf(" blocks 0x07 and 0x08 are write protected\n");
}
for(i = 25; i < 32; i++)
{
if(!(((*(uint32_t *) systemArea) >> i) & 1))
{
printf(" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
}
}
}
void get_info_sr176_legacy(uint8_t * systemArea)
{
uint8_t i;
printf(" | Fixed Chip_ID: 0x%1x\n | ST reserved : ", systemArea[0] & 0x0f);
for(i = 4; i < 8; i++)
{
printf("%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
}
printf("\n | OTP_Lock_Reg : ");
for(i = 8; i < 16; i++)
{
printf("%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
}
printf("\n");
for(i = 8; i < 16; i++)
{
if(((*(uint16_t *) systemArea) >> i) & 1)
{
printf(" blocks 0x%02hhx and 0x%02hhx are write protected\n", (uint8_t) ((i - 8) * 2), (uint8_t) (((i - 8) * 2) + 1));
}
}
}
void get_info_sri_srt_512_legacy(uint8_t * systemArea)
{
uint8_t b, i;
b = ((*(uint32_t *) systemArea) >> 15) & 1;
printf(" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
for(i = 8; i < 15; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ? "not " : "");
for(i = 16; i < 32; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n");
for(i = 16; i < 32; i++)
{
if(!(((*(uint32_t *) systemArea) >> i) & 1))
{
printf(" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
}
}
}
void get_info_sri2k_4k_srix4k_srix512_legacy(uint8_t * systemArea)
{
uint8_t i;
printf(" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
for(i = 8; i < 24; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n | OTP_Lock_Reg : ");
for(i = 24; i < 32; i++)
{
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
}
printf("\n");
if(!(((*(uint32_t *) systemArea) >> 24) & 1))
{
printf(" blocks 0x07 and 0x08 are write protected\n");
}
for(i = 25; i < 32; i++)
{
if(!(((*(uint32_t *) systemArea) >> i) & 1))
{
printf(" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
}
}
}
const st_data STRefs[] = {
{0x1b, false, "ST25TB512-AC", "https://www.st.com/resource/en/datasheet/st25tb512-ac.pdf", 4, 16, 255, get_info_st25tb512},
{0x33, false, "ST25TB512-AT", "https://www.st.com/resource/en/datasheet/st25tb512-at.pdf", 4, 16, 255, get_info_st25tb512},
{0x3f, false, "ST25TB02K", "https://www.st.com/resource/en/datasheet/st25tb02k.pdf", 4, 64, 255, get_info_st25tb2k_4k},
{0x1f, false, "ST25TB04K", "https://www.st.com/resource/en/datasheet/st25tb04k.pdf", 4, 128, 255, get_info_st25tb2k_4k},
};
const st_data STRefs_legacy[] = {
{ 0, true, "SRI4K(s)", NULL, 4, 128, 255, NULL},
{ 2, true, "SR176", "https://www.st.com/resource/en/datasheet/sr176.pdf", 2, 15, 15, get_info_sr176_legacy},
{ 3, true, "SRIX4K", NULL, 4, 128, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
{ 4, true, "SRIX512", "https://www.st.com/resource/en/datasheet/srix512.pdf", 4, 16, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
{ 6, true, "SRI512", "https://www.st.com/resource/en/datasheet/sri512.pdf", 4, 16, 255, get_info_sri_srt_512_legacy},
{ 7, true, "SRI4K", "https://www.st.com/resource/en/datasheet/sri4k.pdf", 4, 128, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
{12, true, "SRT512", "https://www.st.com/resource/en/datasheet/srt512.pdf", 4, 16, 255, get_info_sri_srt_512_legacy},
{15, true, "SRI2K", "https://www.st.com/resource/en/datasheet/sri2k.pdf", 4, 64, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
};
const st_data * get_info(const nfc_target *pnt, bool bPrintIt)
{
const st_data *currentData = NULL;
const uint8_t *p;
uint8_t chipId, i;
if(pnt->nm.nmt == NMT_ISO14443B2SR)
{
printf("Target : %s (%s)\nUID : ", str_nfc_modulation_type(pnt->nm.nmt), str_nfc_baud_rate(pnt->nm.nbr));
print_hex(pnt->nti.nsi.abtUID, sizeof(pnt->nti.nsi.abtUID));
printf("\n");
p = pnt->nti.nsi.abtUID;
if(p[7] == 0xd0) // ST25TB* / SR*
{
chipId = p[5];
printf("Manuf : 0x%02hhx - %s\n", p[6], (p[6] == 0x02) ? "STMicroelectronics" : "other");
for(i = 0; i < (sizeof(STRefs) / sizeof(STRefs[0])); i++)
{
if(chipId == STRefs[i].chipId)
{
currentData = &STRefs[i];
break;
}
}
if(!currentData)
{
chipId >>= 2;
for(i = 0; i < (sizeof(STRefs_legacy) / sizeof(STRefs_legacy[0])); i++)
{
if(chipId == STRefs_legacy[i].chipId)
{
currentData = &STRefs_legacy[i];
break;
}
}
}
if(bPrintIt && currentData)
{
printf("ChipId : 0x%02hhx - %s%s\nSerial : 0x", currentData->chipId, currentData->szName, currentData->bIsLegacy ? " (legacy)" : "");
if(currentData->bIsLegacy)
{
printf("%1hhx", (uint8_t) (p[5] & 0x03));
}
printf("%02hhx%02hhx%02hhx%02hhx%02hhx\n|blk sz : %hhu bits\n|nb blks: %hhu\n|sys idx: %hhu\n", p[4], p[3], p[2], p[1], p[0], (uint8_t) (currentData->blockSize * 8), currentData->nbNormalBlock, currentData->bnSystem);
}
}
else printf("WARNI - Last byte of UID isn\'t 0xd0, but 0x%02hhx (not ST25TB / SR series?)\n", p[7]);
}
else printf("ERROR - not a NMT_ISO14443B2SR ?\n");
return currentData;
}
void display_system_info(nfc_device *pnd, const st_data * stdata)
{
uint8_t systemArea[ST25TB_SR_BLOCK_MAX_SIZE];
if(get_block_at(pnd, stdata->bnSystem, systemArea, stdata->blockSize, true))
{
if(stdata->pfnGetInfo)
{
stdata->pfnGetInfo(systemArea);
}
}
}
void print_hex(const uint8_t *pbtData, const size_t szBytes)
{
size_t szPos;
for (szPos = 0; szPos < szBytes; szPos++)
{
printf("%02hhx ", pbtData[szPos]);
}
}

View File

@ -5,9 +5,6 @@ IF(WIN32)
# Add in the rc for version information in the dll # Add in the rc for version information in the dll
LIST(APPEND WINDOWS_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/../windows/libnfc.rc) 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) ENDIF(WIN32)
# Library's chips # Library's chips
@ -29,23 +26,23 @@ IF(UART_REQUIRED)
ENDIF(UART_REQUIRED) ENDIF(UART_REQUIRED)
IF(I2C_REQUIRED) IF(I2C_REQUIRED)
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") IF(WIN32)
LIST(APPEND BUSES_SOURCES buses/i2c) # Windows is not supported at the moment
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# Only Linux is supported at the moment
#LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/i2c) #LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/i2c)
MESSAGE( FATAL_ERROR "I2C is only (yet) supported in Linux!" ) MESSAGE( FATAL_ERROR "I2C not (yet) supported under Windows!" )
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") ELSE(WIN32)
LIST(APPEND BUSES_SOURCES buses/i2c)
ENDIF(WIN32)
ENDIF(I2C_REQUIRED) ENDIF(I2C_REQUIRED)
IF(SPI_REQUIRED) IF(SPI_REQUIRED)
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") IF(WIN32)
LIST(APPEND BUSES_SOURCES buses/spi) # Windows is not supported at the moment
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# Only Linux is supported at the moment
#LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/spi) #LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/spi)
MESSAGE( FATAL_ERROR "SPI is only (yet) supported in Linux!" ) MESSAGE( FATAL_ERROR "SPI not (yet) supported under Windows!" )
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") ELSE(WIN32)
LIST(APPEND BUSES_SOURCES buses/spi)
ENDIF(WIN32)
ENDIF(SPI_REQUIRED) ENDIF(SPI_REQUIRED)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses)
@ -66,9 +63,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
IF(LIBNFC_LOG) IF(LIBNFC_LOG)
IF(WIN32) IF(WIN32)
IF(MINGW) SET(CMAKE_C_FLAGS "-fgnu89-inline ${CMAKE_C_FLAGS}")
SET(CMAKE_C_FLAGS "-fgnu89-inline ${CMAKE_C_FLAGS}")
ENDIF(MINGW)
LIST(APPEND LIBRARY_SOURCES log ../contrib/win32/libnfc/log-internal) LIST(APPEND LIBRARY_SOURCES log ../contrib/win32/libnfc/log-internal)
ELSE(WIN32) ELSE(WIN32)
LIST(APPEND LIBRARY_SOURCES log log-internal) LIST(APPEND LIBRARY_SOURCES log log-internal)
@ -93,16 +88,13 @@ SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 6 VERSION 6.0.0)
IF(WIN32) IF(WIN32)
# Libraries that are windows specific # Libraries that are windows specific
TARGET_LINK_LIBRARIES(nfc wsock32) TARGET_LINK_LIBRARIES(nfc wsock32)
IF(MINGW)
ADD_CUSTOM_COMMAND( ADD_CUSTOM_COMMAND(
OUTPUT libnfc.lib 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 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 DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def
) )
ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib) 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 # 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 # directory as the excutables or in the path, we add it to same directory

View File

@ -33,9 +33,7 @@
#ifndef __NFC_BUS_UART_H__ #ifndef __NFC_BUS_UART_H__
# define __NFC_BUS_UART_H__ # define __NFC_BUS_UART_H__
#if !defined(_MSC_VER)
# include <sys/time.h> # include <sys/time.h>
#endif
# include <stdio.h> # include <stdio.h>
# include <string.h> # include <string.h>

View File

@ -1155,14 +1155,6 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd,
uint8_t abtRx[1]; uint8_t abtRx[1];
uint8_t *pbtInitData = (uint8_t *) "\x0b"; uint8_t *pbtInitData = (uint8_t *) "\x0b";
size_t szInitData = 1; size_t szInitData = 1;
if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_TxAuto, 0xef, 0x07)) < 0) // Initial RFOn, Tx2 RFAutoEn, Tx1 RFAutoEn
return res;
if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_CWGsP, 0x3f, 0x3f)) < 0) // Conductance of the P-Driver
return res;
if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_ModGsP, 0x3f, 0x12)) < 0) // Driver P-output conductance for the time of modulation
return res;
// Getting random Chip_ID // Getting random Chip_ID
if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) { if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) {
if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
@ -1216,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 // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response
uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL
uint8_t abtAnticol[11]; uint8_t abtAnticol[11];
if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout) < 0) { if ((res = 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"); 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 //if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
// continue; // continue;
@ -2072,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 abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN]; uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
if (nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar) < 1) { if ((ret = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 1) {
failures++; failures++;
} else { } else {
nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true); nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);

View File

@ -195,8 +195,6 @@ conf_parse_file(const char *filename,
free(key); free(key);
free(value); free(value);
} else { } else {
free(key);
free(value);
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line);
} }
} }

View File

@ -60,9 +60,7 @@ Thanks to d18c7db and Okko for example code
#include <sys/select.h> #include <sys/select.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#ifdef _MSC_VER
#include <sys/types.h>
#endif
#include <nfc/nfc.h> #include <nfc/nfc.h>
#include "nfc-internal.h" #include "nfc-internal.h"
@ -598,7 +596,7 @@ read:
if (timeout == USB_INFINITE_TIMEOUT) { if (timeout == USB_INFINITE_TIMEOUT) {
usb_timeout = USB_TIMEOUT_PER_PASS; usb_timeout = USB_TIMEOUT_PER_PASS;
} else { } else {
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
remaining_time -= USB_TIMEOUT_PER_PASS; remaining_time -= USB_TIMEOUT_PER_PASS;
if (remaining_time <= 0) { if (remaining_time <= 0) {
pnd->last_error = NFC_ETIMEOUT; pnd->last_error = NFC_ETIMEOUT;
@ -612,7 +610,6 @@ read:
uint8_t attempted_response = RDR_to_PC_DataBlock; uint8_t attempted_response = RDR_to_PC_DataBlock;
size_t len; size_t len;
int error, status;
if (res == NFC_ETIMEOUT) { if (res == NFC_ETIMEOUT) {
if (DRIVER_DATA(pnd)->abort_flag) { if (DRIVER_DATA(pnd)->abort_flag) {
@ -624,7 +621,7 @@ read:
goto read; goto read;
} }
} }
if (res < 10) { if (res < 12) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Invalid RDR_to_PC_DataBlock frame"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Invalid RDR_to_PC_DataBlock frame");
// try to interrupt current device state // try to interrupt current device state
acr122_usb_ack(pnd); acr122_usb_ack(pnd);
@ -639,16 +636,6 @@ read:
offset++; offset++;
len = abtRxBuf[offset++]; len = abtRxBuf[offset++];
status = abtRxBuf[7];
error = abtRxBuf[8];
if (len == 0 && error == 0xFE) { // ICC_MUTE; XXX check for more errors
// Do not check status; my ACR122U seemingly has status=0 in this case,
// even though the spec says it should have had bmCommandStatus=1
// and bmICCStatus=1.
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Command timed out");
pnd->last_error = NFC_ETIMEOUT;
return pnd->last_error;
}
if (!((len > 1) && (abtRxBuf[10] == 0xd5))) { // In case we didn't get an immediate answer: if (!((len > 1) && (abtRxBuf[10] == 0xd5))) { // In case we didn't get an immediate answer:
if (len != 2) { if (len != 2) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Wrong reply"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Wrong reply");
@ -677,7 +664,7 @@ read:
goto read; // FIXME May cause some trouble on Touchatag, right ? goto read; // FIXME May cause some trouble on Touchatag, right ?
} }
} }
if (res < 10) { if (res < 12) {
// try to interrupt current device state // try to interrupt current device state
acr122_usb_ack(pnd); acr122_usb_ack(pnd);
pnd->last_error = NFC_EIO; pnd->last_error = NFC_EIO;

View File

@ -527,7 +527,7 @@ acr122s_close(nfc_device *pnd)
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
#ifndef WIN32 #ifndef WIN32
// Release file descriptors used for abort mechanism // Release file descriptors used for abort mecanism
close(DRIVER_DATA(pnd)->abort_fds[0]); close(DRIVER_DATA(pnd)->abort_fds[0]);
close(DRIVER_DATA(pnd)->abort_fds[1]); close(DRIVER_DATA(pnd)->abort_fds[1]);
#endif #endif

View File

@ -158,7 +158,7 @@ arygon_scan(const nfc_context *context, nfc_connstring connstrings[], const size
} }
#ifndef WIN32 #ifndef WIN32
// pipe-based abort mechanism // pipe-based abort mecanism
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) { if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
pn53x_data_free(pnd); pn53x_data_free(pnd);
@ -211,7 +211,7 @@ arygon_close_step2(nfc_device *pnd)
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
#ifndef WIN32 #ifndef WIN32
// Release file descriptors used for abort mechanism // Release file descriptors used for abort mecanism
close(DRIVER_DATA(pnd)->iAbortFds[0]); close(DRIVER_DATA(pnd)->iAbortFds[0]);
close(DRIVER_DATA(pnd)->iAbortFds[1]); close(DRIVER_DATA(pnd)->iAbortFds[1]);
#endif #endif
@ -304,7 +304,7 @@ arygon_open(const nfc_context *context, const nfc_connstring connstring)
pnd->driver = &arygon_driver; pnd->driver = &arygon_driver;
#ifndef WIN32 #ifndef WIN32
// pipe-based abort mechanism // pipe-based abort mecanism
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) { if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
pn53x_data_free(pnd); pn53x_data_free(pnd);

View File

@ -5,7 +5,7 @@
* Copyright (C) 2019 Frank Morgner * Copyright (C) 2019 Frank Morgner
* See AUTHORS file for a more comprehensive list of contributors. * See AUTHORS file for a more comprehensive list of contributors.
* Additional contributors of this file: * Additional contributors of this file:
* Copyright (C) 2020 Feitian Technologies *
* This program is free software: you can redistribute it and/or modify it * 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 * 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 * Free Software Foundation, either version 3 of the License, or (at your
@ -34,7 +34,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <nfc/nfc.h> #include <nfc/nfc.h>
@ -73,11 +72,6 @@
#include <winscard.h> #include <winscard.h>
#endif #endif
#ifdef WIN32
#include <windows.h>
#define usleep(x) Sleep((x + 999) / 1000)
#endif
#define PCSC_DRIVER_NAME "pcsc" #define PCSC_DRIVER_NAME "pcsc"
#include <nfc/nfc.h> #include <nfc/nfc.h>
@ -144,14 +138,8 @@ static int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t
DWORD dw_rx_len = *rx_len; 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 //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 //so if found the reader is Feitian reader, we set to 2
if (is_pcsc_reader_vendor_feitian(pnd)) if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) {
{ dw_rx_len = 2;
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); LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len);
@ -264,7 +252,7 @@ static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
if (pnd->last_error != NFC_SUCCESS) if (pnd->last_error != NFC_SUCCESS)
return pnd->last_error; 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"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS");
pnd->last_error = NFC_EDEVNOTSUPP; pnd->last_error = NFC_EDEVNOTSUPP;
return pnd->last_error; return pnd->last_error;
@ -275,7 +263,8 @@ static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
return pnd->last_error; return pnd->last_error;
} }
memcpy(ats, resp + 1, resp_len - 2 - 1);//data expect TL and SW1SW2 //memcpy(ats, resp + 1, resp_len - 2 - 1);
memcpy(ats, resp + 1, resp[0] - 1);
return resp_len - 2 - 1; return resp_len - 2 - 1;
} }
@ -352,23 +341,17 @@ static int pcsc_props_to_target(struct nfc_device *pnd, uint8_t it, const uint8_
if (is_pcsc_reader_vendor_feitian(pnd)) { if (is_pcsc_reader_vendor_feitian(pnd)) {
uint8_t atqa[2]; uint8_t atqa[2];
pcsc_get_atqa(pnd, atqa, sizeof(atqa)); pcsc_get_atqa(pnd, atqa, sizeof(atqa));
//ATQA Coding of NXP Contactless Card ICs //memcpy(pnt->nti.nai.abtAtqa,atqa,2);
if(atqa[0] == 0x00 || atqa[0] == 0x03) pnt->nti.nai.abtAtqa[0] = atqa[1];
{ pnt->nti.nai.abtAtqa[1] = atqa[0];
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]; uint8_t sak[1];
pcsc_get_sak(pnd, sak, sizeof(sak)); pcsc_get_sak(pnd, sak, sizeof(sak));
pnt->nti.nai.btSak = sak[0]; pnt->nti.nai.btSak = sak[0];
uint8_t ats[256]; uint8_t ats[256];
int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats)); 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, ats_len);
pnt->nti.nai.szAtsLen = ats_len; //memcpy(pnt->nti.nai.abtAts + ats_len, patr + 4, (uint8_t)(szatr - 5));
pnt->nti.nai.szAtsLen = ats_len;// + szatr - 5;
} else { } else {
/* SAK_ISO14443_4_COMPLIANT */ /* SAK_ISO14443_4_COMPLIANT */
pnt->nti.nai.btSak = 0x20; pnt->nti.nai.btSak = 0x20;
@ -538,7 +521,7 @@ pcsc_open(const nfc_context *context, const nfc_connstring connstring)
// Test if context succeeded // Test if context succeeded
if (!(pscc = pcsc_get_scardcontext())) if (!(pscc = pcsc_get_scardcontext()))
goto error; goto error;
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)); 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));
if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) {
// We can not connect to this device. // We can not connect to this device.
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed");
@ -814,21 +797,6 @@ static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t
memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
send_size = 5 + szTx - 2; send_size = 5 + szTx - 2;
} else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A) { //Auth command } 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[0] = 0xFF;
apdu_data[1] = 0x86; apdu_data[1] = 0x86;
apdu_data[2] = 0x00; apdu_data[2] = 0x00;
@ -916,9 +884,6 @@ static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_prope
// ignore // ignore
return NFC_SUCCESS; return NFC_SUCCESS;
case NP_AUTO_ISO14443_4: case NP_AUTO_ISO14443_4:
if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
return NFC_SUCCESS;
break;
case NP_EASY_FRAMING: case NP_EASY_FRAMING:
if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd))) if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
return NFC_SUCCESS; return NFC_SUCCESS;
@ -971,13 +936,8 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf)
{ {
struct pcsc_data *data = pnd->driver_data; struct pcsc_data *data = pnd->driver_data;
LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; 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, DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE,
type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE;
#endif
int res = NFC_SUCCESS; int res = NFC_SUCCESS;
SCARDCONTEXT *pscc; SCARDCONTEXT *pscc;

View File

@ -136,7 +136,7 @@ pn532_uart_scan(const nfc_context *context, nfc_connstring connstrings[], const
CHIP_DATA(pnd)->power_mode = LOWVBAT; CHIP_DATA(pnd)->power_mode = LOWVBAT;
#ifndef WIN32 #ifndef WIN32
// pipe-based abort mechanism // pipe-based abort mecanism
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) { if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
pn53x_data_free(pnd); pn53x_data_free(pnd);
@ -191,7 +191,7 @@ pn532_uart_close(nfc_device *pnd)
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
#ifndef WIN32 #ifndef WIN32
// Release file descriptors used for abort mechanism // Release file descriptors used for abort mecanism
close(DRIVER_DATA(pnd)->iAbortFds[0]); close(DRIVER_DATA(pnd)->iAbortFds[0]);
close(DRIVER_DATA(pnd)->iAbortFds[1]); close(DRIVER_DATA(pnd)->iAbortFds[1]);
#endif #endif
@ -277,7 +277,7 @@ pn532_uart_open(const nfc_context *context, const nfc_connstring connstring)
pnd->driver = &pn532_uart_driver; pnd->driver = &pn532_uart_driver;
#ifndef WIN32 #ifndef WIN32
// pipe-based abort mechanism // pipe-based abort mecanism
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) { if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
uart_close(DRIVER_DATA(pnd)->port); uart_close(DRIVER_DATA(pnd)->port);
pn53x_data_free(pnd); pn53x_data_free(pnd);

View File

@ -43,9 +43,7 @@ Thanks to d18c7db and Okko for example code
#include <sys/select.h> #include <sys/select.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#ifdef _MSC_VER
#include <sys/types.h>
#endif
#include <nfc/nfc.h> #include <nfc/nfc.h>
#include "nfc-internal.h" #include "nfc-internal.h"
@ -623,7 +621,7 @@ read:
if (timeout == USB_INFINITE_TIMEOUT) { if (timeout == USB_INFINITE_TIMEOUT) {
usb_timeout = USB_TIMEOUT_PER_PASS; usb_timeout = USB_TIMEOUT_PER_PASS;
} else { } else {
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
remaining_time -= USB_TIMEOUT_PER_PASS; remaining_time -= USB_TIMEOUT_PER_PASS;
if (remaining_time <= 0) { if (remaining_time <= 0) {
pnd->last_error = NFC_ETIMEOUT; pnd->last_error = NFC_ETIMEOUT;
@ -819,7 +817,7 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const
if (NP_ACTIVATE_FIELD == property) { if (NP_ACTIVATE_FIELD == property) {
/* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */ /* 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"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Switch progressive field %s", bEnable ? "On" : "Off");
if (pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31)) < 0) if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31))) < 0)
return NFC_ECHIP; return NFC_ECHIP;
} }
break; break;

View File

@ -34,9 +34,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <err.h> #include <err.h>
#if !defined(_MSC_VER)
# include <sys/time.h> # include <sys/time.h>
#endif
#include "nfc/nfc.h" #include "nfc/nfc.h"

View File

@ -565,30 +565,24 @@ nfc_initiator_select_passive_target(nfc_device *pnd,
nfc_target *pnt) nfc_target *pnt)
{ {
uint8_t *abtInit = NULL; uint8_t *abtInit = NULL;
uint8_t maxAbt = MAX(12, szInitData); uint8_t abtTmpInit[MAX(12, szInitData)];
uint8_t *abtTmpInit = malloc(sizeof(uint8_t) * maxAbt);
size_t szInit = 0; size_t szInit = 0;
int res; 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; return res;
}
if (szInitData == 0) { if (szInitData == 0) {
// Provide default values, if any // Provide default values, if any
prepare_initiator_data(nm, &abtInit, &szInit); prepare_initiator_data(nm, &abtInit, &szInit);
free(abtTmpInit);
} else if (nm.nmt == NMT_ISO14443A) { } else if (nm.nmt == NMT_ISO14443A) {
abtInit = abtTmpInit; abtInit = abtTmpInit;
iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit); iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit);
} else { } else {
abtInit = abtTmpInit; abtInit = abtTmpInit;
memcpy(abtInit, pbtInitData, szInitData); memcpy(abtInit, pbtInitData, szInitData);
free(abtTmpInit);
szInit = szInitData; szInit = szInitData;
} }
HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt);
free(abtTmpInit); HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt);
} }
/** @ingroup initiator /** @ingroup initiator

View File

@ -23,8 +23,7 @@ FOREACH(source ${UTILS-SOURCES})
SET(RC_COMMENT "${PACKAGE_NAME} utility") SET(RC_COMMENT "${PACKAGE_NAME} utility")
SET(RC_INTERNAL_NAME ${source}) SET(RC_INTERNAL_NAME ${source})
SET(RC_ORIGINAL_NAME ${source}.exe) SET(RC_ORIGINAL_NAME ${source}.exe)
# RC_FILE_TYPE: VFT_APP SET(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) 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) LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
ENDIF(WIN32) ENDIF(WIN32)
@ -42,9 +41,6 @@ FOREACH(source ${UTILS-SOURCES})
LIST(APPEND TARGETS ../contrib/win32/stdlib) LIST(APPEND TARGETS ../contrib/win32/stdlib)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32)
ENDIF(${source} MATCHES "nfc-scan-device") 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) ENDIF(WIN32)
ADD_EXECUTABLE(${source} ${TARGETS}) ADD_EXECUTABLE(${source} ${TARGETS})

View File

@ -97,6 +97,10 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Display libnfc version
acLibnfcVersion = nfc_version();
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
// Get commandline options // Get commandline options
for (arg = 1; arg < argc; arg++) { for (arg = 1; arg < argc; arg++) {
if (0 == strcmp(argv[arg], "-h")) { if (0 == strcmp(argv[arg], "-h")) {
@ -113,7 +117,7 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Force TypeB for all derivatives of B // Force TypeB for all derivatives of B
if (mask & 0xd0) if (mask & 0xf0)
mask |= 0x08; mask |= 0x08;
} else { } else {
ERR("%s is not supported option.", argv[arg]); ERR("%s is not supported option.", argv[arg]);
@ -122,13 +126,6 @@ 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 */ /* Lazy way to open an NFC device */
#if 0 #if 0
pnd = nfc_open(context, NULL); pnd = nfc_open(context, NULL);

View File

@ -54,12 +54,6 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#ifndef _WIN32
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include <nfc/nfc.h> #include <nfc/nfc.h>
#include "mifare.h" #include "mifare.h"
@ -76,7 +70,8 @@ static bool bUseKeyFile;
static bool bForceKeyFile; static bool bForceKeyFile;
static bool bTolerateFailures; static bool bTolerateFailures;
static bool bFormatCard; static bool bFormatCard;
static bool dWrite = false; static bool magic2 = false;
static bool magic3 = false;
static bool unlocked = false; static bool unlocked = false;
static uint8_t uiBlocks; static uint8_t uiBlocks;
static uint8_t keys[] = { static uint8_t keys[] = {
@ -216,6 +211,15 @@ authenticate(uint32_t uiBlock)
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
return true; 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 // If formatting or not using key file, try to guess the right key
} else if (bFormatCard || !bUseKeyFile) { } else if (bFormatCard || !bUseKeyFile) {
for (size_t key_index = 0; key_index < num_keys; key_index++) { for (size_t key_index = 0; key_index < num_keys; key_index++) {
@ -238,7 +242,7 @@ authenticate(uint32_t uiBlock)
} }
static bool static bool
unlock_card(bool write) unlock_card(void)
{ {
// Configure the CRC // Configure the CRC
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) { if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
@ -256,10 +260,6 @@ unlock_card(bool write)
// now send unlock // now send unlock
if (!transmit_bits(abtUnlock1, 7)) { if (!transmit_bits(abtUnlock1, 7)) {
printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); 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 { } else {
if (transmit_bytes(abtUnlock2, 1)) { if (transmit_bytes(abtUnlock2, 1)) {
printf("Card unlocked\n"); printf("Card unlocked\n");
@ -270,15 +270,6 @@ unlock_card(bool write)
} }
// reset reader // 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 // Configure the CRC
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) { if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
nfc_perror(pnd, "nfc_device_set_property_bool"); nfc_perror(pnd, "nfc_device_set_property_bool");
@ -325,19 +316,23 @@ get_rats(void)
} }
static bool static bool
read_card(bool read_unlocked) read_card(int read_unlocked)
{ {
int32_t iBlock; int32_t iBlock;
bool bFailure = false; bool bFailure = false;
uint32_t uiReadBlocks = 0; uint32_t uiReadBlocks = 0;
if (read_unlocked) { 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 //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. //need to use the R mode. We'll trigger a warning and let them proceed.
if (dWrite) { if (magic2) {
printf("Note: This card can't do an unlocked read (R) \n"); printf("Note: This card does not require an unlocked read (R) \n");
read_unlocked = 0; 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;
}
} }
} }
@ -367,11 +362,18 @@ read_card(bool read_unlocked)
if (read_unlocked) { if (read_unlocked) {
memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData)); memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
} else { } else {
// Copy the keys over from our key dump and store the retrieved access bits //If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL
memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA)); if (magic3) {
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key));
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB)); 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));
} }
}
} else { } else {
printf("!\nfailed to read trailer block 0x%02x\n", iBlock); printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
bFailure = true; bFailure = true;
@ -401,7 +403,7 @@ read_card(bool read_unlocked)
} }
static bool static bool
write_card(bool write_block_zero) write_card(int write_block_zero)
{ {
uint32_t uiBlock; uint32_t uiBlock;
bool bFailure = false; bool bFailure = false;
@ -409,18 +411,24 @@ write_card(bool write_block_zero)
//Determine if we have to unlock the card //Determine if we have to unlock the card
if (write_block_zero) { if (write_block_zero) {
unlock_card(true); //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;
}
}
} }
printf("Writing %d blocks |", uiBlocks + write_block_zero); printf("Writing %d blocks |", uiBlocks + 1);
// Completely write the card, but skipping block 0 if we don't need to write on it // Completely write the card, end to start, but skipping block 0
for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { for (uiBlock = 4; 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 // Authenticate everytime we reach the first sector of a new block
if (uiBlock == 1 || is_first_block(uiBlock)) { if (is_first_block(uiBlock)) {
if (bFailure) { if (bFailure) {
// When a failure occured we need to redo the anti-collision // When a failure occured we need to redo the anti-collision
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
@ -434,15 +442,14 @@ write_card(bool write_block_zero)
// Try to authenticate for the current sector // Try to authenticate for the current sector
// If we are are writing to a chinese magic card, we've already unlocked // If we are are writing to a chinese magic card, we've already unlocked
// If we're writing to a direct write card, we need to authenticate // If we're writing to a One Time Write card, we need to authenticate
// If we're writing something else, we'll need to authenticate // If we're writing something else, we'll need to authenticate
if ((write_block_zero && dWrite) || !write_block_zero) { if ((write_block_zero && magic3) || !write_block_zero) {
if (!authenticate(uiBlock) && !bTolerateFailures) { if (!authenticate(uiBlock) && !bTolerateFailures) {
printf("!\nError: authentication failed for block %02x\n", uiBlock); printf("!\nError: authentication failed for block %02x\n", uiBlock);
return false; return false;
} }
} }
}
if (is_trailer_block(uiBlock)) { if (is_trailer_block(uiBlock)) {
if (bFormatCard) { if (bFormatCard) {
@ -463,6 +470,10 @@ write_card(bool write_block_zero)
bFailure = true; bFailure = true;
} }
} else { } 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 // Make sure a earlier write did not fail
if (!bFailure) { if (!bFailure) {
// Try to write the data block // Try to write the data block
@ -473,7 +484,7 @@ write_card(bool write_block_zero)
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); 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! // do not write a block 0 with incorrect BCC - card will be made invalid!
if (uiBlock == 0) { 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) { 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("!\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]); printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
return false; return false;
@ -483,29 +494,88 @@ write_card(bool write_block_zero)
bFailure = true; bFailure = true;
printf("Failure to write to data block %i\n", uiBlock); 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 { } else {
printf("Failure during write process.\n"); printf("Failure during write process.\n");
} }
} }
//} }
// Show if the write went well for each block // Show if the write went well for each block
print_success_or_failure(bFailure, &uiWriteBlocks); print_success_or_failure(bFailure, &uiWriteBlocks);
if ((! bTolerateFailures) && bFailure) if ((! bTolerateFailures) && bFailure)
return false; 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("|\n");
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
fflush(stdout); fflush(stdout);
@ -523,24 +593,18 @@ static void
print_usage(const char *pcProgramName) print_usage(const char *pcProgramName)
{ {
printf("Usage: "); 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("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
#endif 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");
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(" *** 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(" *** unlocked read does not require authentication and will reveal A and B keys\n");
printf(" *** note that block 0 write will attempt to overwrite block 0 including UID\n"); printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
printf(" *** block 0 write only works with special Mifare cards (Chinese clones)\n"); printf(" *** unlocking only works with special Mifare 1K 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(" 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(" 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(" <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(" <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"); 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("Examples: \n\n");
printf(" Read card to file, using key A:\n\n"); printf(" Read card to file, using key A:\n\n");
printf(" %s r a u mycard.mfd\n\n", pcProgramName); printf(" %s r a u mycard.mfd\n\n", pcProgramName);
@ -556,6 +620,54 @@ 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 int
main(int argc, const char *argv[]) main(int argc, const char *argv[])
{ {
@ -564,7 +676,7 @@ main(int argc, const char *argv[])
uint8_t _tag_uid[4]; uint8_t _tag_uid[4];
uint8_t *tag_uid = _tag_uid; uint8_t *tag_uid = _tag_uid;
bool unlock = false; int unlock = 0;
if (argc < 2) { if (argc < 2) {
print_usage(argv[0]); print_usage(argv[0]);
@ -579,19 +691,19 @@ main(int argc, const char *argv[])
if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) { if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
atAction = ACTION_READ; atAction = ACTION_READ;
if (strcmp(command, "R") == 0) if (strcmp(command, "R") == 0)
unlock = true; unlock = 1;
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 5) && strcmp(argv[5], "v"); bUseKeyFile = (argc > 5);
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
atAction = ACTION_WRITE; atAction = ACTION_WRITE;
if (strcmp(command, "W") == 0) if (strcmp(command, "W") == 0)
unlock = true; unlock = 1;
bFormatCard = (strcmp(command, "f") == 0); bFormatCard = (strcmp(command, "f") == 0);
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 5) && strcmp(argv[5], "v"); bUseKeyFile = (argc > 5);
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
} }
if (argv[3][0] == 'U') { if (argv[3][0] == 'U') {
@ -613,21 +725,6 @@ main(int argc, const char *argv[])
tag_uid = NULL; 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) { if (atAction == ACTION_USAGE) {
print_usage(argv[0]); print_usage(argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -667,14 +764,6 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE); 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 // Let the reader only try once to find a tag
if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) { if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
nfc_perror(pnd, "nfc_device_set_property_bool"); nfc_perror(pnd, "nfc_device_set_property_bool");
@ -690,24 +779,11 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE); 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)); printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
// Try to find a MIFARE Classic tag // Try to find a MIFARE Classic tag
int tags; int tags;
tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt); tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
if (tags <= 0) { if (tags <= 0) {
printf("Error: no tag was found\n"); printf("Error: no tag was found\n");
@ -716,8 +792,7 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Test if we are dealing with a MIFARE compatible tag // Test if we are dealing with a MIFARE compatible tag
if (((nt.nti.nai.btSak & 0x08) == 0) && (nt.nti.nai.btSak != 0x01)) { if ((nt.nti.nai.btSak & 0x08) == 0) {
// if ((nt.nti.nai.btSak & 0x08) == 0) {
printf("Warning: tag is probably not a MFC!\n"); printf("Warning: tag is probably not a MFC!\n");
} }
@ -764,10 +839,35 @@ main(int argc, const char *argv[])
// MIFARE Plus 2K // MIFARE Plus 2K
uiBlocks = 0x7f; 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 } else
printf("RATS support: no\n"); printf("RATS support: no\n");
printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block))); 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) { if (bUseKeyFile) {
FILE *pfKeys = fopen(argv[5], "rb"); FILE *pfKeys = fopen(argv[5], "rb");
if (pfKeys == NULL) { if (pfKeys == NULL) {
@ -822,17 +922,9 @@ main(int argc, const char *argv[])
} }
printf("Done.\n"); printf("Done.\n");
fclose(pfDump); fclose(pfDump);
} else {
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
} }
} else if (atAction == ACTION_WRITE) { } else if (atAction == ACTION_WRITE) {
if (!write_card(unlock)) { write_card(unlock);
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
} }
nfc_close(pnd); nfc_close(pnd);

View File

@ -62,7 +62,7 @@
#include "nfc-utils.h" #include "nfc-utils.h"
#if defined(WIN32) /* mingw compiler */ #if defined(WIN32) && defined(__GNUC__) /* mingw compiler */
#include <getopt.h> #include <getopt.h>
#endif #endif