Compare commits
No commits in common. "master" and "libnfc-1.5.0" have entirely different histories.
master
...
libnfc-1.5
64
.gitignore
vendored
64
.gitignore
vendored
@ -1,64 +0,0 @@
|
|||||||
**/.deps/
|
|
||||||
**/.libs/
|
|
||||||
**/Makefile
|
|
||||||
**/Makefile.in
|
|
||||||
*.exe
|
|
||||||
*.la
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*~
|
|
||||||
.vs/
|
|
||||||
CMakeSettings.json
|
|
||||||
Doxyfile
|
|
||||||
INSTALL
|
|
||||||
aclocal.m4
|
|
||||||
ar-lib
|
|
||||||
autom4te.cache/
|
|
||||||
build
|
|
||||||
compile
|
|
||||||
config.guess
|
|
||||||
config.h
|
|
||||||
config.h.in
|
|
||||||
config.log
|
|
||||||
config.status
|
|
||||||
config.sub
|
|
||||||
configure
|
|
||||||
debian/
|
|
||||||
depcomp
|
|
||||||
examples/nfc-anticol
|
|
||||||
examples/nfc-dep-initiator
|
|
||||||
examples/nfc-dep-target
|
|
||||||
examples/nfc-emulate-forum-tag2
|
|
||||||
examples/nfc-emulate-tag
|
|
||||||
examples/nfc-emulate-uid
|
|
||||||
examples/nfc-mfsetuid
|
|
||||||
examples/nfc-poll
|
|
||||||
examples/nfc-relay
|
|
||||||
examples/pn53x-diagnose
|
|
||||||
examples/pn53x-sam
|
|
||||||
examples/pn53x-tamashell
|
|
||||||
examples/quick_start_example1
|
|
||||||
examples/quick_start_example2
|
|
||||||
install-sh
|
|
||||||
libnfc.pc
|
|
||||||
libtool
|
|
||||||
ltmain.sh
|
|
||||||
m4/libtool.m4
|
|
||||||
m4/ltoptions.m4
|
|
||||||
m4/ltsugar.m4
|
|
||||||
m4/ltversion.m4
|
|
||||||
m4/lt~obsolete.m4
|
|
||||||
missing
|
|
||||||
stamp-h1
|
|
||||||
test-driver
|
|
||||||
test/run-test.sh.log
|
|
||||||
test/run-test.sh.trs
|
|
||||||
test/test-suite.log
|
|
||||||
utils/nfc-emulate-forum-tag4
|
|
||||||
utils/nfc-jewel
|
|
||||||
utils/nfc-list
|
|
||||||
utils/nfc-mfclassic
|
|
||||||
utils/nfc-mfultralight
|
|
||||||
utils/nfc-read-forum-tag3
|
|
||||||
utils/nfc-relay-picc
|
|
||||||
utils/nfc-scan-device
|
|
||||||
81
.travis.yml
81
.travis.yml
@ -1,81 +0,0 @@
|
|||||||
language: c
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: windows
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
before_install:
|
|
||||||
- mkdir build && cd build && wget "https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/libusb-win32-bin-1.2.6.0.zip" && 7z x libusb-win32-bin-1.2.6.0.zip -o"$PROGRAMFILES" && mv "$PROGRAMFILES/libusb-win32-bin-1.2.6.0" "$PROGRAMFILES/libusb-win32"
|
|
||||||
install:
|
|
||||||
choco install doxygen.install ninja
|
|
||||||
script:
|
|
||||||
cmake -GNinja .. && cmake --build .
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: bionic
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
- cmake
|
|
||||||
script:
|
|
||||||
- mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: bionic
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
script:
|
|
||||||
- autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: bionic
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
- cmake
|
|
||||||
script:
|
|
||||||
- mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
|
|
||||||
|
|
||||||
- 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
|
|
||||||
47
AUTHORS
47
AUTHORS
@ -1,49 +1,2 @@
|
|||||||
# Alphabetical cleaned output of "git shortlog -s -e|cut -c 8-" :
|
|
||||||
Adam Laurie <adam@algroup.co.uk>
|
|
||||||
Ahti Legonkov <ahti.legonkov@gmail.com>
|
|
||||||
Alex Lian <alian@alum.mit.edu>
|
|
||||||
Alexander Inyukhin <shurick@sectorb.msk.ru>
|
|
||||||
Anugrah Redja Kusuma <anugrah.redja@gmail.com>
|
|
||||||
Audrey Diacre <adiacre@il4p.fr>
|
|
||||||
Boris Moiseev <cyberbobs@gmail.com>
|
|
||||||
Christoph Gritschenberger <christoph.gritschenberger@gmail.com>
|
|
||||||
Dario Carluccio <dario.carluccio@gmail.com>
|
|
||||||
David Kreitschmann <david@kreitschmann.de>
|
|
||||||
Emanuele Bertoldi <emanuele.bertoldi@gmail.com>
|
|
||||||
Emmanuel Dreyfus <manu@netbsd.org>
|
|
||||||
Eugeny Boger <eugenyboger@gmail.com>
|
|
||||||
Francois Kooman <fkooman@tuxed.net>
|
|
||||||
Frank Morgner <frankmorgner@gmail.com>
|
|
||||||
Frédéric Bourgeois <bourgeoislab@gmail.com>
|
|
||||||
Hidde Wieringa <hidde@hiddewieringa.nl>
|
|
||||||
Jairo Andres Suarez <andres4005@gmail.com>
|
|
||||||
Jiapeng Li <gapleehit@gmail.com>
|
|
||||||
Jim Anastassiou <jim.anastassiou@gmail.com>
|
|
||||||
John Galt <centromere@users.noreply.github.com>
|
|
||||||
Julien Ehrhart <julien.ehrhart@live.com>
|
|
||||||
Julien Schueller <julien.schueller@gmail.com>
|
|
||||||
Laurent Latil <laurent@latil.nom.fr>
|
|
||||||
Ludovic Rousseau <ludovic.rousseau@gmail.com>
|
|
||||||
Marcello Morena <marcello.morena@gmail.com>
|
|
||||||
Marcos Vives Del Sol <socram8888@gmail.com>
|
|
||||||
Mati Vait <mativait@gmail.com>
|
|
||||||
Maxim Martyanov <llorephie@gmail.com>
|
|
||||||
Mike Auty <mike.auty@gmail.com>
|
|
||||||
Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
|
|
||||||
Olliver Schinagl <oliver@schinagl.nl>
|
|
||||||
Paul Menzel <paul.menzel@giantmonkey.de>
|
|
||||||
Peter Meerwald <pmeerw@pmeerw.net>
|
|
||||||
Philippe Teuwen <yobibe@gmail.com>
|
|
||||||
Pim 't Hart <pimmeyproductions@gmail.com>
|
|
||||||
Ray Lee <rayleesky@outlook.com>
|
|
||||||
Roel Verdult <roel@libnfc.org>
|
Roel Verdult <roel@libnfc.org>
|
||||||
Romain Tartiere <romain.tartiere@gmail.com>
|
|
||||||
Romuald Conty <romuald@libnfc.org>
|
Romuald Conty <romuald@libnfc.org>
|
||||||
Simon Yorkston <simon.yorkston@gmail.com>
|
|
||||||
bhack <s.fabri@email.it>
|
|
||||||
lego <lego@debian-fresh.prx>
|
|
||||||
quantum-x <simon.yorkston@gmail.com>
|
|
||||||
timzi <developers@make-gadget.ru>
|
|
||||||
xantares <xantares09@hotmail.com>
|
|
||||||
xaqq <kapp.arno@gmail.com>
|
|
||||||
yerzhanm <yerzhan.mukhamejan@gmail.com>
|
|
||||||
|
|||||||
241
CMakeLists.txt
241
CMakeLists.txt
@ -1,13 +1,7 @@
|
|||||||
cmake_minimum_required (VERSION 2.6)
|
PROJECT(libnfc C)
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
if (NOT DEFINED CMAKE_BUILD_TYPE)
|
|
||||||
set (CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
project (libnfc C)
|
|
||||||
|
|
||||||
SET(VERSION_MAJOR "1")
|
SET(VERSION_MAJOR "1")
|
||||||
SET(VERSION_MINOR "8")
|
SET(VERSION_MINOR "5")
|
||||||
SET(VERSION_PATCH "0")
|
SET(VERSION_PATCH "0")
|
||||||
|
|
||||||
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||||
@ -18,57 +12,25 @@ 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_SOURCE_DIR}/config.h)
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
|
||||||
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")
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
|
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
# make it easy to locate CMake modules for finding libraries
|
# make it easy to locate CMake modules for finding libraries
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/")
|
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
option (LIBNFC_LOG "Enable log facility (errors, warning, info and debug messages)" ON)
|
SET(LIBNFC_DEBUG_OUTPUT OFF CACHE BOOL "Debug output of communication with the NFC chip")
|
||||||
IF(LIBNFC_LOG)
|
IF(LIBNFC_DEBUG_OUTPUT)
|
||||||
ADD_DEFINITIONS(-DLOG)
|
ADD_DEFINITIONS(-DDEBUG -g3)
|
||||||
ENDIF(LIBNFC_LOG)
|
ENDIF(LIBNFC_DEBUG_OUTPUT)
|
||||||
|
|
||||||
option (LIBNFC_ENVVARS "Enable envvars facility" ON)
|
|
||||||
IF(LIBNFC_ENVVARS)
|
|
||||||
ADD_DEFINITIONS(-DENVVARS)
|
|
||||||
ENDIF(LIBNFC_ENVVARS)
|
|
||||||
|
|
||||||
SET(LIBNFC_DEBUG_MODE OFF CACHE BOOL "Debug mode")
|
|
||||||
IF(LIBNFC_DEBUG_MODE)
|
|
||||||
ADD_DEFINITIONS(-DDEBUG)
|
|
||||||
SET(CMAKE_C_FLAGS "-g3 ${CMAKE_C_FLAGS}")
|
|
||||||
SET(WIN32_MODE "debug")
|
|
||||||
SET(CMAKE_RC_FLAGS "-D_DEBUG ${CMAKE_RC_FLAGS}")
|
|
||||||
ELSE(LIBNFC_DEBUG_MODE)
|
|
||||||
SET(WIN32_MODE "release")
|
|
||||||
ENDIF(LIBNFC_DEBUG_MODE)
|
|
||||||
|
|
||||||
option (LIBNFC_CONFFILES_MODE "Enable configuration files" ON)
|
|
||||||
IF(LIBNFC_CONFFILES_MODE)
|
|
||||||
ADD_DEFINITIONS(-DCONFFILES)
|
|
||||||
ENDIF(LIBNFC_CONFFILES_MODE)
|
|
||||||
|
|
||||||
option (BUILD_EXAMPLES "build examples ON/OFF" ON)
|
|
||||||
option (BUILD_UTILS "build utils ON/OFF" ON)
|
|
||||||
|
|
||||||
option (BUILD_DEBPKG "build debian package ON/OFF" OFF)
|
|
||||||
|
|
||||||
|
|
||||||
# Doxygen
|
# Doxygen
|
||||||
SET(builddir "${CMAKE_BINARY_DIR}")
|
SET(builddir "${CMAKE_BINARY_DIR}")
|
||||||
@ -96,41 +58,17 @@ ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX)
|
|||||||
# Additonnal GCC flags
|
# Additonnal GCC flags
|
||||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||||
# Make sure we will not miss some warnings ;)
|
# Make sure we will not miss some warnings ;)
|
||||||
SET(CMAKE_C_FLAGS "-Wall -pedantic -std=c99 ${CMAKE_C_FLAGS}")
|
ADD_DEFINITIONS(-Wall -pedantic -std=c99)
|
||||||
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
|
||||||
# Workarounds for libusb in C99
|
# Workarounds for libusb in C99
|
||||||
ADD_DEFINITIONS(-Du_int8_t=uint8_t -Du_int16_t=uint16_t)
|
ADD_DEFINITIONS(-Du_int8_t=uint8_t -Du_int16_t=uint16_t)
|
||||||
|
|
||||||
IF(MINGW)
|
IF(MINGW)
|
||||||
IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
# force MinGW-w64 in 32bit mode
|
||||||
# force MinGW-w64 in 32bit mode
|
ADD_DEFINITIONS(-m32)
|
||||||
SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
|
SET(CMAKE_SHARED_LINKER_FLAGS -m32)
|
||||||
SET(CMAKE_MODULE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
|
SET(CMAKE_EXE_LINKER_FLAGS -m32)
|
||||||
SET(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
|
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}")
|
|
||||||
SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}")
|
|
||||||
ELSE(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
|
||||||
IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
|
|
||||||
# force MinGW-w64 in 32bit mode
|
|
||||||
MESSAGE("Building 32-bit Windows DLL")
|
|
||||||
#SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
|
|
||||||
#SET(CMAKE_MODULE_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
|
|
||||||
#SET(CMAKE_SHARED_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
|
|
||||||
#SET(CMAKE_EXE_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}")
|
|
||||||
SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}")
|
|
||||||
ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
|
||||||
MESSAGE("Building 64-bit Windows DLL")
|
|
||||||
SET(CMAKE_RC_FLAGS "--target=pe-x86-64 --output-format=coff ${CMAKE_RC_FLAGS}")
|
|
||||||
ELSE(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
|
|
||||||
MESSAGE(FATAL_ERROR "Unknown Processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
|
||||||
ENDIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
|
|
||||||
ENDIF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
|
||||||
|
|
||||||
FIND_PROGRAM(DLLTOOL dlltool CMAKE_FIND_ROOT_PATH_BOTH)
|
|
||||||
IF (NOT DLLTOOL)
|
|
||||||
MESSAGE(FATAL_ERROR "Could not find dlltool command")
|
|
||||||
ENDIF (NOT DLLTOOL)
|
|
||||||
ENDIF(MINGW)
|
ENDIF(MINGW)
|
||||||
|
|
||||||
IF(NOT WIN32)
|
IF(NOT WIN32)
|
||||||
@ -141,165 +79,30 @@ 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)
|
IF(LIBNFC_DRIVER_ACR122)
|
||||||
SET(PKG_REQ ${PKG_REQ} "libusb")
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
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)
|
|
||||||
SET(PKG_REQ ${PKG_REQ} "libpcsclite")
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
|
|
||||||
# CMake lists are separated by a semi colon, replace with colon
|
# CMake lists are separated by a semi colon, replace with colon
|
||||||
STRING(REPLACE ";" "," PKG_CONFIG_REQUIRES "${PKG_REQ}")
|
STRING(REPLACE ";" "," PKG_CONFIG_REQUIRES "${PKG_REQ}")
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libnfc.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc @ONLY)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libnfc.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc @ONLY)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||||
ENDIF(NOT WIN32)
|
ENDIF(NOT WIN32)
|
||||||
|
|
||||||
INCLUDE(LibnfcDrivers)
|
|
||||||
|
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
IF(I2C_REQUIRED)
|
|
||||||
# Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html
|
|
||||||
INCLUDE (CheckFunctionExists)
|
|
||||||
INCLUDE (CheckLibraryExists)
|
|
||||||
CHECK_FUNCTION_EXISTS (clock_gettime HAVE_CLOCK_GETTIME)
|
|
||||||
IF (NOT HAVE_CLOCK_GETTIME)
|
|
||||||
CHECK_LIBRARY_EXISTS (rt clock_gettime "" HAVE_CLOCK_GETTIME_IN_RT)
|
|
||||||
IF (HAVE_CLOCK_GETTIME_IN_RT)
|
|
||||||
SET(LIBRT_FOUND TRUE)
|
|
||||||
SET(LIBRT_LIBRARIES "rt")
|
|
||||||
ENDIF (HAVE_CLOCK_GETTIME_IN_RT)
|
|
||||||
ENDIF (NOT HAVE_CLOCK_GETTIME)
|
|
||||||
ENDIF(I2C_REQUIRED)
|
|
||||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
|
|
||||||
IF(PCSC_INCLUDE_DIRS)
|
|
||||||
INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS})
|
|
||||||
LINK_DIRECTORIES(${PCSC_LIBRARY_DIRS})
|
|
||||||
ENDIF(PCSC_INCLUDE_DIRS)
|
|
||||||
|
|
||||||
IF(LIBUSB_INCLUDE_DIRS)
|
|
||||||
INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS})
|
|
||||||
LINK_DIRECTORIES(${LIBUSB_LIBRARY_DIRS})
|
|
||||||
SET(LIBUSB_FOUND TRUE)
|
|
||||||
ENDIF(LIBUSB_INCLUDE_DIRS)
|
|
||||||
|
|
||||||
# version.rc for Windows
|
|
||||||
IF(WIN32)
|
|
||||||
# Date for filling in rc file information
|
|
||||||
IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
|
||||||
MACRO (GET_CURRENT_YEAR RESULT)
|
|
||||||
EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT})
|
|
||||||
STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}})
|
|
||||||
STRING(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3" ${RESULT} ${${RESULT}})
|
|
||||||
ENDMACRO (GET_CURRENT_YEAR)
|
|
||||||
ELSE(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
|
||||||
MACRO (GET_CURRENT_YEAR RESULT)
|
|
||||||
EXECUTE_PROCESS(COMMAND "date" "+%Y" OUTPUT_VARIABLE ${RESULT})
|
|
||||||
STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}})
|
|
||||||
ENDMACRO (GET_CURRENT_YEAR)
|
|
||||||
ENDIF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
|
||||||
GET_CURRENT_YEAR(CURRENT_YEAR)
|
|
||||||
MESSAGE("Year for copyright is " ${CURRENT_YEAR})
|
|
||||||
|
|
||||||
SET(prefix ${CMAKE_INSTALL_PREFIX})
|
|
||||||
SET(RC_COMMENT "${PACKAGE_NAME} library")
|
|
||||||
SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}")
|
|
||||||
SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll)
|
|
||||||
# RC_FILE_TYPE: VFT_DLL
|
|
||||||
SET(RC_FILE_TYPE 0x00000002L)
|
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/windows/libnfc.rc @ONLY)
|
|
||||||
ENDIF(WIN32)
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(libnfc)
|
ADD_SUBDIRECTORY(libnfc)
|
||||||
ADD_SUBDIRECTORY(include)
|
ADD_SUBDIRECTORY(include)
|
||||||
|
ADD_SUBDIRECTORY(examples)
|
||||||
if (BUILD_UTILS)
|
|
||||||
add_subdirectory (utils)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUILD_EXAMPLES)
|
|
||||||
add_subdirectory (examples)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT MSVC)
|
|
||||||
# config script install path
|
|
||||||
if ( NOT DEFINED LIBNFC_CMAKE_CONFIG_DIR )
|
|
||||||
set ( LIBNFC_CMAKE_CONFIG_DIR lib${LIB_SUFFIX}/cmake/libnfc )
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set ( LIBNFC_INCLUDE_DIR ${includedir} )
|
|
||||||
set ( LIBNFC_INCLUDE_DIRS ${LIBNFC_INCLUDE_DIR} )
|
|
||||||
list ( APPEND LIBNFC_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIRS} )
|
|
||||||
set ( LIBNFC_LIBRARY nfc )
|
|
||||||
set ( LIBNFC_LIBRARIES ${LIBNFC_LIBRARY} )
|
|
||||||
list ( APPEND LIBNFC_LIBRARIES ${LIBUSB_LIBRARIES} )
|
|
||||||
set ( LIBNFC_LIBRARY_DIRS ${libdir} )
|
|
||||||
set ( LIBNFC_ROOT_DIR ${prefix} )
|
|
||||||
set ( LIBNFC_VERSION_STRING ${VERSION} )
|
|
||||||
set ( LIBNFC_VERSION_MAJOR ${VERSION_MAJOR} )
|
|
||||||
set ( LIBNFC_VERSION_MINOR ${VERSION_MINOR} )
|
|
||||||
set ( LIBNFC_VERSION_PATCH ${VERSION_PATCH} )
|
|
||||||
|
|
||||||
set ( LIBNFC_USE_FILE ${CMAKE_INSTALL_PREFIX}/${LIBNFC_CMAKE_CONFIG_DIR}/UseLibNFC.cmake )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_LESS 2.8.8)
|
|
||||||
configure_file ( cmake/LibNFCConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake @ONLY )
|
|
||||||
configure_file ( cmake/LibNFCConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfigVersion.cmake @ONLY )
|
|
||||||
else ()
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
configure_package_config_file (
|
|
||||||
cmake/LibNFCConfig.cmake.in
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake
|
|
||||||
INSTALL_DESTINATION ${LIBNFC_CMAKE_CONFIG_DIR}
|
|
||||||
PATH_VARS
|
|
||||||
LIBNFC_USE_FILE
|
|
||||||
LIBNFC_ROOT_DIR
|
|
||||||
LIBNFC_INCLUDE_DIR
|
|
||||||
LIBNFC_INCLUDE_DIRS
|
|
||||||
LIBNFC_LIBRARY_DIRS
|
|
||||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
|
||||||
)
|
|
||||||
write_basic_package_version_file (
|
|
||||||
LibNFCConfigVersion.cmake
|
|
||||||
VERSION ${LIBNFC_VERSION_STRING}
|
|
||||||
COMPATIBILITY AnyNewerVersion
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfigVersion.cmake
|
|
||||||
cmake/UseLibNFC.cmake
|
|
||||||
DESTINATION ${LIBNFC_CMAKE_CONFIG_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Binary Package
|
# Binary Package
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(CPACK_GENERATOR "ZIP")
|
SET(CPACK_GENERATOR "NSIS")
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
SET(CPACK_GENERATOR "TBZ2")
|
SET(CPACK_GENERATOR "TBZ2")
|
||||||
IF(BUILD_DEBPKG)
|
|
||||||
SET(CPACK_GENERATOR "DEB")
|
|
||||||
ENDIF(BUILD_DEBPKG)
|
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Near Field Communication (NFC) library")
|
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Near Field Communication (NFC) library")
|
||||||
SET(CPACK_PACKAGE_VENDOR "Roel Verdult")
|
SET(CPACK_PACKAGE_VENDOR "Roel Verdult")
|
||||||
SET(CPACK_PACKAGE_CONTACT "Roel Verdult <roel@libnfc.org>")
|
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
||||||
|
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||||
#Readme file
|
|
||||||
IF(WIN32)
|
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README-Windows.md")
|
|
||||||
ELSE(WIN32)
|
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
|
||||||
ENDIF(WIN32)
|
|
||||||
|
|
||||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
|
||||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "libnfc")
|
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "libnfc")
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
||||||
@ -324,5 +127,5 @@ ELSE(WIN32)
|
|||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "libnfc-${VERSION}")
|
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "libnfc-${VERSION}")
|
||||||
SET(CPACK_SOURCE_IGNORE_FILES "~$" "/\\\\.git/" "bin/")
|
SET(CPACK_SOURCE_IGNORE_FILES "~$" "/\\\\.svn/" "bin/")
|
||||||
INCLUDE(CPack)
|
INCLUDE(CPack)
|
||||||
|
|||||||
465
ChangeLog
465
ChangeLog
@ -1,466 +1,15 @@
|
|||||||
May 22, 2020 - 1.8.0
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Bump revision due to changes in API introduced in v1.7.2
|
|
||||||
- Bump library version to 6.0.0
|
|
||||||
|
|
||||||
May 21, 2020 - 1.7.2 (avoid using it, incompatible with 1.7.1)
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Remove unreachable code
|
|
||||||
- nfc_emulate_uid: cleaner exit on interrupt
|
|
||||||
- Fix reporting of modulations and baud rates by nfc-scan-device -v
|
|
||||||
- Fix out-of-bounds access in nfc-mfultralight
|
|
||||||
- Several Cygwin compilation fixes
|
|
||||||
- Fix comparison when nfc_initiator_target_is_present() with a specified target
|
|
||||||
- Fix nfc_initiator_poll_target without tag on PN532
|
|
||||||
- Export iso14443b* symbols
|
|
||||||
- Fix udev rule which was executed too early
|
|
||||||
- Fix improper device name initialization
|
|
||||||
- Fix setenv()/unsetenv() for Windows
|
|
||||||
- Fix win32/nfc.def according to nfc.h
|
|
||||||
- Fix missing timeout in pn53x_initiator_select_passive_target()
|
|
||||||
- nfc-mfclassic: fix option to tolerate write errors
|
|
||||||
- nfc-poll: fix card removing check
|
|
||||||
- nfc-relay-picc: fix wrong open mode for file descriptor
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- Allow ISO14443A to be used at higher baud rates
|
|
||||||
- nfc_initiator_select_passive_target() now checks against
|
|
||||||
reported modulations and baud rates for current device
|
|
||||||
- More serial devices on MAC OS X
|
|
||||||
- Add section to README to help to configure libnfc
|
|
||||||
- Various cmake improvements
|
|
||||||
- Drop PCRE dependency on Windows
|
|
||||||
- Remove deprecated readdir_r
|
|
||||||
- Markdown conversion of the text files
|
|
||||||
- Use hardcoded PN533 descriptors to be more robust on Windows
|
|
||||||
- Add support for SCL3712
|
|
||||||
- Add support for ACR1222U-C1
|
|
||||||
- Add support for NetBSD
|
|
||||||
- Add support for PN532 on RPi3 UART
|
|
||||||
- Add support for cross-compilation of 32b & 64b versions of the library for Windows
|
|
||||||
- Add pn533_usb to the kernel modules blacklist
|
|
||||||
- Add support for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested)
|
|
||||||
- Add support for contactless PC/SC readers (only as initiator)
|
|
||||||
- Add support for Feitian R502 and bR500 into pcsc driver
|
|
||||||
- Add support for HID iClass (Picopass) support (nfc-iclass tool in external nfc-tools repo)
|
|
||||||
- Allows for sending empty data in nfc_initiator_transceive_bits
|
|
||||||
- driver i2c: respect proper timing specifications
|
|
||||||
- driver i2c: add retry on error mechanism
|
|
||||||
- nfc-mfclassic: improvements fo magic cards
|
|
||||||
- nfc-mfclassic: add option to specify UID
|
|
||||||
- nfc-mfclassic/nfc-mfsetuid: add support for new gen (1b) of magic 4K cards
|
|
||||||
- nfc-mfclassic: Add RATS support indicator
|
|
||||||
- nfc-mfsetuid: allow to write complete Block0, instead of only UID
|
|
||||||
- nfc-mfultralight: add automatic modes and --check-magic
|
|
||||||
- nfc-mfultralight: add support for magic gen2 cards
|
|
||||||
- nfc-mfultralight: add option to specify UID
|
|
||||||
- nfc-mfultralight: add support for Ultralight NTAG213/215/216
|
|
||||||
- nfc-barcode: new command to read and decode NFC Barcodes (Tag-Talks-First)
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- nfc_device_get_supported_baud_rate() takes now a "mode" parameter
|
|
||||||
- New nfc_device_get_supported_baud_rate_target_mode()
|
|
||||||
- New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol
|
|
||||||
- New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass)
|
|
||||||
- pn53x_transceive() is now part of public API
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Jim Anastassiou, Frédéric Bourgeois, Dario Carluccio, Emmanuel Dreyfus,
|
|
||||||
Julien Ehrhart, S. Fabri, John Galt, Christoph Gritschenberger,
|
|
||||||
Alexander Inyukhin, Arnaud Kapp, David Kreitschmann, Adam Laurie, Ray Lee,
|
|
||||||
Maxim Martyanov, Paul Menzel, Boris Moiseev, Yerzhan Mukhamejan,
|
|
||||||
Olliver Shinagl, Jairo Andres Suarez, Mati Vait, Marcos Vives Del Sol,
|
|
||||||
Hidde Wieringa, Simon Yorkston, timzi, usk-johnny-s, xantares, Hanno
|
|
||||||
Heinrichs, jgeslin, Mikolaj Stawiski, rstular, Khem Raj, Frank Morgner, jpwidera,
|
|
||||||
Feitian Technologies
|
|
||||||
|
|
||||||
Feb 24, 2014 - 1.7.1
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Fix several issues reported by Coverity Scan
|
|
||||||
(mem leaks, buff overflows, reuse after free, etc)
|
|
||||||
- More robust when several conflicting uart drivers are in the config
|
|
||||||
- Fix racing condition with uart_flush_input()
|
|
||||||
- Silent pn53x_check_communication error messages when scanning
|
|
||||||
- Fix nfc_target_init(), was returning success in case of timeout
|
|
||||||
- Windows: fix several compilation issues
|
|
||||||
- On tag selection, save current target info also for ISO14443B*
|
|
||||||
- nfc-read-forum-tag3: fix incomplete NDEF retrieval and size of output file
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- nfc-list: New option to choose which technologies to poll for
|
|
||||||
- UART: drivers now supported under kFreeBSD
|
|
||||||
- New LIBNFC_DEVICE env var to use one reader and exclude all other readers
|
|
||||||
while LIBNFC_DEFAULT_DEVICE only prepends it to the configured devices list
|
|
||||||
- New LIBNFC_AUTO_SCAN env var to enable(default)/disable auto scan
|
|
||||||
- On tag selection, save current target info even if pnt=NULL
|
|
||||||
- On tag selection, grant NP_INFINITE_SELECT also for ISO14443B*
|
|
||||||
- Save & restore NP_INFINITE_SELECT status when changing it internally
|
|
||||||
- nfc-mfclassic: add format/wipe command (thanks to Adam Laurie)
|
|
||||||
- nfc-jewel: new utility to read/write Topaz/Jewel tags (thanks to Pim 't Hart)
|
|
||||||
- nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL
|
|
||||||
- nfc-read-forum-tag3: add -q option, add full parsing of NDEF Attribute Block
|
|
||||||
|
|
||||||
Fixes & improvements specific to nfc_initiator_target_is_present():
|
|
||||||
- Supports fully PN532 & PN533, not tested on other chips
|
|
||||||
- Fix usage after nfc_initiator_poll_target()
|
|
||||||
- Set correctly last_error
|
|
||||||
- Fix issue when there was no saved target
|
|
||||||
- Allow NULL pointer to tag
|
|
||||||
- Fix issues in case of tear off conditions
|
|
||||||
- Now works with:
|
|
||||||
* MFUL, MFC, MFC Mini, MFC 7-byte (re-selection: you'll need to auth again)
|
|
||||||
* ISO14443-4A, ISO14443-4B
|
|
||||||
* ISO14443-4B', ASK CTx, ST SRx
|
|
||||||
* Jewel
|
|
||||||
* FeliCa
|
|
||||||
|
|
||||||
Sep 03, 2013 - 1.7.0
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- pn53x: only create a current target when at least one have been found
|
|
||||||
- pn532_uart: fix 'operation abort' feature with this driver
|
|
||||||
- pn532_uart: let more time to PN532 to wake-up, this fix some specific cases
|
|
||||||
where PN532 shown one of two runs (Thanks to Marcello Morena)
|
|
||||||
- nfc-mfclassic: allow option f for read operation too
|
|
||||||
- Avoid clash with system's htole32 if it exists
|
|
||||||
- Include <stdlib.h>, required for getenv(3)
|
|
||||||
- usb: fix USB enumeration issue (Thanks to Mike Auty)
|
|
||||||
- acr122_pcsc: fix compilation on Mac OSX 10.8.4
|
|
||||||
- Fix pn53x_initiator_transceive_bytes_timed() measures for TypeB
|
|
||||||
- Various minor fixes: warnings, style, etc.
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- New PN532 over I2C driver, see contrib/libnfc/pn532_i2c_on_rpi.conf.sample
|
|
||||||
- ACR122/Touchatag: misc improvements
|
|
||||||
- ReadMobib/ReadNavigo: improve shell script portability
|
|
||||||
- Add ISO14443-4 chaining support for RX (MI)
|
|
||||||
- UART: add support for BeagleBone serial ports (Thanks to Johan Henselmans)
|
|
||||||
- nfc-mfultralight: allow setting of UID for special 'chinese' ultralight cards
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Laurent Latil (new pn532_i2c driver for linux)
|
|
||||||
- Nobuhiro Iwamatsu (warning fixes and debian package)
|
|
||||||
|
|
||||||
Apr 05, 2013 - 1.7.0-rc7 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Fix bug when compiling without libusb
|
|
||||||
- Fix several memory leaks in error handling conditions
|
|
||||||
- Remove calls to exit() from the library
|
|
||||||
- Create safer snprint_nfc_*() instead of sprint_nfc_*() functions
|
|
||||||
- Fix warnings returned by cppcheck & clang/scan-build
|
|
||||||
- Obsolete function 'usleep' => nanosleep()
|
|
||||||
- Non reentrant function 'readdir' => readdir_r()
|
|
||||||
- Non reentrant function 'strtok' => new connstring_decode()
|
|
||||||
- Buffer may not be null-terminated after call to strncpy()
|
|
||||||
- scanf without field width limits can crash with huge input data
|
|
||||||
- Resource leaks: missing fclose()
|
|
||||||
- Dead code, unused vars & vars scopes warnings
|
|
||||||
- Unify copyright notices & update authors lists
|
|
||||||
- Windows: Fix compilation due to new usbbus file
|
|
||||||
- Windows: Clean up compiler/linker warnings
|
|
||||||
- Fixed the suppression of the auto-fixup for linking against MS built libs
|
|
||||||
- Fixed all the formatting warnings by shifting to inttypes.h specifiers
|
|
||||||
- shifted to %lu for DWORD printf
|
|
||||||
- nfc-anticol: fix ATS length
|
|
||||||
- nfc-mfclassic: fix reporting of processed blocks total
|
|
||||||
- nfc-mfclassic: detect MIFARE Plus 2K as 2K instead of 1K
|
|
||||||
- pn53x_usb/acr122_usb: check usb_open() returns before using it
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- New PN532 over SPI driver, see contrib/libnfc/pn532_spi_on_rpi.conf.sample
|
|
||||||
- Devels HACKING file: introduce clang/scan-build & cppcheck for better code
|
|
||||||
- Better internal dependencies handling (bus <> drivers)
|
|
||||||
- Cleaner handling of portability patches
|
|
||||||
- Windows: logging via OutputDebugString(), ease debugging
|
|
||||||
- nfc-mfclassic: use smaller files for cards < 4k
|
|
||||||
- nfc-mfclassic: by defaut don't authorise wrong keyfile, use "f" to force
|
|
||||||
- quick_start_example1.c: remove err.h dependency, easier for Windowsians
|
|
||||||
- nfc-mfclassic: support some new magic cards with writeable sector #0
|
|
||||||
- nfc-anticol: add -t option to use timed functions
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Upon malloc error, nfc_init() doesn't force exit() anymore
|
|
||||||
so now you should test if context != NULL after nfc_init() call
|
|
||||||
- API: nfc_initiator_target_is_present() & str_nfc_target()
|
|
||||||
now take a pointer to nfc_target as argument instead of passing by value
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Eugeny Boger (new pn532_spi driver for linux)
|
|
||||||
|
|
||||||
Mar 03, 2013 - 1.7.0-rc6 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Fix several memory leaks (nfc_drivers, libusb, config parser)
|
|
||||||
- Fix stack smash while displaying long data transmission (LOG_HEX)
|
|
||||||
- pn53x-tamashell: allow larger commands up to full extended frame
|
|
||||||
- Add missing windows file in archive (version.rc.in)
|
|
||||||
- Fix compilation warnings & potential bugs
|
|
||||||
- Fix documentation
|
|
||||||
- Fix missing malloc() calls checks
|
|
||||||
- Fix missing free() calls in some error handlers
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- Allow to disable conffils & envvar supports on embedded platforms
|
|
||||||
- Add option to nfc-mfclassic to tolerate RW errors
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Replace usb_set_debug() in applications by LIBNFC_LOG_LEVEL libusb group
|
|
||||||
|
|
||||||
Feb 16, 2013 - 1.7.0-rc5 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Add missing sample configuration file in archive
|
|
||||||
- Add missing windows files in archive
|
|
||||||
- Preserve error code while using pn53x_set_property_bool() with
|
|
||||||
NP_AUTO_ISO14443_4 flag
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- New nfc_register_driver() function allowing to hook custom drivers
|
|
||||||
- New nfc_free() function to free allocated buffers
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Ahti Legonkov (new nfc_register_driver())
|
|
||||||
|
|
||||||
Feb 04, 2013 - 1.7.0-rc4 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Fix tag selection for nfc-mfclassic, nfc-mfultralight, nfc-read-forum-tag3
|
|
||||||
and nfc-relay-picc
|
|
||||||
- Fix crash in nfc-relay-picc -i/-t if fd3 or fd4 is missing
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- Windows support build with CMake
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Configuration directory (ie. libnfc.conf) can now be set a compile-time
|
|
||||||
- Log can be enabled/disabled using CMake
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Alex Lian (Windows support improvements)
|
|
||||||
- Nobuhiro Iwamatsu (Debian package improvements)
|
|
||||||
|
|
||||||
Jan 31, 2013 - 1.7.0-rc3 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Fix pn53x_usb bulk write timeout
|
|
||||||
- Fix BCC in nfc-emulate-uid example
|
|
||||||
- Fix nfc-relay-picc example
|
|
||||||
- Fix a miss returned value within some internal functions (user program could
|
|
||||||
be affected)
|
|
||||||
- Fix nfc-scan-device -i option
|
|
||||||
- Remove wrong exit() calls in library
|
|
||||||
- Fix issue in driver acr122_usb affecting Touchatag
|
|
||||||
- Reenable some idle in all drivers, add selectively PowerDown when possible
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- nfc_emulate_target() now takes timeout parameter
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Alex Lian (Windows support refresh)
|
|
||||||
|
|
||||||
Jan 20, 2013 - 1.7.0-rc2 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Fix API version in debian files
|
|
||||||
- Fix wrong condition to display a warning when user disables autoscan
|
|
||||||
- Fix unit tests
|
|
||||||
- Fix ISO14443B' ATS
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- Allow device.optional=true to tolerate missing device
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- pn532_uart driver is now enabled by default
|
|
||||||
|
|
||||||
Dec 09, 2012 - 1.7.0-rc1 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- nfc_initiator_deselect_target() now returns 0 on success (as expected by caller)
|
|
||||||
- example/pn532-sam: Fix few bugs
|
|
||||||
- Fix ACR122S device detection when no ACR122S device available (endless UART receive)
|
|
||||||
- Suppress a lot of compiler warnings !.. which fixes many potential bugs
|
|
||||||
- Display right driver name while detecting PCSC
|
|
||||||
- Correctly handle PCSC header files on Mac OS X
|
|
||||||
- Fix nfc-emulation (now works with utils/nfc-emulate-forum-tag4 and Nexus S)
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- New nfc_initiator_init_secure_element() function to set SAM as wired card (only relevant with a PN532 SAM-equipped)
|
|
||||||
- New str_nfc_target(), str_nfc_modulation_type(), str_nfc_baud_rate() function to convert some libnfc's types into allocated string
|
|
||||||
- New nfc_device_target_is_present() to check if passed target is in the field
|
|
||||||
- --enable-serial-autoprobe option at compile time to replace it with some run-time options
|
|
||||||
- New -i option to nfc-scan-device to allow intrusive scan
|
|
||||||
- New feature, libnfc now uses configuration files:
|
|
||||||
* main configuration file can be used to set options (ie. intrusive, autoscan, log-level)
|
|
||||||
* main configuration file can contains a device as default device, HIGHLY recommended for UART devices users
|
|
||||||
* multiple devices files can be used to declare multiple devices and ordered them
|
|
||||||
- UART port scan now includes ttyAMA* to detect UART-devices connected on Raspberry Pi (e.g. `nfc-scan-device -i`)
|
|
||||||
- Support for OpenPCD2 (with a dedicated firmware)
|
|
||||||
- Support for FTDI dongle under MacOS
|
|
||||||
- Enhance messages display
|
|
||||||
- Provides modprobe configuration file and instructions for Linux >3.1 with PN533 users.
|
|
||||||
- Greatly improve log facility with log level filter, configurable using conf file (ie. /etc/nfc/libnfc.conf) or environment var LIBNFC_LOG_LEVEL
|
|
||||||
- New man page for nfc-read-forum-tag3 utility (Thanks to UNFORGiVEN512)
|
|
||||||
- New man page for nfc-scan-device utility
|
|
||||||
- New man page for nfc-emulate-forum-tag2 example
|
|
||||||
- README: Add few words about device permissions and udev/devd rules available in package
|
|
||||||
- utils/nfc-emulate-forum-tag4: add support for v2.0 of the spec
|
|
||||||
- New "make style" command to have a beautiful code
|
|
||||||
- Code cleanup (indentation, white spaces, etc.)
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- New nfc_device_get_information_about() now allocates returned string
|
|
||||||
- No more in/out paramaters in nfc_initiator_transceive_*() functions
|
|
||||||
- Rename nfc-probe to nfc-scan-device
|
|
||||||
- Rename abtUid from struct mifare_param_auth into abtAuthUid: this is not the UID while using 7-bytes UID MIFARE Classic tags.
|
|
||||||
- utils/nfc-list: always display the card type when a card is found
|
|
||||||
- nfc-utils: new fingerprinting method closer to AN10833, (Thanks to Balazs Bucsay)
|
|
||||||
|
|
||||||
See NEWS file for major changes (ie. API changes)
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Ludovic Rousseau (Code cleanup, tests under MacOS, etc.)
|
|
||||||
- Frank Morgner
|
|
||||||
|
|
||||||
Feb 27, 2012 - 1.6.0-rc1 (release candidate)
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- utils/nfc-mfclassic: use MIFARE instead of Mifare typo
|
|
||||||
- utils/nfc-list: continue to attempt to reach devices after a connection failure
|
|
||||||
- libnfc: avoid readline auto-detection when cross-compiling
|
|
||||||
- driver/pn53x_usb: fix path usage for FreeBSD
|
|
||||||
- doc: quick_start_example1.c fixed
|
|
||||||
- utils/*: verbose option back for nfc-list, and newly implemented in nfc-poll
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- libnfc: enhanced documentation
|
|
||||||
- libnfc: debug facility back without external depends
|
|
||||||
- libnfc: add nfc_device_get_supported_modulation() and nfc_device_get_supported_baud_rate() functions
|
|
||||||
- libnfc: enhanced code indent
|
|
||||||
- drivers: implement driver for ACR122S device
|
|
||||||
- utils/nfc-mfclassic: remove non-conscistent "extract payload" option in nfc-mfclassic
|
|
||||||
- utils/nfc-emulate-forum-tag2: add missing manpage
|
|
||||||
- utils/nfc-read-forum-tag3: add missing manpage
|
|
||||||
- tests/*: fix some warnings in test
|
|
||||||
- tests/test_dep*: add some DEP tests (Active/Passive in several baud rates)
|
|
||||||
- doc: quick_start_example1 is now compiled when running make check or distcheck
|
|
||||||
- libnfc: a printf-based logging replaces log4c
|
|
||||||
- libnfc: various minor fixes/enhancements
|
|
||||||
- utils/*: nfc-probe example added to show devices connection strings
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- PN53x specific errors are not public anymore;
|
|
||||||
- Timeouts are now integers instead of timeval structure
|
|
||||||
- Removes libusb types workaround (r200) as it seems to not be needed anymore but may disturb compiler
|
|
||||||
- Removes parse_args() from nfc-utils.[hc]
|
|
||||||
- Move nfc-emulate-forum-tag2 from utils to examples.
|
|
||||||
- contrib: move udev and devd files into contrib/
|
|
||||||
- debian: udev rules file renamed
|
|
||||||
|
|
||||||
See NEWS file for major changes (ie. API changes)
|
|
||||||
|
|
||||||
Special thanks to:
|
|
||||||
- Thomas Hood (Debian packages and various fixes/contributions)
|
|
||||||
- Anugrah Redja (ACR122S driver)
|
|
||||||
|
|
||||||
Oct 17, 2011 - 1.5.1 (unstable)
|
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
Apr nn, 2011 - 1.5.0 (unstable)
|
||||||
Fixes:
|
|
||||||
- libnfc: fix invalid memory access when a new driver is probing for hardware and the number of requested devices was already reached
|
|
||||||
- chips/pn53x: fix bug in _timed fcts
|
|
||||||
- drivers/pn53x_usb: fix crash when usb_bulk_read() fails.
|
|
||||||
- drivers/pn53x_usb: continue to search a available device on usb errors (ie. Device Busy)
|
|
||||||
- drivers/pn53x_usb: make PN53x usb connection more stable
|
|
||||||
- examples/nfc-relay: fix UID problem
|
|
||||||
- windows: fix uart_receive() under Win32 platform
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
- libnfc: add logging facility using log4c.
|
|
||||||
- libnfc: abort mecanism is now implemented in driver layer, so it can use pipe-based mecanism (as PN532_UART or ARYGON driver does under POSIX system) or flag-based mecanism.
|
|
||||||
- libnfc: add ISO/IEC 14443 B' aka Type B' modulation partial support
|
|
||||||
- libnfc: add partial support (list) for ISO14443B-3 ST SRx & ASK CTx cards
|
|
||||||
- libnfc: compile unit tests only on demand unless using --enable-debug.
|
|
||||||
- libnfc: error handling improvements
|
|
||||||
- libnfc: new function nfc_idle() to set the NFC device in idle mode
|
|
||||||
- libnfc: add partial support for Sony S360 reader
|
|
||||||
- libnfc: some manual test reports have been added
|
|
||||||
- libnfc: list_targets support for ASK CTS512B (no anticol support yet)
|
|
||||||
- libnfc: nfc_disconnect() now switches NFC device into idle before disconnecting
|
|
||||||
- libnfc: nfc_initiator_poll_target() is now available for all devices
|
|
||||||
- libnfc: implement software polling for non-PN532 equipped device
|
|
||||||
- chips/pn53x: add pn53x_data_new() function to alloc and init pn53x_data structure
|
|
||||||
- chips/pn53x: add some SFR registers description
|
|
||||||
- chips/pn53x: implement WriteBack cache
|
|
||||||
- chips/pn53x: new pn53x_PowerDown wrapper for PowerDown (PN532) command
|
|
||||||
- chips/pn53x: prints a debug trace when reading PN53x registers
|
|
||||||
- chips/pn53x: set some parameters in ISO/IEC 14443A when using DEP mode (ie. SAK says ISO/IEC 18092 compliant) (Android NFC stack now detects the target as DEP)
|
|
||||||
- chips/pn53x: some optimisations in registers initialisation
|
|
||||||
- chips/pn53x: list_passive_targets() fixed for TypeB on LoGO
|
|
||||||
- chips/pn53x: pn53x_data now have a operating_mode enum to know the current running mode (initiator, target or idle)
|
|
||||||
- drivers/*: all commands are now abortable
|
|
||||||
- drivers/pn532_uart,arygon: make valgrind happy with UART-based drivers
|
|
||||||
- drivers/pn53x*: use shared pn53x_ack_frame[] and pn53x_nack_frame[] instead of local declaration
|
|
||||||
- drivers/pn53x_usb: all USB errors are now reported in text format
|
|
||||||
- drivers/pn53x_usb: enable progressive field on init to allow pn53x-tamashell to works (note: it does not distrib progressive field enabling when nfc_list_passive_target() is used)
|
|
||||||
- drivers/pn53x_usb: implement PN53x extended information frames with USB devices
|
|
||||||
- drivers/pn53x_usb: use progressive field on/off only for ISO14443 Type B target listing
|
|
||||||
- buses/uart: now provides an abort mecanism for windows users
|
|
||||||
- buses/uart: UART based drivers could now use uart_flush_input() to discard junk bytes on input.
|
|
||||||
- examples/nfc-anticol: add -f option to force RATS
|
|
||||||
- examples/nfc-mfclassic: handle 7-byte UID cards & MFC Mini
|
|
||||||
- examples/nfc-anticol: now use nfc_abort_command()
|
|
||||||
- examples/nfc-dep-*: disconnect from NFC device on error.
|
|
||||||
- examples/nfc-emulate-forum-tag2: add new example to emulate a NFC Forum Tag Type 2
|
|
||||||
- examples/nfc-emulate-forum-tag4: add document references.
|
|
||||||
- examples/nfc-emulate-forum-tag4: this example now fails with ENOTSUPP when used with a non-PN532 chip.
|
|
||||||
- examples/nfc-mfclassic: write special Mifare 1K cards, including Block 0 / UID
|
|
||||||
- examples/nfc-mfsetuid: add a new example to set UID of special Mifare 1K cards
|
|
||||||
- examples/nfc-read-forum-tag3: add new example to read a NFC Forum Tag Type 3
|
|
||||||
- examples/pn53x-tamashell-scripts: minor enhancements
|
|
||||||
- tests/test-dep: add a threaded DEP test to check DEP communication between two local devices
|
|
||||||
- debian: enable all drivers at compile time
|
|
||||||
- debian: improve debian packaging (Thanks to Thomas Hood)
|
|
||||||
- debian: use a numbering that allow to have libnfc pre-version and debian package pre-version too. (Thanks to Thomas Hood)
|
|
||||||
- freebsd: add FreeBSD devd(8) snippet configuration for Sony S330 readers.
|
|
||||||
- windows: implement abort mecanism in pn532_uart driver (Based on provided patch: many thanks to Edwin Evans)
|
|
||||||
- windows: USB drivers now relies on libusb-win32 with version >= 1.2.4.x (1.2.4.6 recommended) (Many thanks to Glenn)
|
|
||||||
- windows: implement automatic uart port detection and input flush (Thanks to Edwin Evans)
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- libnfc: add 'struct timeval *timeout' parameter for pn53x_transceive(), pn53x_target_receive_bytes() and pn53x_target_send_bytes().
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Apr 29, 2011 - 1.5.0 (unstable)
|
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
Fixes:
|
Fixes:
|
||||||
- libnfc: silent warnings with more strict CFLAGS
|
- libnfc: silent warnings with more strict CFLAGS
|
||||||
- libnfc: update devd(8) rules file for FreeBSD
|
- libnfc: update devd(8) rules file for FreeBSD
|
||||||
- libnfc: make libnfc compile under Windows
|
- libnfc: make libnfc compile under Windows
|
||||||
- libnfc: fix nfc_pick_device() when called from nfc_connect with NULL nfc_device_desc_t parameter
|
- libnfc: fix nfc_pick_device() when called from nfc_connect with NULL nfc_device_desc_t parameter (Fixes Issue 156)
|
||||||
- chips/pn53x: fix a bug when value is larger than mask when using WriteRegister
|
- chips/pn53x: fix a bug when value is larger than mask when using WriteRegister
|
||||||
- chips/pn53x: adapt MaxRetries to avoid issue with 2 tags on PN531
|
- chips/pn53x: adapt MaxRetries to avoid issue with 2 tags on PN531
|
||||||
- examples/nfc-mfclassic: UID was shown reverse-ordered
|
- examples/nfc-mfclassic: UID was shown reverse-ordered. (Fixes Issue 146)
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
- libnfc: use a new way to handle drivers, introduce a real HAL
|
- libnfc: use a new way to handle drivers, introduce a real HAL
|
||||||
@ -515,8 +64,7 @@ Changes:
|
|||||||
- drivers/pn53x_usb: pn531_usb and pn533_usb drivers are now merged and use the pn53x IC version autodetection
|
- drivers/pn53x_usb: pn531_usb and pn533_usb drivers are now merged and use the pn53x IC version autodetection
|
||||||
- buses/uart: use a smart way to determine available ports on POSIX systems (tested on Linux and FreeBSD)
|
- buses/uart: use a smart way to determine available ports on POSIX systems (tested on Linux and FreeBSD)
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
|
||||||
Feb 21, 2011 - 1.4.2
|
Feb 21, 2011 - 1.4.2
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -539,7 +87,6 @@ Improvements:
|
|||||||
- documentation: add more pcsc-lite related instruction in README
|
- documentation: add more pcsc-lite related instruction in README
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Feb 1, 2011 - 1.4.1
|
Feb 1, 2011 - 1.4.1
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -563,7 +110,6 @@ Improvements:
|
|||||||
Experimental: Windows platform support (Thanks to Glenn Ergeerts)
|
Experimental: Windows platform support (Thanks to Glenn Ergeerts)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Nov 17, 2010 - 1.4.0
|
Nov 17, 2010 - 1.4.0
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -617,7 +163,6 @@ Changes:
|
|||||||
- examples: change examples license for the sake of consistency: LGPL covers library, re-usable examples code is now under BSD license.
|
- examples: change examples license for the sake of consistency: LGPL covers library, re-usable examples code is now under BSD license.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Aug 31, 2010 - 1.3.9
|
Aug 31, 2010 - 1.3.9
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -723,7 +268,7 @@ Fixes:
|
|||||||
- libnfc: Fix tag re-selection with UID length > 4 bytes (like DESFire or Ultralight);
|
- libnfc: Fix tag re-selection with UID length > 4 bytes (like DESFire or Ultralight);
|
||||||
- nfc-mfclassic: Fix authenticated only with KEYA;
|
- nfc-mfclassic: Fix authenticated only with KEYA;
|
||||||
|
|
||||||
Improvements:
|
Improvments:
|
||||||
- build: Build on FreeBSD;
|
- build: Build on FreeBSD;
|
||||||
- build: Add alternative build system (CMake);
|
- build: Add alternative build system (CMake);
|
||||||
- build: Add new files usefull for desktop GNU/Linux users: some rules for udev to allow non-root access to PN53x USB devices;
|
- build: Add new files usefull for desktop GNU/Linux users: some rules for udev to allow non-root access to PN53x USB devices;
|
||||||
|
|||||||
2496
Doxyfile.in
2496
Doxyfile.in
File diff suppressed because it is too large
Load Diff
68
HACKING.md
68
HACKING.md
@ -1,68 +0,0 @@
|
|||||||
Hello hackers!
|
|
||||||
|
|
||||||
General remarks about contributing
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
Contributions to the libnfc are welcome!
|
|
||||||
Here are some directions to get you started:
|
|
||||||
|
|
||||||
1. Follow style conventions
|
|
||||||
The source code of the library trend to follow some conventions so that it
|
|
||||||
is consistent in style and thus easier to read.
|
|
||||||
Look around and respect the same style.
|
|
||||||
Don't use tabs. Increment unit is two spaces.
|
|
||||||
Don't leave dandling spaces or tabs at EOL.
|
|
||||||
Helper script to get some uniformity in the style:
|
|
||||||
$ make style
|
|
||||||
|
|
||||||
If you use vim see the [Vim: How to prevent trailing whitespaces](http://www.carbon-project.org/Vim__How_to_prevent_trailing_whitespaces.html).
|
|
||||||
|
|
||||||
2. Chase warnings: no warning should be introduced by your changes
|
|
||||||
Depending what you touch, you can check with:
|
|
||||||
|
|
||||||
2.1 When using autotools
|
|
||||||
|
|
||||||
$ autoreconf -Wall -vis
|
|
||||||
|
|
||||||
2.2 When compiling
|
|
||||||
|
|
||||||
2.2.1 Using extra flags:
|
|
||||||
|
|
||||||
$ export CFLAGS="-Wall -g -O2 -Wextra -pipe -funsigned-char -fstrict-aliasing \
|
|
||||||
-Wchar-subscripts -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wunused \
|
|
||||||
-Wuninitialized -Wpointer-arith -Wredundant-decls -Winline -Wformat \
|
|
||||||
-Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs \
|
|
||||||
-Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \
|
|
||||||
-Wbad-function-cast -Wnested-externs -Wmissing-declarations"
|
|
||||||
$ ./configure
|
|
||||||
$ make clean
|
|
||||||
$ make
|
|
||||||
|
|
||||||
2.2.2 Using clang:
|
|
||||||
|
|
||||||
You can use same CFLAGS but also `-Wunreachable-code`
|
|
||||||
|
|
||||||
$ scan-build ./configure
|
|
||||||
$ make clean
|
|
||||||
$ scan-build make
|
|
||||||
|
|
||||||
2.2.3 Using `cppcheck` (v1.58 or higher):
|
|
||||||
|
|
||||||
$ make cppcheck
|
|
||||||
|
|
||||||
2.3 When Debianizing
|
|
||||||
|
|
||||||
$ lintian --info --display-info --display-experimental *deb
|
|
||||||
or (shorter version)
|
|
||||||
$ lintian -iIE *deb
|
|
||||||
|
|
||||||
3. Preserve cross-platform compatibility
|
|
||||||
|
|
||||||
The source code should remain compilable across various platforms,
|
|
||||||
including some you probably cannot test alone so keep it in mind.
|
|
||||||
Supported platforms:
|
|
||||||
|
|
||||||
- Linux
|
|
||||||
- FreeBSD
|
|
||||||
- Mac OS X
|
|
||||||
- Windows with MinGW
|
|
||||||
165
LICENSE
Normal file
165
LICENSE
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
71
Makefile.am
71
Makefile.am
@ -2,13 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
|
|||||||
|
|
||||||
AM_CFLAGS = $(LIBNFC_CFLAGS)
|
AM_CFLAGS = $(LIBNFC_CFLAGS)
|
||||||
|
|
||||||
SUBDIRS = libnfc utils
|
SUBDIRS = libnfc 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
|
||||||
@ -16,18 +10,16 @@ pkgconfig_DATA = libnfc.pc
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
CMakeLists.txt \
|
CMakeLists.txt \
|
||||||
Doxyfile \
|
Doxyfile \
|
||||||
HACKING.md \
|
LICENSE \
|
||||||
NEWS.md \
|
README-Windows.txt \
|
||||||
README.md \
|
pn53x.conf \
|
||||||
README-Windows.md \
|
pn53x.rules
|
||||||
libnfc.conf.sample \
|
|
||||||
mingw-cross-compile.sh
|
|
||||||
|
|
||||||
CLEANFILES = Doxygen.log coverage.info libnfc.pc
|
CLEANFILES = Doxygen.log coverage.info
|
||||||
|
|
||||||
clean-local: clean-local-doc clean-local-coverage
|
clean-local: clean-local-doc clean-local-coverage
|
||||||
|
|
||||||
.PHONY: clean-local-coverage clean-local-doc doc style
|
.PHONY: clean-local-coverage clean-local-doc doc
|
||||||
clean-local-coverage:
|
clean-local-coverage:
|
||||||
-rm -rf coverage
|
-rm -rf coverage
|
||||||
|
|
||||||
@ -37,25 +29,34 @@ clean-local-doc:
|
|||||||
doc : Doxyfile
|
doc : Doxyfile
|
||||||
@DOXYGEN@ $(builddir)/Doxyfile
|
@DOXYGEN@ $(builddir)/Doxyfile
|
||||||
|
|
||||||
|
if HAS_INDENT
|
||||||
|
INDENT_ARGS = --blank-before-sizeof \
|
||||||
|
--blank-lines-after-commas \
|
||||||
|
--blank-lines-after-procedures \
|
||||||
|
--braces-after-func-def-line \
|
||||||
|
--braces-on-if-line \
|
||||||
|
--braces-on-struct-decl-line \
|
||||||
|
--continue-at-parentheses \
|
||||||
|
--cuddle-else \
|
||||||
|
--declaration-indentation 8 \
|
||||||
|
--indent-level 2 \
|
||||||
|
--line-length 120 \
|
||||||
|
--no-blank-lines-after-declarations \
|
||||||
|
--no-tabs \
|
||||||
|
--preprocessor-indentation 2 \
|
||||||
|
--procnames-start-lines \
|
||||||
|
--space-after-cast \
|
||||||
|
--space-after-procedure-calls
|
||||||
|
|
||||||
|
indent:
|
||||||
|
@[ ! -d $(top_srcdir)/.svn ] || \
|
||||||
|
[ 0 -eq $$(svn status | grep '\.[hc]$$' | tee /dev/fd/2 | wc -l) ] || \
|
||||||
|
( echo "These files are localy modified. 'commit' or 'reverse' them, then retry." >&2; false )
|
||||||
|
@for f in $$(find $(top_srcdir)/libnfc $(top_srcdir)/include $(top_srcdir)/examples -name "*.[hc]"); do \
|
||||||
|
echo " INDENT $$f"; \
|
||||||
|
$(INDENT) $(INDENT_ARGS) "$$f" || exit 1; \
|
||||||
|
done
|
||||||
|
endif
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS="--with-drivers=all"
|
DISTCHECK_CONFIGURE_FLAGS="--with-drivers=all"
|
||||||
|
|
||||||
style:
|
|
||||||
find . -name "*.[ch]" -exec perl -pi -e 's/[ \t]+$$//' {} \;
|
|
||||||
find . -name "*.[ch]" -exec astyle --formatted --mode=c --suffix=none \
|
|
||||||
--indent=spaces=2 --indent-switches --indent-preprocessor \
|
|
||||||
--keep-one-line-blocks --max-instatement-indent=60 \
|
|
||||||
--style=linux --pad-oper --unpad-paren --pad-header \
|
|
||||||
--align-pointer=name {} \;
|
|
||||||
|
|
||||||
cppcheck:
|
|
||||||
cppcheck --quiet \
|
|
||||||
-I include -I libnfc -I libnfc/buses -I libnfc/chips -I libnfc/drivers \
|
|
||||||
--check-config .
|
|
||||||
cppcheck --quiet --enable=all --std=posix --std=c99 \
|
|
||||||
-I include -I libnfc -I libnfc/buses -I libnfc/chips -I libnfc/drivers \
|
|
||||||
-DLOG -D__linux__ \
|
|
||||||
-DDRIVER_PN53X_USB_ENABLED -DDRIVER_ACR122_PCSC_ENABLED \
|
|
||||||
-DDRIVER_ACR122_USB_ENABLED -DDRIVER_ACR122S_ENABLED \
|
|
||||||
-DDRIVER_PN532_UART_ENABLED -DDRIVER_ARYGON_ENABLED \
|
|
||||||
-DDRIVER_PN532_SPI_ENABLED -DDRIVER_PN532_I2C_ENABLED \
|
|
||||||
--force --inconclusive .
|
|
||||||
|
|||||||
173
NEWS.md → NEWS
173
NEWS.md → NEWS
@ -1,176 +1,3 @@
|
|||||||
New in 1.8.0:
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
- Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
|
|
||||||
- Bump library version to 6.0.0
|
|
||||||
|
|
||||||
New in 1.7.2:
|
|
||||||
|
|
||||||
Drivers:
|
|
||||||
|
|
||||||
* New driver for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested)
|
|
||||||
* New driver for contactless PC/SC readers (only as initiator)
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* nfc_device_get_supported_baud_rate() now takes also "mode" as argument
|
|
||||||
* New nfc_device_get_supported_baud_rate_target_mode()
|
|
||||||
* New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol
|
|
||||||
* New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass)
|
|
||||||
* pn53x_transceive() is now part of public API
|
|
||||||
|
|
||||||
New in 1.7.1:
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL
|
|
||||||
* nfc_initiator_target_is_present() allow NULL pointer to tag
|
|
||||||
|
|
||||||
New in 1.7.0:
|
|
||||||
|
|
||||||
Drivers:
|
|
||||||
|
|
||||||
* New PN532 over I2C driver, see contrib/libnfc/pn532_i2c_on_rpi.conf.sample
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* New function iso14443b_crc_append()
|
|
||||||
|
|
||||||
New in 1.7.0-rc7:
|
|
||||||
|
|
||||||
Drivers:
|
|
||||||
|
|
||||||
* New PN532 over SPI driver, see contrib/libnfc/pn532_spi_on_rpi.conf.sample
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* Functions
|
|
||||||
- nfc_initiator_target_is_present() & str_nfc_target():
|
|
||||||
now take a pointer to nfc_target as argument
|
|
||||||
- nfc_init(): upon malloc error, doesn't force exit() anymore
|
|
||||||
so now you should test if context != NULL after nfc_init() call
|
|
||||||
|
|
||||||
New in 1.7.0-rc5:
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* Functions
|
|
||||||
- New nfc_register_driver() function allowing to hook custom drivers.
|
|
||||||
|
|
||||||
New in 1.7.0-rc3:
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* Functions
|
|
||||||
- Add timeout param to nfc_emulate_target()
|
|
||||||
|
|
||||||
New in 1.7.0-rc2:
|
|
||||||
|
|
||||||
Configuration:
|
|
||||||
libnfc can now use a configuration file for special setups, or features
|
|
||||||
activation. This file (/etc/nfc/libnfc.conf under GNU/Linux systems)
|
|
||||||
supports already some keywords:
|
|
||||||
- "allow_autoscan" to enable/disable device auto-detection feature;
|
|
||||||
- "allow_intrusive_scan" to enable/disable intrusive auto-detection
|
|
||||||
(ie. serial port probing);
|
|
||||||
- "log_level" to select library verbosity;
|
|
||||||
- "device.name" and "device.connstring" to define a user device,
|
|
||||||
this is the recommended method if user has a not easily detectable
|
|
||||||
device (ie. a serial one).
|
|
||||||
It is also possible to define devices using dedicated configuration files and
|
|
||||||
put them into device search directory (/etc/nfc/devices.d under GNU/Linux).
|
|
||||||
Example for the OpenPCD2: create /etc/nfc/devices.d/openpcd2.conf with:
|
|
||||||
name = "OpenPCD2"
|
|
||||||
connstring = "pn532_uart:/dev/ttyACM0"
|
|
||||||
optional = true
|
|
||||||
The keyword "optional" does not mandate the device to be present always
|
|
||||||
(it detects if the reader is indeed present before using it)
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* Types
|
|
||||||
- New NFC_ESOFT error to handle software errors (allocations, pipe
|
|
||||||
creation, etc.)
|
|
||||||
|
|
||||||
* Functions
|
|
||||||
- Remove nfc_get_default_device() function: the default device is now the
|
|
||||||
first in nfc_list_devices() or could be open using NULL connstring with
|
|
||||||
nfc_open() function.
|
|
||||||
- New enum-to-string converter functions str_nfc_modulation_type() and
|
|
||||||
str_nfc_baud_rate()
|
|
||||||
- New str_nfc_target() to convert nfc_target struct into allocated string
|
|
||||||
- New nfc_device_get_information_about() function to retreive some device's
|
|
||||||
information
|
|
||||||
- No more in/out function parameter: nfc_initiator_transceive_*() now
|
|
||||||
take a constant size for Rx buffer
|
|
||||||
- New nfc_initiator_target_is_present() to test is the previously selected
|
|
||||||
target is available in the field
|
|
||||||
- nfc_initiator_transceive_bytes() returns NFC_EMFCAUTHFAIL when AUTH
|
|
||||||
command failed on a Mifare Classic
|
|
||||||
- New nfc_initiator_init_secure_element() to initiate a connection with
|
|
||||||
secure element (Only supported with a PN532 with SAM equipped)
|
|
||||||
|
|
||||||
New in 1.6.0-rc1:
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
|
|
||||||
* Types
|
|
||||||
- '_t' suffix removed from all types (e.g. nfc_device_t is now nfc_device)
|
|
||||||
- All errors removed in flavour of NFC_EIO, NFC_EINVARG, NFC_EDEVNOTSUPP,
|
|
||||||
NFC_ENOTSUCHDEV, NFC_EOVFLOW, NFC_ETIMEOUT, NFC_EOPABORTED, NFC_ENOTIMPL,
|
|
||||||
NFC_ETGRELEASED, NFC_ERFTRANS, NFC_ECHIP and NFC_SUCCESS
|
|
||||||
- nfc_device_desc_t replaced by nfc_connstring: libnfc now uses connection
|
|
||||||
strings to describe a device
|
|
||||||
- byte_t typedef removed, libnfc now uses uint8_t from C99
|
|
||||||
- nfc_device is now an opaque type
|
|
||||||
- nfc_properties replaces nfc_options
|
|
||||||
|
|
||||||
* Functions
|
|
||||||
- New nfc_get_default_device() function that allows to grab the connstring
|
|
||||||
stored in LIBNFC_DEFAULT_DEVICE environnement variable or returns the
|
|
||||||
first available device if not set
|
|
||||||
- New nfc_device_get_connstring() accessor function to know the device
|
|
||||||
connstring
|
|
||||||
- New nfc_device_set_property_bool() function that replace nfc_configure()
|
|
||||||
- New nfc_device_set_property_int() function to set integer property
|
|
||||||
- nfc_device_name() renamed to nfc_device_get_name() for the sake of
|
|
||||||
consistency
|
|
||||||
- New nfc_device_get_last_error() function, an accessor to last error occured
|
|
||||||
- Whole libnfc's functions now return 0 (NFC_SUCCESS) or positive value if
|
|
||||||
appropriated on success and libnfc's error code on failure
|
|
||||||
- nfc_connect(), nfc_disconnect() renamed to nfc_open(), nfc_close()
|
|
||||||
respectively
|
|
||||||
- Add 2 new functions: initialization and deinitialization functions:
|
|
||||||
nfc_init() and nfc_exit()
|
|
||||||
- New nfc_device_get_supported_modulation() and
|
|
||||||
nfc_device_get_supported_baud_rate() functions
|
|
||||||
|
|
||||||
* Dependencies
|
|
||||||
- log4c is not anymore used for debugging facility. It was a bad choice,
|
|
||||||
sorry for inconvenience.
|
|
||||||
|
|
||||||
New in 1.5.1:
|
|
||||||
|
|
||||||
API Changes
|
|
||||||
|
|
||||||
* Types
|
|
||||||
- Communication-level errors DEIO and DETIMEOUT are now know as ECOMIO,
|
|
||||||
ECOMTIMEOUT respectively
|
|
||||||
- Common device-level errors DEINVAL and DEABORT are now know as EINVALARG,
|
|
||||||
EOPABORT respectively
|
|
||||||
- New errors: EFRAACKMISMATCH, EFRAISERRFRAME, EDEVNOTSUP and ENOTIMPL
|
|
||||||
|
|
||||||
* Functions
|
|
||||||
- nfc_abort_command() returns a boolean
|
|
||||||
- timeout (struct timeval) pointer added to
|
|
||||||
nfc_initiator_transceive_bytes(), nfc_target_send_bytes() and
|
|
||||||
nfc_target_receive_bytes()
|
|
||||||
- timed functions nfc_initiator_transceive_bytes_timed() and
|
|
||||||
nfc_initiator_transceive_bits_timed() now takes uint32_t as cycles
|
|
||||||
pointer
|
|
||||||
- nfc_initiator_poll_targets() renamed to nfc_initiator_poll_target() and
|
|
||||||
only return one target
|
|
||||||
|
|
||||||
New in 1.5.0:
|
New in 1.5.0:
|
||||||
|
|
||||||
Installed files
|
Installed files
|
||||||
133
README
Normal file
133
README
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romain Tartière, Romuald Conty
|
||||||
|
-*
|
||||||
|
|
||||||
|
General Information
|
||||||
|
===================
|
||||||
|
|
||||||
|
libnfc is a library which allows userspace application access to NFC devices.
|
||||||
|
|
||||||
|
The official web site is:
|
||||||
|
http://www.libnfc.org/
|
||||||
|
|
||||||
|
The official forum site is:
|
||||||
|
http://www.libnfc.org/community/
|
||||||
|
|
||||||
|
The official development site is:
|
||||||
|
http://libnfc.googlecode.com/
|
||||||
|
|
||||||
|
Important note: this file covers POSIX systems, for Windows please read README-Windows.txt
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
Some NFC drivers depends on third party software:
|
||||||
|
|
||||||
|
* pn53x_usb:
|
||||||
|
|
||||||
|
- libusb-0.1 http://libusb.sf.net
|
||||||
|
|
||||||
|
* acr122:
|
||||||
|
|
||||||
|
- pcsc-lite http://pcsclite.alioth.debian.org/
|
||||||
|
|
||||||
|
The regression test suite depend on the cutter framework:
|
||||||
|
http://cutter.sf.net
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
See the file 'INSTALL'
|
||||||
|
|
||||||
|
How to report bugs
|
||||||
|
==================
|
||||||
|
|
||||||
|
To report a bug, visit http://code.google.com/p/libnfc/issues/list and fill
|
||||||
|
out a bug report form.
|
||||||
|
|
||||||
|
If you have questions, remarks, we encourage you to post this in the developers
|
||||||
|
community:
|
||||||
|
http://www.libnfc.org/community
|
||||||
|
|
||||||
|
Please make sure to include:
|
||||||
|
|
||||||
|
* The version of libnfc
|
||||||
|
|
||||||
|
* Information about your system. For instance:
|
||||||
|
|
||||||
|
- What operating system and version
|
||||||
|
- For Linux, what version of the C library
|
||||||
|
|
||||||
|
And anything else you think is relevant.
|
||||||
|
|
||||||
|
* How to reproduce the bug.
|
||||||
|
|
||||||
|
Please include a short test program that exhibits the behavior.
|
||||||
|
As a last resort, you can also provide a pointer to a larger piece
|
||||||
|
of software that can be downloaded.
|
||||||
|
|
||||||
|
* If the bug was a crash, the exact text that was printed out
|
||||||
|
when the crash occured.
|
||||||
|
|
||||||
|
* Further information such as stack traces may be useful, but
|
||||||
|
is not necessary.
|
||||||
|
|
||||||
|
Patches
|
||||||
|
=======
|
||||||
|
|
||||||
|
Patches can be posted to http://code.google.com/p/libnfc/issues/list or
|
||||||
|
can be sent directly to libnfc's developers: http://www.libnfc.org/contact
|
||||||
|
|
||||||
|
If the patch fixes a bug, it is usually a good idea to include
|
||||||
|
all the information described in "How to Report Bugs".
|
||||||
|
|
||||||
|
Building
|
||||||
|
========
|
||||||
|
|
||||||
|
It should be as simple as running these two commands:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
===============
|
||||||
|
|
||||||
|
Touchatag/ACR122:
|
||||||
|
-----------------
|
||||||
|
If your Touchatag or ACR122 device fails being detected by PCSC-lite daemon
|
||||||
|
(pcsc_scan doesn't see anything) then try removing the bogus firmware detection
|
||||||
|
of libccid: edit libccid_Info.plist configuration file (usually
|
||||||
|
/etc/libccid_Info.plist) and locate "<key>ifdDriverOptions</key>", turn
|
||||||
|
"<string>0x0000</string>" value into 0x0004 to allow bogus devices and restart
|
||||||
|
pcscd daemon.
|
||||||
|
|
||||||
|
ACR122:
|
||||||
|
-------
|
||||||
|
Using an ACR122 device with libnfc and without tag (e.g. to use NFCIP modes or
|
||||||
|
card emulation) needs yet another PCSC-lite tweak: You need to allow usage of
|
||||||
|
CCID Exchange command. To do this, edit libccid_Info.plist configuration file
|
||||||
|
(usually /etc/libccid_Info.plist) and locate "<key>ifdDriverOptions</key>",
|
||||||
|
turn "<string>0x0000</string>" value into 0x0001 to allow CCID exchange or
|
||||||
|
0x0005 to allow CCID exchange and bogus devices (cf previous remark) and
|
||||||
|
restart pcscd daemon.
|
||||||
|
|
||||||
|
Warning: if you use ACS CCID drivers (acsccid), configuration file is located
|
||||||
|
in something like: /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist
|
||||||
|
|
||||||
|
SCL3711:
|
||||||
|
--------
|
||||||
|
Libnfc cannot be used concurrently with the PCSC proprietary driver of SCL3711.
|
||||||
|
Two possible solutions:
|
||||||
|
* Either you don't install SCL3711 driver at all
|
||||||
|
* Or you stop the PCSC daemon when you want to use libnfc-based tools
|
||||||
|
|
||||||
|
Proprietary Notes
|
||||||
|
=================
|
||||||
|
|
||||||
|
FeliCa is s registered trademark of the Sony Corporation.
|
||||||
|
MIFARE is a trademark of NXP Semiconductors.
|
||||||
|
Jewel Topaz is a trademark of Innovision Research & Technology.
|
||||||
|
All other trademarks are the property of their respective owners.
|
||||||
|
|
||||||
@ -1,27 +1,18 @@
|
|||||||
*-
|
*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
*
|
* Copyright (C) 2010, Glenn Ergeerts
|
||||||
* 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
|
|
||||||
* Additional contributors of Windows-specific parts:
|
|
||||||
* Copyright (C) 2010 Glenn Ergeerts
|
|
||||||
* Copyright (C) 2013 Alex Lian
|
|
||||||
-*
|
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
============
|
============
|
||||||
|
|
||||||
- MinGW-w64 compiler toolchain [1]
|
- MinGW-w64 compiler toolchain [1]
|
||||||
- LibUsb-Win32 1.2.5.0 (or greater) [2]
|
- LibUsb-Win32 0.1.12.2 [2]
|
||||||
- CMake 2.8 [3]
|
- CMake 2.6 [3]
|
||||||
|
|
||||||
This was tested on Windows 7 64 bit, but should work on Windows Vista and
|
This was tested on Windows 7 64 bit, but should work on Windows Vista and
|
||||||
Windows XP and 32 bit as well.
|
Windows XP and 32 bit as well.
|
||||||
Only the ACS ACR122 and the ASK Logo readers are tested at the moment, so any feedback about other devices is very welcome.
|
Only the ACS ACR122 reader is tested at the moment, so any feedback about other devices is very welcome.
|
||||||
|
|
||||||
Community forum: http://www.libnfc.org/community/
|
Community forum: http://www.libnfc.org/community/
|
||||||
|
|
||||||
@ -33,15 +24,13 @@ is an example of how to generate a distribution with the above mentioned
|
|||||||
requirements fulfilled (it is assumed the CMake binaries are in the system
|
requirements fulfilled (it is assumed the CMake binaries are in the system
|
||||||
path, this is optional during installation of CMake):
|
path, this is optional during installation of CMake):
|
||||||
|
|
||||||
- Add the following directories to your PATH:
|
- Add the following directories to your PATH : c:\MinGW64\bin;c:\MinGW64\x86_64-w64-mingw32\lib32;c:\MinGW64\x86_64-w64-mingw32\include
|
||||||
|
|
||||||
c:\MinGW64\bin;c:\MinGW64\x86_64-w64-mingw32\lib32;c:\MinGW64\x86_64-w64-mingw32\include
|
|
||||||
|
|
||||||
- Now it is possible to run CMake and mingw32-make:
|
- Now it is possible to run CMake and mingw32-make:
|
||||||
|
|
||||||
C:\dev\libnfc-read-only> mkdir ..\libnfc-build
|
C:\dev\libnfc-read-only> mkdir ..\libnfc-build
|
||||||
C:\dev\libnfc-read-only> cd ..\libnfc-build
|
C:\dev\libnfc-read-only> cd ..\libnfc-build
|
||||||
C:\dev\libnfc-build> cmake-gui .
|
C:\dev\libnfc-build> cmake-gui .
|
||||||
|
|
||||||
Now you can configure the build. Press "Configure", specify "MinGW32 Makefiles"
|
Now you can configure the build. Press "Configure", specify "MinGW32 Makefiles"
|
||||||
and then you have the opportunity to set some configuration variables. If you
|
and then you have the opportunity to set some configuration variables. If you
|
||||||
@ -49,12 +38,12 @@ don't want a Debug build change the variable CMAKE_BUILD_TYPE to "Release".
|
|||||||
|
|
||||||
If a non-GUI solution is preferred one can use:
|
If a non-GUI solution is preferred one can use:
|
||||||
|
|
||||||
C:\dev\libnfc-build> cmake -G "MinGW Makefiles"
|
C:\dev\libnfc-build> cmake -G "MinGW Makefiles"
|
||||||
-DCMAKE_BUILD_TYPE=Release ..\libnfc-read-only
|
-DCMAKE_BUILD_TYPE=Release ..\libnfc-read-only
|
||||||
|
|
||||||
Now run mingw32-make to build:
|
Now run mingw32-make to build:
|
||||||
|
|
||||||
C:\dev\libnfc-read-only\bin> mingw32-make
|
C:\dev\libnfc-read-only\bin> mingw32-make
|
||||||
|
|
||||||
The build will create a shared library for Windows (nfc.dll) to link your applications against. It will compile
|
The build will create a shared library for Windows (nfc.dll) to link your applications against. It will compile
|
||||||
the tools against this shared library.
|
the tools against this shared library.
|
||||||
@ -64,7 +53,5 @@ References
|
|||||||
[1] the easiest way is to use the TDM-GCC installer.
|
[1] the easiest way is to use the TDM-GCC installer.
|
||||||
Make sure to select MinGW-w64 in the installer, the regular MinGW does not contain headers for PCSC.
|
Make sure to select MinGW-w64 in the installer, the regular MinGW does not contain headers for PCSC.
|
||||||
http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download
|
http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download
|
||||||
|
[2] http://libusb-win32.sourceforge.net/
|
||||||
[2] http://sourceforge.net/projects/libusb-win32/files/
|
|
||||||
|
|
||||||
[3] http://www.cmake.org
|
[3] http://www.cmake.org
|
||||||
250
README.md
250
README.md
@ -1,250 +0,0 @@
|
|||||||
```
|
|
||||||
*-
|
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
|
||||||
*
|
|
||||||
* Libnfc historical contributors:
|
|
||||||
* Copyright (C) 2009 Roel Verdult
|
|
||||||
* Copyright (C) 2009-2015 Romuald Conty
|
|
||||||
* Copyright (C) 2010-2012 Romain Tartière
|
|
||||||
* Copyright (C) 2010-2013 Philippe Teuwen
|
|
||||||
* Copyright (C) 2012-2013 Ludovic Rousseau
|
|
||||||
* Additional contributors:
|
|
||||||
* See AUTHORS file
|
|
||||||
-*
|
|
||||||
```
|
|
||||||
|
|
||||||
General Information
|
|
||||||
===================
|
|
||||||
|
|
||||||
libnfc is a library which allows userspace application access to NFC devices.
|
|
||||||
|
|
||||||
The official web site is:
|
|
||||||
http://www.nfc-tools.org/
|
|
||||||
|
|
||||||
The official forum site is:
|
|
||||||
http://www.libnfc.org/community/
|
|
||||||
|
|
||||||
The official development site is:
|
|
||||||
https://github.com/nfc-tools/libnfc
|
|
||||||
|
|
||||||
Important note: this file covers POSIX systems, for Windows please read README-Windows.md
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
============
|
|
||||||
|
|
||||||
Some NFC drivers depend on third party software:
|
|
||||||
|
|
||||||
* pn53x_usb & acr122_usb:
|
|
||||||
|
|
||||||
- libusb-0.1 http://libusb.sf.net
|
|
||||||
|
|
||||||
* acr122_pcsc:
|
|
||||||
|
|
||||||
- pcsc-lite https://pcsclite.apdu.fr/
|
|
||||||
- pcsc:
|
|
||||||
|
|
||||||
- Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test.
|
|
||||||
|
|
||||||
The regression test suite depends on the cutter framework:
|
|
||||||
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
|
|
||||||
============
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
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.
|
|
||||||
e.g. under Debian, Ubuntu, etc.
|
|
||||||
|
|
||||||
sudo cp contrib/udev/93-pn53x.rules /lib/udev/rules.d/
|
|
||||||
|
|
||||||
Under FreeBSD, if you use devd, there is also a rules file: contrib/devd/pn53x.conf.
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
=============
|
|
||||||
|
|
||||||
In order to change the default behavior of the library, the libnfc uses a
|
|
||||||
configuration file located in sysconfdir (as provided to ./configure).
|
|
||||||
|
|
||||||
A sample commented file is available in sources: libnfc.conf.sample
|
|
||||||
|
|
||||||
If you have compiled using:
|
|
||||||
|
|
||||||
./configure --prefix=/usr --sysconfdir=/etc
|
|
||||||
|
|
||||||
you can make configuration directory and copy the sample file:
|
|
||||||
|
|
||||||
sudo mkdir /etc/nfc
|
|
||||||
sudo cp libnfc.conf.sample /etc/nfc/libnfc.conf
|
|
||||||
|
|
||||||
To configure multiple devices, you can either modify libnfc.conf or create a
|
|
||||||
file per device in a nfc/devices.d directory:
|
|
||||||
|
|
||||||
sudo mkdir -p /etc/nfc/devices.d
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
==================
|
|
||||||
|
|
||||||
To report a bug, visit https://github.com/nfc-tools/libnfc/issues and fill
|
|
||||||
out a bug report form.
|
|
||||||
|
|
||||||
If you have questions, remarks, we encourage you to post this in the developers
|
|
||||||
community:
|
|
||||||
http://www.libnfc.org/community
|
|
||||||
|
|
||||||
Please make sure to include:
|
|
||||||
|
|
||||||
* The version of libnfc
|
|
||||||
|
|
||||||
* Information about your system. For instance:
|
|
||||||
|
|
||||||
- What operating system and version
|
|
||||||
- For Linux, what version of the C library
|
|
||||||
|
|
||||||
And anything else you think is relevant.
|
|
||||||
|
|
||||||
* A trace with debug activated.
|
|
||||||
|
|
||||||
Reproduce the bug with debug, e.g. if it was:
|
|
||||||
|
|
||||||
$ nfc-list -v
|
|
||||||
|
|
||||||
run it as:
|
|
||||||
|
|
||||||
$ LIBNFC_LOG_LEVEL=3 nfc-list -v
|
|
||||||
|
|
||||||
* How to reproduce the bug.
|
|
||||||
|
|
||||||
Please include a short test program that exhibits the behavior.
|
|
||||||
|
|
||||||
As a last resort, you can also provide a pointer to a larger piece
|
|
||||||
|
|
||||||
of software that can be downloaded.
|
|
||||||
|
|
||||||
* If the bug was a crash, the exact text that was printed out
|
|
||||||
|
|
||||||
when the crash occured.
|
|
||||||
|
|
||||||
* Further information such as stack traces may be useful, but
|
|
||||||
|
|
||||||
is not necessary.
|
|
||||||
|
|
||||||
Patches
|
|
||||||
=======
|
|
||||||
|
|
||||||
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
|
|
||||||
all the information described in "How to Report Bugs".
|
|
||||||
|
|
||||||
Troubleshooting
|
|
||||||
===============
|
|
||||||
|
|
||||||
Touchatag/ACR122:
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
If your Touchatag or ACR122 device fails being detected by libnfc, make sure
|
|
||||||
that PCSC-lite daemon (`pcscd`) is installed and is running.
|
|
||||||
|
|
||||||
If your Touchatag or ACR122 device fails being detected by PCSC-lite daemon
|
|
||||||
(`pcsc_scan` doesn't see anything) then try removing the bogus firmware detection
|
|
||||||
of libccid: edit libccid_Info.plist configuration file (usually
|
|
||||||
`/etc/libccid_Info.plist`) and locate `<key>ifdDriverOptions</key>`, turn
|
|
||||||
`<string>0x0000</string>` value into `0x0004` to allow bogus devices and restart
|
|
||||||
pcscd daemon.
|
|
||||||
|
|
||||||
ACR122:
|
|
||||||
-------
|
|
||||||
|
|
||||||
Using an ACR122 device with libnfc and without tag (e.g. to use NFCIP modes or
|
|
||||||
card emulation) needs yet another PCSC-lite tweak: You need to allow usage of
|
|
||||||
CCID Exchange command. To do this, edit `libccid_Info.plist` configuration file
|
|
||||||
(usually `/etc/libccid_Info.plist`) and locate `<key>ifdDriverOptions</key>`,
|
|
||||||
turn `<string>0x0000</string>` value into `0x0001` to allow CCID exchange or
|
|
||||||
`0x0005` to allow CCID exchange and bogus devices (cf previous remark) and
|
|
||||||
restart pcscd daemon.
|
|
||||||
|
|
||||||
Warning: if you use ACS CCID drivers (acsccid), configuration file is located
|
|
||||||
in something like: `/usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist`
|
|
||||||
|
|
||||||
SCL3711:
|
|
||||||
--------
|
|
||||||
|
|
||||||
Libnfc cannot be used concurrently with the PCSC proprietary driver of SCL3711.
|
|
||||||
Two possible solutions:
|
|
||||||
|
|
||||||
* Either you don't install SCL3711 driver at all
|
|
||||||
* Or you stop the PCSC daemon when you want to use libnfc-based tools
|
|
||||||
|
|
||||||
PN533 USB device on Linux >= 3.1:
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
Since Linux kernel version 3.1, a few kernel-modules must not be loaded in order
|
|
||||||
to use libnfc : "nfc", "pn533" and "pn533_usb".
|
|
||||||
To prevent kernel from loading automatically these modules, you can blacklist
|
|
||||||
them in a modprobe conf file. This file is provided within libnfc archive:
|
|
||||||
|
|
||||||
sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf
|
|
||||||
|
|
||||||
FEITIAN bR500 and R502:
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Libnfc can work with PCSC proprietary driver of bR500 and R502, which is already available on most Linux setups.
|
|
||||||
To activate the PCSC support: `./configure --with-drivers=pcsc`.
|
|
||||||
Readers known to work:
|
|
||||||
|
|
||||||
- Feitian bR500
|
|
||||||
- Feitian R502 Dual interface reader
|
|
||||||
- Feitian R502 CL(Contactless) reader
|
|
||||||
|
|
||||||
These readers are support by CCID since v1.4.25, make sure your CCID driver version higher or equal to 1.4.25.
|
|
||||||
|
|
||||||
On MacOS, you can check your CCID version with the following command, and if required, you can install latest CCID driver from [https://github.com/martinpaljak/osx-ccid-installer/releases](https://github.com/martinpaljak/osx-ccid-installer/releases)
|
|
||||||
|
|
||||||
```
|
|
||||||
grep -A 1 CFBundleShortVersionString /usr/local/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
|
|
||||||
```
|
|
||||||
|
|
||||||
On Linux, you can check your CCID version with the following command, and if required, you can install latest CCID driver from [https://ccid.apdu.fr/](https://ccid.apdu.fr/)
|
|
||||||
|
|
||||||
```
|
|
||||||
grep -A 1 CFBundleShortVersionString /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
|
||||||
```
|
|
||||||
|
|
||||||
Proprietary Notes
|
|
||||||
=================
|
|
||||||
FeliCa is a registered trademark of the Sony Corporation.
|
|
||||||
MIFARE is a trademark of NXP Semiconductors.
|
|
||||||
Jewel Topaz is a trademark of Innovision Research & Technology.
|
|
||||||
All other trademarks are the property of their respective owners.
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
# -*- cmake -*-
|
|
||||||
|
|
||||||
|
|
||||||
# Use the following variables to compile and link against LibNFC:
|
|
||||||
# LIBNFC_FOUND - True if LibNFC was found on your system
|
|
||||||
# LIBNFC_USE_FILE - The file making LibNFC usable
|
|
||||||
# LIBNFC_DEFINITIONS - Definitions needed to build with LibNFC
|
|
||||||
# LIBNFC_INCLUDE_DIR - Directory where nfc/nfc.h can be found
|
|
||||||
# LIBNFC_INCLUDE_DIRS - List of directories of LibNFC and it's dependencies
|
|
||||||
# LIBNFC_LIBRARY - LibNFC library location
|
|
||||||
# LIBNFC_LIBRARIES - List of libraries to link against LibNFC library
|
|
||||||
# LIBNFC_LIBRARY_DIRS - List of directories containing LibNFC' libraries
|
|
||||||
# LIBNFC_ROOT_DIR - The base directory of LibNFC
|
|
||||||
# LIBNFC_VERSION_STRING - A human-readable string containing the version
|
|
||||||
# LIBNFC_VERSION_MAJOR - The major version of LibNFC
|
|
||||||
# LIBNFC_VERSION_MINOR - The minor version of LibNFC
|
|
||||||
# LIBNFC_VERSION_PATCH - The patch version of LibNFC
|
|
||||||
|
|
||||||
set ( LIBNFC_FOUND 1 )
|
|
||||||
set ( LIBNFC_USE_FILE "@LIBNFC_USE_FILE@" )
|
|
||||||
|
|
||||||
set ( LIBNFC_DEFINITIONS "@LIBNFC_DEFINITIONS@" )
|
|
||||||
set ( LIBNFC_INCLUDE_DIR "@LIBNFC_INCLUDE_DIR@" )
|
|
||||||
set ( LIBNFC_INCLUDE_DIRS "@LIBNFC_INCLUDE_DIRS@" )
|
|
||||||
set ( LIBNFC_LIBRARY "@LIBNFC_LIBRARY@" )
|
|
||||||
set ( LIBNFC_LIBRARIES "@LIBNFC_LIBRARIES@" )
|
|
||||||
set ( LIBNFC_LIBRARY_DIRS "@LIBNFC_LIBRARY_DIRS@" )
|
|
||||||
set ( LIBNFC_ROOT_DIR "@LIBNFC_ROOT_DIR@" )
|
|
||||||
|
|
||||||
set ( LIBNFC_VERSION_STRING "@LIBNFC_VERSION_STRING@" )
|
|
||||||
set ( LIBNFC_VERSION_MAJOR "@LIBNFC_VERSION_MAJOR@" )
|
|
||||||
set ( LIBNFC_VERSION_MINOR "@LIBNFC_VERSION_MINOR@" )
|
|
||||||
set ( LIBNFC_VERSION_PATCH "@LIBNFC_VERSION_PATCH@" )
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
# This is a basic version file for the Config-mode of find_package().
|
|
||||||
# It is used by write_basic_package_version_file() as input file for configure_file()
|
|
||||||
# to create a version-file which can be installed along a config.cmake file.
|
|
||||||
#
|
|
||||||
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
|
|
||||||
# the requested version string are exactly the same and it sets
|
|
||||||
# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
|
|
||||||
# The variable CVF_VERSION must be set before calling configure_file().
|
|
||||||
|
|
||||||
set(PACKAGE_VERSION "@LIBNFC_VERSION_STRING@")
|
|
||||||
|
|
||||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
||||||
else()
|
|
||||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
|
||||||
if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
|
|
||||||
set(PACKAGE_VERSION_EXACT TRUE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
|
|
||||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
|
|
||||||
if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
|
||||||
math(EXPR installedBits "8 * 8")
|
|
||||||
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
|
|
||||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
|
||||||
endif()
|
|
||||||
@ -1,9 +1,5 @@
|
|||||||
SUBDIRS = modules
|
SUBDIRS = modules
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
FixBundle.cmake.in \
|
|
||||||
config_posix.h.cmake \
|
config_posix.h.cmake \
|
||||||
config_windows.h.cmake \
|
config_windows.h.cmake
|
||||||
LibNFCConfig.cmake.in \
|
|
||||||
LibNFCConfigVersion.cmake.in \
|
|
||||||
UseLibNFC.cmake
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
# -*- cmake -*-
|
|
||||||
|
|
||||||
add_definitions ( ${LIBNFC_DEFINITIONS} )
|
|
||||||
include_directories ( ${LIBNFC_INCLUDE_DIRS} )
|
|
||||||
link_directories ( ${LIBNFC_LIBRARY_DIRS} )
|
|
||||||
@ -2,4 +2,3 @@
|
|||||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||||
#cmakedefine _XOPEN_SOURCE @_XOPEN_SOURCE@
|
#cmakedefine _XOPEN_SOURCE @_XOPEN_SOURCE@
|
||||||
#cmakedefine SYSCONFDIR "@SYSCONFDIR@"
|
|
||||||
|
|||||||
@ -3,4 +3,3 @@
|
|||||||
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
|
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
|
||||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||||
#cmakedefine LIBNFC_SYSCONFDIR "@LIBNFC_SYSCONFDIR@"
|
|
||||||
|
|||||||
@ -25,31 +25,23 @@ IF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
|
|||||||
ENDIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
|
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 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(WIN32)
|
||||||
ELSE(MINGW)
|
# If not under Windows we use PkgConfig
|
||||||
FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramW6432}/libusb-win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
|
FIND_PACKAGE (PkgConfig)
|
||||||
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64")
|
IF(PKG_CONFIG_FOUND)
|
||||||
SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramW6432}/libusb-win32/bin/amd64/")
|
PKG_CHECK_MODULES(LIBUSB REQUIRED libusb)
|
||||||
ENDIF(MINGW)
|
ELSE(PKG_CONFIG_FOUND)
|
||||||
# Must fix up variable to avoid backslashes during packaging
|
MESSAGE(FATAL_ERROR "Could not find PkgConfig")
|
||||||
STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR})
|
ENDIF(PKG_CONFIG_FOUND)
|
||||||
ELSE(WIN32)
|
ENDIF(WIN32)
|
||||||
# If not under Windows we use PkgConfig
|
|
||||||
FIND_PACKAGE (PkgConfig)
|
|
||||||
IF(PKG_CONFIG_FOUND)
|
|
||||||
PKG_CHECK_MODULES(LIBUSB REQUIRED libusb)
|
|
||||||
ELSE(PKG_CONFIG_FOUND)
|
|
||||||
MESSAGE(FATAL_ERROR "Could not find PkgConfig")
|
|
||||||
ENDIF(PKG_CONFIG_FOUND)
|
|
||||||
ENDIF(WIN32)
|
|
||||||
|
|
||||||
IF(LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES)
|
IF(LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES)
|
||||||
SET(LIBUSB_FOUND TRUE)
|
SET(LIBUSB_FOUND TRUE)
|
||||||
ENDIF(LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES)
|
ENDIF(LIBUSB_INCLUDE_DIRS AND LIBUSB_LIBRARIES)
|
||||||
ENDIF(NOT LIBUSB_FOUND)
|
ENDIF(NOT LIBUSB_FOUND)
|
||||||
|
|
||||||
IF(LIBUSB_FOUND)
|
IF(LIBUSB_FOUND)
|
||||||
|
|||||||
@ -1,78 +1,29 @@
|
|||||||
SET(LIBNFC_DRIVER_PCSC OFF CACHE BOOL "Enable PC/SC reader support (Depends on PC/SC)")
|
SET(LIBNFC_DRIVER_ACR122 ON CACHE BOOL "Enable ACR122 support (Depends on PC/SC)")
|
||||||
SET(LIBNFC_DRIVER_ACR122_PCSC OFF CACHE BOOL "Enable ACR122 support (Depends on PC/SC)")
|
|
||||||
SET(LIBNFC_DRIVER_ACR122_USB ON CACHE BOOL "Enable ACR122 support (Direct USB connection)")
|
|
||||||
SET(LIBNFC_DRIVER_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)")
|
|
||||||
SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)")
|
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
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_SPI OFF CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
|
|
||||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
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)")
|
||||||
|
SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)")
|
||||||
|
SET(LIBNFC_DRIVER_PN532_UART OFF CACHE BOOL "Enable PN532 UART support (Use serial port)")
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_PCSC)
|
IF(LIBNFC_DRIVER_ACR122)
|
||||||
FIND_PACKAGE(PCSC REQUIRED)
|
FIND_PACKAGE(PCSC REQUIRED)
|
||||||
ADD_DEFINITIONS("-DDRIVER_PCSC_ENABLED")
|
ADD_DEFINITIONS("-DDRIVER_ACR122_ENABLED")
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pcsc")
|
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122")
|
||||||
ENDIF(LIBNFC_DRIVER_PCSC)
|
ENDIF(LIBNFC_DRIVER_ACR122)
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_ACR122_PCSC)
|
|
||||||
FIND_PACKAGE(PCSC REQUIRED)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_ACR122_PCSC_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122_pcsc")
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
FIND_PACKAGE(LIBUSB REQUIRED)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_ACR122_USB_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122_usb")
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_ACR122S)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_ACR122S_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122s")
|
|
||||||
SET(UART_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122S)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_ARYGON)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_ARYGON_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/arygon")
|
|
||||||
SET(UART_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_ARYGON)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_PN532_I2C)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_PN532_I2C_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn532_i2c")
|
|
||||||
SET(I2C_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_PN532_I2C)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_PN532_SPI)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_PN532_SPI_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn532_spi")
|
|
||||||
SET(SPI_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_PN532_SPI)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_PN532_UART)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_PN532_UART_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn532_uart")
|
|
||||||
SET(UART_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_PN532_UART)
|
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_PN53X_USB)
|
IF(LIBNFC_DRIVER_PN53X_USB)
|
||||||
FIND_PACKAGE(LIBUSB REQUIRED)
|
FIND_PACKAGE(LIBUSB REQUIRED)
|
||||||
ADD_DEFINITIONS("-DDRIVER_PN53X_USB_ENABLED")
|
ADD_DEFINITIONS("-DDRIVER_PN53X_USB_ENABLED")
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn53x_usb")
|
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn53x_usb")
|
||||||
SET(USB_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_PN53X_USB)
|
ENDIF(LIBNFC_DRIVER_PN53X_USB)
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_ACR122_USB)
|
IF(LIBNFC_DRIVER_ARYGON)
|
||||||
FIND_PACKAGE(LIBUSB REQUIRED)
|
ADD_DEFINITIONS("-DDRIVER_ARYGON_ENABLED")
|
||||||
ADD_DEFINITIONS("-DDRIVER_ACR122_USB_ENABLED")
|
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/arygon")
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122_usb")
|
ENDIF(LIBNFC_DRIVER_ARYGON)
|
||||||
SET(USB_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_USB)
|
IF(LIBNFC_DRIVER_PN532_UART)
|
||||||
|
ADD_DEFINITIONS("-DDRIVER_PN532_UART_ENABLED")
|
||||||
|
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn532_uart")
|
||||||
|
ENDIF(LIBNFC_DRIVER_PN532_UART)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/drivers)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers)
|
|
||||||
|
|||||||
@ -91,7 +91,8 @@ if(DOXYGEN_FOUND AND DOXYFILE_IN)
|
|||||||
|
|
||||||
configure_file(${DOXYFILE_IN} Doxyfile ESCAPE_QUOTES IMMEDIATE @ONLY)
|
configure_file(${DOXYFILE_IN} Doxyfile ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||||
|
|
||||||
if(NOT TARGET doc)
|
get_target_property(DOC_TARGET doc TYPE)
|
||||||
|
if(NOT DOC_TARGET)
|
||||||
add_custom_target(doc)
|
add_custom_target(doc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
126
configure.ac
126
configure.ac
@ -1,30 +1,28 @@
|
|||||||
# General init
|
# General init
|
||||||
|
|
||||||
# /!\ Don't forget to update 'CMakeLists.txt' too /!\
|
# /!\ Don't forget to update 'CMakeLists.txt' too /!\
|
||||||
AC_INIT([libnfc],[1.8.0],[nfc-tools@googlegroups.com])
|
AC_INIT(libnfc, 1.5.0, info@libnfc.org)
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
# GIT revison
|
# SVN revison
|
||||||
GIT_REVISION=`which git > /dev/null && git describe`
|
define([svn_revision], esyscmd([sh -c "svnversion -n"]))
|
||||||
if test x"$GIT_REVISION" != x""; then
|
SVN_REVISION=svn_revision
|
||||||
AC_DEFINE_UNQUOTED([GIT_REVISION], ["$GIT_REVISION"], [GIT revision])
|
AC_DEFINE_UNQUOTED([SVN_REVISION], ["$SVN_REVISION"], [SVN revision])
|
||||||
fi
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE(subdir-objects dist-bzip2 no-dist-gzip foreign)
|
AM_INIT_AUTOMAKE
|
||||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
|
||||||
|
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
AC_LANG([C])
|
AC_LANG_C
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
|
|
||||||
WITH_POSIX_ONLY_EXAMPLES=1
|
WITH_POSIX_ONLY_EXAMPLES=1
|
||||||
# Libtool
|
# Libtool
|
||||||
LT_INIT
|
AC_PROG_LIBTOOL
|
||||||
case "$host" in
|
case "$host" in
|
||||||
*-pc-linux-gnu)
|
*-pc-linux-gnu)
|
||||||
AC_MSG_RESULT([Fixing libtool for -rpath problems.])
|
AC_MSG_RESULT([Fixing libtool for -rpath problems.])
|
||||||
@ -39,22 +37,23 @@ case "$host" in
|
|||||||
esac
|
esac
|
||||||
AM_CONDITIONAL(POSIX_ONLY_EXAMPLES_ENABLED, [test "$WITH_POSIX_ONLY_EXAMPLES" = "1"])
|
AM_CONDITIONAL(POSIX_ONLY_EXAMPLES_ENABLED, [test "$WITH_POSIX_ONLY_EXAMPLES" = "1"])
|
||||||
|
|
||||||
PKG_PROG_PKG_CONFIG
|
AC_PATH_PROG(PKG_CONFIG, pkg-config)
|
||||||
|
if test x"$PKG_CONFIG" = x""; then
|
||||||
|
AC_MSG_ERROR([pkg-config not found.])
|
||||||
|
fi
|
||||||
|
|
||||||
# Checks for header files.
|
# Checks for header files.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_HEADER_STDBOOL
|
AC_HEADER_STDBOOL
|
||||||
AC_CHECK_HEADERS([fcntl.h limits.h stdio.h stdlib.h stdint.h stddef.h stdbool.h sys/ioctl.h sys/param.h sys/time.h termios.h])
|
AC_CHECK_HEADERS([fcntl.h limits.h stdio.h stdlib.h stdint.h stddef.h stdbool.h sys/ioctl.h sys/param.h sys/time.h termios.h])
|
||||||
AC_CHECK_HEADERS([linux/spi/spidev.h], [spi_available="yes"])
|
|
||||||
AC_CHECK_HEADERS([linux/i2c-dev.h], [i2c_available="yes"])
|
|
||||||
AC_CHECK_HEADERS([linux_nfc_api.h], [nfc_nci_available="yes"])
|
|
||||||
AC_CHECK_FUNCS([memmove memset select strdup strerror strstr strtol usleep],
|
AC_CHECK_FUNCS([memmove memset select strdup strerror strstr strtol usleep],
|
||||||
[AC_DEFINE([_XOPEN_SOURCE], [600], [Enable POSIX extensions if present])])
|
[AC_DEFINE([_XOPEN_SOURCE], [600], [Enable POSIX extensions if present])])
|
||||||
|
|
||||||
AC_DEFINE(_NETBSD_SOURCE, 1, [Define on NetBSD to activate all library features])
|
AC_DEFINE(_NETBSD_SOURCE, 1, [Define on NetBSD to activate all library features])
|
||||||
AC_DEFINE(_DARWIN_C_SOURCE, 1, [Define on Darwin to activate all library features])
|
AC_DEFINE(_DARWIN_C_SOURCE, 1, [Define on Darwin to activate all library features])
|
||||||
|
|
||||||
# Note: malloc function should be tested but it produces some error while cross-compiling with MinGW
|
# XXX malloc function should be tested
|
||||||
|
# but it produces some error while cross-compiling with MinGW
|
||||||
# AC_FUNC_MALLOC
|
# AC_FUNC_MALLOC
|
||||||
|
|
||||||
# Checks for types
|
# Checks for types
|
||||||
@ -63,82 +62,37 @@ AC_TYPE_UINT8_T
|
|||||||
AC_TYPE_UINT16_T
|
AC_TYPE_UINT16_T
|
||||||
AC_TYPE_UINT32_T
|
AC_TYPE_UINT32_T
|
||||||
AC_TYPE_UINT64_T
|
AC_TYPE_UINT64_T
|
||||||
AC_TYPE_INT16_T
|
|
||||||
AC_TYPE_INT32_T
|
AC_TYPE_INT32_T
|
||||||
AC_TYPE_OFF_T
|
AC_TYPE_OFF_T
|
||||||
|
|
||||||
|
AC_TYPE_SIGNAL
|
||||||
|
|
||||||
LIBNFC_CFLAGS='-I$(top_srcdir)/libnfc -I$(top_builddir)/include -I$(top_srcdir)/include'
|
LIBNFC_CFLAGS='-I$(top_srcdir)/libnfc -I$(top_builddir)/include -I$(top_srcdir)/include'
|
||||||
AC_SUBST(LIBNFC_CFLAGS)
|
AC_SUBST(LIBNFC_CFLAGS)
|
||||||
|
|
||||||
# Log support (default:yes)
|
|
||||||
AC_ARG_ENABLE([log],AS_HELP_STRING([--disable-log],[Disable any logs]),[enable_log=$enableval],[enable_log="yes"])
|
|
||||||
AC_MSG_CHECKING(for log flag)
|
|
||||||
AC_MSG_RESULT($enable_log)
|
|
||||||
AM_CONDITIONAL([WITH_LOG], [test "$enable_log" != "no"])
|
|
||||||
|
|
||||||
if test x"$enable_log" = "xyes"
|
|
||||||
then
|
|
||||||
AC_DEFINE([LOG], [1], [Enable log])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Conffiles support (default:yes)
|
|
||||||
AC_ARG_ENABLE([conffiles],AS_HELP_STRING([--disable-conffiles],[Disable use of config files]),[enable_conffiles=$enableval],[enable_conffiles="yes"])
|
|
||||||
AC_MSG_CHECKING(for conffiles flag)
|
|
||||||
AC_MSG_RESULT($enable_conffiles)
|
|
||||||
AM_CONDITIONAL([WITH_CONFFILES], [test "$enable_conffiles" != "no"])
|
|
||||||
|
|
||||||
if test x"$enable_conffiles" = "xyes"
|
|
||||||
then
|
|
||||||
AC_DEFINE([CONFFILES], [1], [Enable conffiles])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Envvars support (default:yes)
|
|
||||||
AC_ARG_ENABLE([envvars],AS_HELP_STRING([--disable-envvars],[Disable use of environment variables]),[enable_envvars=$enableval],[enable_envvars="yes"])
|
|
||||||
AC_MSG_CHECKING(for envvars flag)
|
|
||||||
AC_MSG_RESULT($enable_envvars)
|
|
||||||
AM_CONDITIONAL([WITH_ENVVARS], [test "$enable_envvars" != "no"])
|
|
||||||
|
|
||||||
if test x"$enable_envvars" = "xyes"
|
|
||||||
then
|
|
||||||
AC_DEFINE([ENVVARS], [1], [Enable envvars])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Debug support (default:no)
|
# Debug support (default:no)
|
||||||
AC_ARG_ENABLE([debug],AS_HELP_STRING([--enable-debug],[Enable debug mode]),[enable_debug=$enableval],[enable_debug="no"])
|
AC_ARG_ENABLE([debug],AS_HELP_STRING([--enable-debug],[Enable debug output]),[enable_debug=$enableval],[enable_debug="no"])
|
||||||
|
|
||||||
AC_MSG_CHECKING(for debug flag)
|
AC_MSG_CHECKING(for debug flag)
|
||||||
AC_MSG_RESULT($enable_debug)
|
AC_MSG_RESULT($enable_debug)
|
||||||
AM_CONDITIONAL([WITH_DEBUG], [test "$enable_debug" != "no"])
|
|
||||||
|
|
||||||
if test x"$enable_debug" = "xyes"
|
if test x"$enable_debug" = "xyes"
|
||||||
then
|
then
|
||||||
AC_DEFINE([DEBUG], [1], [Enable debug flag])
|
CFLAGS="$CFLAGS -g -DDEBUG -O0 -ggdb"
|
||||||
CFLAGS="$CFLAGS -g -O0 -ggdb"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Handle --with-drivers option
|
# Handle --with-drivers option
|
||||||
LIBNFC_ARG_WITH_DRIVERS
|
LIBNFC_ARG_WITH_DRIVERS
|
||||||
|
|
||||||
# Enable UART if
|
# Serial autoprobing support (default:no)
|
||||||
AM_CONDITIONAL(UART_ENABLED, [test x"$uart_required" = x"yes"])
|
AC_ARG_ENABLE([serial-autoprobe],AS_HELP_STRING([--enable-serial-autoprobe],[Allow serial ports to be probed (can seriously disturb connected serial devices)]),[enable_serial_autoprobe=$enableval],[enable_serial_autoprobe="no"])
|
||||||
|
|
||||||
# Enable SPI if
|
AC_MSG_CHECKING(for serial autoprobe flag)
|
||||||
AM_CONDITIONAL(SPI_ENABLED, [test x"$spi_required" = x"yes"])
|
AC_MSG_RESULT($enable_serial_autoprobe)
|
||||||
|
|
||||||
# Enable I2C if
|
if test x"$enable_serial_autoprobe" = "xyes"
|
||||||
AM_CONDITIONAL(I2C_ENABLED, [test x"$i2c_required" = x"yes"])
|
|
||||||
if test x"$i2c_required" = x"yes"
|
|
||||||
then
|
then
|
||||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
CFLAGS="$CFLAGS -DSERIAL_AUTOPROBE_ENABLED"
|
||||||
fi
|
|
||||||
|
|
||||||
# Enable Libnfc-NCI if required
|
|
||||||
if test x"$nfc_nci_required" = x"yes"
|
|
||||||
then
|
|
||||||
PKG_CHECK_MODULES([LIBNFC_NCI], [libnfc-nci],
|
|
||||||
[AC_MSG_NOTICE([libnfc-nci present])],
|
|
||||||
[AC_MSG_ERROR([libnfc-nci not present but required for some drivers configuration])]
|
|
||||||
)
|
|
||||||
CFLAGS="$CFLAGS $LIBNFC_NCI_CFLAGS"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Documentation (default: no)
|
# Documentation (default: no)
|
||||||
@ -157,13 +111,15 @@ 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)
|
# The indent target require GNU indent
|
||||||
AC_ARG_ENABLE([example],AS_HELP_STRING([--enable-example],[Enable example build.]),[enable_example=$enableval],[enable_example="yes"])
|
AC_PATH_PROG([INDENT], [indent])
|
||||||
|
AC_PATH_PROG([GINDENT], [gindent])
|
||||||
|
if test x"$GINDENT" != x""; then
|
||||||
|
INDENT="$GINDENT"
|
||||||
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING(for example build)
|
AC_SUBST(INDENT)
|
||||||
AC_MSG_RESULT($enable_example)
|
AM_CONDITIONAL(HAS_INDENT, [test x"$INDENT" != x""])
|
||||||
|
|
||||||
AM_CONDITIONAL(EXAMPLE_ENABLED, [test x"$enable_example" = xyes])
|
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
PKG_CONFIG_REQUIRES=""
|
PKG_CONFIG_REQUIRES=""
|
||||||
@ -176,17 +132,14 @@ AC_SUBST(PKG_CONFIG_REQUIRES)
|
|||||||
AM_CONDITIONAL(LIBUSB_ENABLED, [test "$HAVE_LIBUSB" = "1"])
|
AM_CONDITIONAL(LIBUSB_ENABLED, [test "$HAVE_LIBUSB" = "1"])
|
||||||
AM_CONDITIONAL(PCSC_ENABLED, [test "$HAVE_PCSC" = "1"])
|
AM_CONDITIONAL(PCSC_ENABLED, [test "$HAVE_PCSC" = "1"])
|
||||||
|
|
||||||
CUTTER_REQUIRED_VERSION=1.1.7
|
CUTTER_REQUIRED_VERSION=1.1.2
|
||||||
m4_ifdef([AC_CHECK_CUTTER], [AC_CHECK_CUTTER([>= $CUTTER_REQUIRED_VERSION])], [ac_cv_use_cutter="no"])
|
m4_ifdef([AC_CHECK_CUTTER], [AC_CHECK_CUTTER([>= $CUTTER_REQUIRED_VERSION])], [ac_cv_use_cutter="no"])
|
||||||
if test x$ac_cv_with_cutter = xyes -a x$ac_cv_use_cutter = xno; then
|
if test x$ac_cv_with_cutter = xyes -a x$ac_cv_use_cutter = xno; then
|
||||||
AC_MSG_ERROR([cutter >= $CUTTER_REQUIRED_VERSION is mandatory.])
|
AC_MSG_ERROR([cutter >= $CUTTER_REQUIRED_VERSION is mandatory.])
|
||||||
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"
|
||||||
@ -200,17 +153,11 @@ CFLAGS="$CFLAGS -Du_int8_t=uint8_t -Du_int16_t=uint16_t"
|
|||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Doxyfile
|
Doxyfile
|
||||||
Makefile
|
Makefile
|
||||||
cmake/Makefile
|
|
||||||
cmake/modules/Makefile
|
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
contrib/devd/Makefile
|
|
||||||
contrib/libnfc/Makefile
|
|
||||||
contrib/linux/Makefile
|
|
||||||
contrib/udev/Makefile
|
|
||||||
contrib/win32/Makefile
|
contrib/win32/Makefile
|
||||||
contrib/win32/sys/Makefile
|
contrib/win32/sys/Makefile
|
||||||
contrib/win32/libnfc/Makefile
|
cmake/Makefile
|
||||||
contrib/win32/libnfc/buses/Makefile
|
cmake/modules/Makefile
|
||||||
examples/Makefile
|
examples/Makefile
|
||||||
examples/pn53x-tamashell-scripts/Makefile
|
examples/pn53x-tamashell-scripts/Makefile
|
||||||
include/Makefile
|
include/Makefile
|
||||||
@ -221,7 +168,6 @@ AC_CONFIG_FILES([
|
|||||||
libnfc/chips/Makefile
|
libnfc/chips/Makefile
|
||||||
libnfc/drivers/Makefile
|
libnfc/drivers/Makefile
|
||||||
test/Makefile
|
test/Makefile
|
||||||
utils/Makefile
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
SUBDIRS = \
|
SUBDIRS = win32
|
||||||
devd \
|
|
||||||
libnfc \
|
|
||||||
linux \
|
|
||||||
udev \
|
|
||||||
win32
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
windows.h
|
windows.h
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
EXTRA_DIST = \
|
|
||||||
pn53x.conf
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
EXTRA_DIST = \
|
|
||||||
arygon.conf.sample \
|
|
||||||
pn532_i2c_on_rpi.conf.sample \
|
|
||||||
pn532_spi_on_rpi.conf.sample \
|
|
||||||
pn532_uart_on_rpi_3.conf.sample \
|
|
||||||
pn532_uart_on_rpi.conf.sample \
|
|
||||||
pn532_via_uart2usb.conf.sample
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
## Typical configuration file for Arygon/IDentive device (with Arygon-MCU on board)
|
|
||||||
name = "IDentive"
|
|
||||||
connstring = arygon:/dev/ttyS0
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
## Typical configuration file for PN532 device on R-Pi connected using I2C
|
|
||||||
## Note: to use SPI port on R-Pi, you have to load kernel modules i2c-bcm2708 and i2c-dev:
|
|
||||||
## Edit /etc/modprobe.d/raspi-blacklist.conf and comment: #blacklist i2c-bcm2708
|
|
||||||
## Edit /etc/modules and add a new line: i2c-dev
|
|
||||||
name = "PN532 board via I2C"
|
|
||||||
connstring = pn532_i2c:/dev/i2c-0
|
|
||||||
|
|
||||||
# Note: If you have an R-Pi revision 2.0, the I2C bus #1 is now routed to connector P1
|
|
||||||
# (instead of the I2C bus #0 routed on same connector on initial board revision), so
|
|
||||||
# the configuration to use would probably be:
|
|
||||||
|
|
||||||
# connstring = pn532_i2c:/dev/i2c-1
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
## Typical configuration file for PN532 device on R-Pi connected using SPI
|
|
||||||
## Note: to use SPI port on R-Pi, you have to load kernel module spi-bcm2708:
|
|
||||||
## Edit /etc/modprobe.d/raspi-blacklist.conf and comment: #blacklist spi-bcm2708
|
|
||||||
name = "PN532 board via SPI"
|
|
||||||
connstring = pn532_spi:/dev/spidev0.0:500000
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
## Typical configuration file for PN532 device on R-Pi connected using UART
|
|
||||||
## Note: to use UART port on R-Pi, you have to disable linux serial console:
|
|
||||||
## http://learn.adafruit.com/adafruit-nfc-rfid-on-raspberry-pi/freeing-uart-on-the-pi
|
|
||||||
name = "PN532 board via UART"
|
|
||||||
connstring = pn532_uart:/dev/ttyAMA0
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
## Typical configuration file for PN532 device on R-Pi 3 connected using miniUART
|
|
||||||
## Note: Changes have been made to R-Pi 3 with the addition of Bluetooth LE
|
|
||||||
## The UART is now being used by the BLE module. Instead of disabling it, you can
|
|
||||||
## use the PN532 device with the "mini UART", which is still hijacked by the linux kernel
|
|
||||||
## as a serial console
|
|
||||||
##
|
|
||||||
## Tested recipe with PN532 breakout from Adafruit
|
|
||||||
##
|
|
||||||
## To enable uart on GPIO, add this line to bottom of /boot/config.txt
|
|
||||||
## enable_uart=1
|
|
||||||
##
|
|
||||||
## Stop and disable serial console:
|
|
||||||
## $ sudo systemctl stop serial-getty@ttyS0.service
|
|
||||||
## $ sudo systemctl disable serial-getty@ttyS0.service
|
|
||||||
##
|
|
||||||
## Remove console from /boot/cmdline.txt by removing:
|
|
||||||
## console=serial0,115200 Save and reboot for changes to take effect.
|
|
||||||
##
|
|
||||||
name = "PN532 board via UART"
|
|
||||||
connstring = pn532_uart:/dev/ttyS0
|
|
||||||
allow_intrusive_scan = true
|
|
||||||
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
## Typical configuration file for PN532 board (ie. microbuilder.eu / Adafruit) device
|
|
||||||
name = "Adafruit PN532 board via UART"
|
|
||||||
connstring = pn532_uart:/dev/ttyUSB0
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
EXTRA_DIST = \
|
|
||||||
blacklist-libnfc.conf
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
blacklist nfc
|
|
||||||
blacklist pn533
|
|
||||||
blacklist pn533_usb
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
EXTRA_DIST = \
|
|
||||||
93-pn53x.rules
|
|
||||||
@ -1,8 +1,4 @@
|
|||||||
SUBDIRS = libnfc sys .
|
SUBDIRS = sys .
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
err.h \
|
err.h
|
||||||
nfc.def \
|
|
||||||
stdlib.c \
|
|
||||||
unistd.h \
|
|
||||||
version.rc.in
|
|
||||||
|
|||||||
@ -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*/
|
|
||||||
|
|
||||||
@ -4,15 +4,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define warnx(...) do { \
|
#define warnx(...) do { \
|
||||||
fprintf (stderr, __VA_ARGS__); \
|
fprintf (stderr, __VA_ARGS__); \
|
||||||
fprintf (stderr, "\n"); \
|
fprintf (stderr, "\n"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define errx(code, ...) do { \
|
#define errx(code, ...) do { \
|
||||||
fprintf (stderr, __VA_ARGS__); \
|
fprintf (stderr, __VA_ARGS__); \
|
||||||
fprintf (stderr, "\n"); \
|
fprintf (stderr, "\n"); \
|
||||||
exit (code); \
|
exit (code); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define err errx
|
#define err errx
|
||||||
|
|
||||||
|
|||||||
@ -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 */
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
SUBDIRS = buses .
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
|
||||||
log-internal.c
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
EXTRA_DIST = \
|
|
||||||
uart.c
|
|
||||||
@ -1,284 +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:
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file uart.c
|
|
||||||
* @brief Windows UART driver
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
|
||||||
#include "nfc-internal.h"
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
#define LOG_GROUP NFC_LOG_GROUP_COM
|
|
||||||
#define LOG_CATEGORY "libnfc.bus.uart_win32"
|
|
||||||
|
|
||||||
// Handle platform specific includes
|
|
||||||
#include "contrib/windows.h"
|
|
||||||
#define delay_ms( X ) Sleep( X )
|
|
||||||
|
|
||||||
struct serial_port_windows {
|
|
||||||
HANDLE hPort; // Serial port handle
|
|
||||||
DCB dcb; // Device control settings
|
|
||||||
COMMTIMEOUTS ct; // Serial port time-out configuration
|
|
||||||
};
|
|
||||||
|
|
||||||
serial_port
|
|
||||||
uart_open(const char *pcPortName)
|
|
||||||
{
|
|
||||||
char acPortName[255];
|
|
||||||
struct serial_port_windows *sp = malloc(sizeof(struct serial_port_windows));
|
|
||||||
|
|
||||||
if (sp == 0)
|
|
||||||
return INVALID_SERIAL_PORT;
|
|
||||||
|
|
||||||
// Copy the input "com?" to "\\.\COM?" format
|
|
||||||
sprintf(acPortName, "\\\\.\\%s", pcPortName);
|
|
||||||
_strupr(acPortName);
|
|
||||||
|
|
||||||
// Try to open the serial port
|
|
||||||
sp->hPort = CreateFileA(acPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
||||||
if (sp->hPort == INVALID_HANDLE_VALUE) {
|
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
|
||||||
}
|
|
||||||
// Prepare the device control
|
|
||||||
memset(&sp->dcb, 0, sizeof(DCB));
|
|
||||||
sp->dcb.DCBlength = sizeof(DCB);
|
|
||||||
if (!BuildCommDCBA("baud=9600 data=8 parity=N stop=1", &sp->dcb)) {
|
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
|
||||||
}
|
|
||||||
// Update the active serial port
|
|
||||||
if (!SetCommState(sp->hPort, &sp->dcb)) {
|
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp->ct.ReadIntervalTimeout = 30;
|
|
||||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
|
||||||
sp->ct.ReadTotalTimeoutConstant = 30;
|
|
||||||
sp->ct.WriteTotalTimeoutMultiplier = 30;
|
|
||||||
sp->ct.WriteTotalTimeoutConstant = 0;
|
|
||||||
|
|
||||||
if (!SetCommTimeouts(sp->hPort, &sp->ct)) {
|
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
|
||||||
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uart_close(const serial_port sp)
|
|
||||||
{
|
|
||||||
if (((struct serial_port_windows *) sp)->hPort != INVALID_HANDLE_VALUE) {
|
|
||||||
CloseHandle(((struct serial_port_windows *) sp)->hPort);
|
|
||||||
}
|
|
||||||
free(sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uart_flush_input(const serial_port sp, bool wait)
|
|
||||||
{
|
|
||||||
PurgeComm(((struct serial_port_windows *) sp)->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
|
|
||||||
{
|
|
||||||
struct serial_port_windows *spw;
|
|
||||||
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed);
|
|
||||||
// Set port speed (Input and Output)
|
|
||||||
switch (uiPortSpeed) {
|
|
||||||
case 9600:
|
|
||||||
case 19200:
|
|
||||||
case 38400:
|
|
||||||
case 57600:
|
|
||||||
case 115200:
|
|
||||||
case 230400:
|
|
||||||
case 460800:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d baud. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
spw = (struct serial_port_windows *) sp;
|
|
||||||
|
|
||||||
// Set baud rate
|
|
||||||
spw->dcb.BaudRate = uiPortSpeed;
|
|
||||||
if (!SetCommState(spw->hPort, &spw->dcb)) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to apply new speed settings.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PurgeComm(spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t
|
|
||||||
uart_get_speed(const serial_port sp)
|
|
||||||
{
|
|
||||||
const struct serial_port_windows *spw = (struct serial_port_windows *) sp;
|
|
||||||
if (!GetCommState(spw->hPort, (serial_port) & spw->dcb))
|
|
||||||
return spw->dcb.BaudRate;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout)
|
|
||||||
{
|
|
||||||
DWORD dwBytesToGet = (DWORD)szRx;
|
|
||||||
DWORD dwBytesReceived = 0;
|
|
||||||
DWORD dwTotalBytesReceived = 0;
|
|
||||||
BOOL res;
|
|
||||||
|
|
||||||
// XXX Put this part into uart_win32_timeouts () ?
|
|
||||||
DWORD timeout_ms = timeout;
|
|
||||||
COMMTIMEOUTS timeouts;
|
|
||||||
timeouts.ReadIntervalTimeout = 0;
|
|
||||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
|
||||||
timeouts.ReadTotalTimeoutConstant = timeout_ms;
|
|
||||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
|
||||||
timeouts.WriteTotalTimeoutConstant = timeout_ms;
|
|
||||||
|
|
||||||
if (!SetCommTimeouts(((struct serial_port_windows *) sp)->hPort, &timeouts)) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to apply new timeout settings.");
|
|
||||||
return NFC_EIO;
|
|
||||||
}
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Timeouts are set to %lu ms", timeout_ms);
|
|
||||||
|
|
||||||
// TODO Enhance the reception method
|
|
||||||
// - According to MSDN, it could be better to implement nfc_abort_command() mechanism using Cancello()
|
|
||||||
volatile bool *abort_flag_p = (volatile bool *)abort_p;
|
|
||||||
do {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ReadFile");
|
|
||||||
res = ReadFile(((struct serial_port_windows *) sp)->hPort, pbtRx + dwTotalBytesReceived,
|
|
||||||
dwBytesToGet,
|
|
||||||
&dwBytesReceived, NULL);
|
|
||||||
|
|
||||||
dwTotalBytesReceived += dwBytesReceived;
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
DWORD err = GetLastError();
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "ReadFile error: %lu", err);
|
|
||||||
return NFC_EIO;
|
|
||||||
} else if (dwBytesReceived == 0) {
|
|
||||||
return NFC_ETIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((DWORD)szRx) > dwTotalBytesReceived) {
|
|
||||||
dwBytesToGet -= dwBytesReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abort_flag_p != NULL && (*abort_flag_p) && dwTotalBytesReceived == 0) {
|
|
||||||
return NFC_EOPABORTED;
|
|
||||||
}
|
|
||||||
} while (((DWORD)szRx) > dwTotalBytesReceived);
|
|
||||||
LOG_HEX(LOG_GROUP, "RX", pbtRx, szRx);
|
|
||||||
|
|
||||||
return (dwTotalBytesReceived == (DWORD) szRx) ? 0 : NFC_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
|
|
||||||
{
|
|
||||||
DWORD dwTxLen = 0;
|
|
||||||
|
|
||||||
COMMTIMEOUTS timeouts;
|
|
||||||
timeouts.ReadIntervalTimeout = 0;
|
|
||||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
|
||||||
timeouts.ReadTotalTimeoutConstant = timeout;
|
|
||||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
|
||||||
timeouts.WriteTotalTimeoutConstant = timeout;
|
|
||||||
|
|
||||||
if (!SetCommTimeouts(((struct serial_port_windows *) sp)->hPort, &timeouts)) {
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to apply new timeout settings.");
|
|
||||||
return NFC_EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_HEX(LOG_GROUP, "TX", pbtTx, szTx);
|
|
||||||
if (!WriteFile(((struct serial_port_windows *) sp)->hPort, pbtTx, szTx, &dwTxLen, NULL)) {
|
|
||||||
return NFC_EIO;
|
|
||||||
}
|
|
||||||
if (!dwTxLen)
|
|
||||||
return NFC_EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL is_port_available(int nPort)
|
|
||||||
{
|
|
||||||
TCHAR szPort[15];
|
|
||||||
COMMCONFIG cc;
|
|
||||||
DWORD dwCCSize;
|
|
||||||
|
|
||||||
sprintf(szPort, "COM%d", nPort);
|
|
||||||
|
|
||||||
// Check if this port is available
|
|
||||||
dwCCSize = sizeof(cc);
|
|
||||||
return GetDefaultCommConfig(szPort, &cc, &dwCCSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path to the serial port is OS-dependant.
|
|
||||||
// Try to guess what we should use.
|
|
||||||
#define MAX_SERIAL_PORT_WIN 255
|
|
||||||
char **
|
|
||||||
uart_list_ports(void)
|
|
||||||
{
|
|
||||||
char **availablePorts = malloc((1 + MAX_SERIAL_PORT_WIN) * sizeof(char *));
|
|
||||||
if (!availablePorts) {
|
|
||||||
perror("malloc");
|
|
||||||
return availablePorts;
|
|
||||||
}
|
|
||||||
int curIndex = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 1; i <= MAX_SERIAL_PORT_WIN; i++) {
|
|
||||||
if (is_port_available(i)) {
|
|
||||||
availablePorts[curIndex] = (char *)malloc(10);
|
|
||||||
if (!availablePorts[curIndex]) {
|
|
||||||
perror("malloc");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sprintf(availablePorts[curIndex], "COM%d", i);
|
|
||||||
// printf("found candidate port: %s\n", availablePorts[curIndex]);
|
|
||||||
curIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
availablePorts[curIndex] = NULL;
|
|
||||||
|
|
||||||
return availablePorts;
|
|
||||||
}
|
|
||||||
@ -1,61 +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:
|
|
||||||
* Copyright (C) 2013 Alex Lian
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "log-internal.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <strsafe.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
log_output_debug(const char *format, va_list args)
|
|
||||||
{
|
|
||||||
char buffer[1024];
|
|
||||||
HRESULT hr = StringCbVPrintf(buffer, sizeof(buffer), format, args);
|
|
||||||
// Spew what we got, even if the buffer is not sized large enough
|
|
||||||
if ((STRSAFE_E_INSUFFICIENT_BUFFER == hr) || (S_OK == hr))
|
|
||||||
OutputDebugString(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
log_vput_internal(const char *format, va_list args)
|
|
||||||
{
|
|
||||||
vfprintf(stderr, format, args);
|
|
||||||
// Additional windows output to the debug window for debugging purposes
|
|
||||||
log_output_debug(format, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
log_put_internal(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list va;
|
|
||||||
va_start(va, format);
|
|
||||||
vfprintf(stderr, format, va);
|
|
||||||
// Additional windows output to the debug window for debugging purposes
|
|
||||||
log_output_debug(format, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
LIBRARY libnfc
|
|
||||||
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
|
|
||||||
@ -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
|
|
||||||
@ -1,57 +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:
|
|
||||||
* Copyright (C) 2013 Alex Lian
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file stdlib.c
|
|
||||||
* @brief Windows System compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Handle platform specific includes
|
|
||||||
#include "contrib/windows.h"
|
|
||||||
|
|
||||||
//There is no setenv()and unsetenv() in windows,but we can use putenv() instead.
|
|
||||||
int setenv(const char *name, const char *value, int overwrite)
|
|
||||||
{
|
|
||||||
char *env = getenv(name);
|
|
||||||
if ((env && overwrite) || (!env)) {
|
|
||||||
char *str[32];
|
|
||||||
strcpy(str, name);
|
|
||||||
strcat(str, "=");
|
|
||||||
strcat(str, value);
|
|
||||||
return putenv(str);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unsetenv(const char *name)
|
|
||||||
{
|
|
||||||
char *str[32];
|
|
||||||
strcpy(str, name);
|
|
||||||
strcat(str, "=");
|
|
||||||
putenv(str);
|
|
||||||
}
|
|
||||||
@ -1,12 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2011, Romuald Conty
|
||||||
* 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
|
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@ -1,48 +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:
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file unistd.h
|
|
||||||
* @brief This file intended to serve as a drop-in replacement for unistd.h on Windows
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _UNISTD_H_
|
|
||||||
#define _UNISTD_H_
|
|
||||||
|
|
||||||
#include "contrib/windows.h"
|
|
||||||
|
|
||||||
// Needed by Sleep() under Windows
|
|
||||||
# include <winbase.h>
|
|
||||||
# define sleep(X) Sleep( X * 1000)
|
|
||||||
|
|
||||||
// With MinGW, getopt(3) is provided as separate header
|
|
||||||
#if defined(WIN32) && defined(__GNUC__) /* mingw compiler */
|
|
||||||
#include <getopt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _UNISTD_H_ */
|
|
||||||
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
1 VERSIONINFO
|
|
||||||
FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
|
||||||
PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
|
||||||
FILEFLAGSMASK 0x3fL
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
FILEOS 0x00040004L
|
|
||||||
FILETYPE @RC_FILE_TYPE@
|
|
||||||
FILESUBTYPE 0x0L
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904e4"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Comments", "@RC_COMMENT@\0"
|
|
||||||
VALUE "CompanyName", "libnfc.org\0"
|
|
||||||
VALUE "FileDescription", "\0"
|
|
||||||
VALUE "FileVersion", "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@.0\0"
|
|
||||||
VALUE "InternalName", "@RC_INTERNAL_NAME@ @WIN32_MODE@\0"
|
|
||||||
VALUE "LegalCopyright", "Copyright (C) @CURRENT_YEAR@\0"
|
|
||||||
VALUE "OriginalFilename", "@RC_ORIGINAL_NAME@\0"
|
|
||||||
VALUE "ProductName", "@PACKAGE_NAME@ @WIN32_MODE@\0"
|
|
||||||
VALUE "ProductVersion", "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@.0\0"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x0409, 1252
|
|
||||||
END
|
|
||||||
END
|
|
||||||
@ -1,15 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2011, Glenn Ergeerts
|
||||||
* 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:
|
|
||||||
* Copyright (C) 2011 Glenn Ergeerts
|
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@ -37,28 +30,15 @@
|
|||||||
# include <winerror.h>
|
# include <winerror.h>
|
||||||
# include "win32/err.h"
|
# include "win32/err.h"
|
||||||
# if defined (__MINGW32__)
|
# if defined (__MINGW32__)
|
||||||
/*
|
# define snprintf(S, n, F, ...) sprintf(S, F, __VA_ARGS__)
|
||||||
* Cheating here on the snprintf to incorporate the format argument
|
# define MAX(a,b) max(a,b)
|
||||||
* into the VA_ARGS. Else we get MinGW errors regarding number of arguments
|
# define MIN(a,b) min(a,b)
|
||||||
* if doing a fixed string with no arguments.
|
|
||||||
*/
|
|
||||||
# define snprintf(S, n, ...) sprintf(S, __VA_ARGS__)
|
|
||||||
# define pipe(fds) _pipe(fds, 5000, _O_BINARY)
|
# define pipe(fds) _pipe(fds, 5000, _O_BINARY)
|
||||||
# define ETIMEDOUT WSAETIMEDOUT
|
# define ETIMEDOUT WSAETIMEDOUT
|
||||||
# define ENOTSUP WSAEOPNOTSUPP
|
# define ENOTSUP 134
|
||||||
# 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
|
||||||
|
|
||||||
/*
|
|
||||||
* setenv and unsetenv are not Windows compliant nor implemented in MinGW.
|
|
||||||
* These declarations get rid of the "implicit declaration warning."
|
|
||||||
*/
|
|
||||||
int setenv(const char *name, const char *value, int overwrite);
|
|
||||||
void unsetenv(const char *name);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
103
debian/changelog
vendored
Normal file
103
debian/changelog
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
libnfc (1.5.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* Experimental not-released trunk version.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Mon, 4 Apr 2011 11:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.4.2-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Tue, 21 Feb 2011 11:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.4.1-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Tue, 1 Feb 2011 10:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.4.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Tue, 26 Oct 2010 16:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.3.9-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Tue, 31 Aug 2010 14:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.3.4-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Wed, 31 Mar 2010 12:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.3.3-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Thu, 17 Feb 2010 15:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.3.2-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Fri, 29 Jan 2010 15:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.3.1-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Mon, 25 Jan 2010 11:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.3.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Thu, 14 Jan 2010 16:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.2.1-4) unstable; urgency=low
|
||||||
|
|
||||||
|
* Add udev rules for USB PN53x.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Fri, 20 Nov 2009 16:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.2.1-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* Don't use CDBS anymore, should now cross compile.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Thu, 29 Sep 2009 9:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.2.1-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Add missing dependencies for ACR122 devices (pcscd).
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Fri, 23 Sep 2009 16:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.2.1-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Description have been updated.
|
||||||
|
* Provided binairies should not be consider as tools but as examples.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Fri, 03 Sep 2009 18:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.2.1-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream version.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Fri, 24 Jul 2009 16:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.2.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream version.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Thu, 23 Jul 2009 15:42:42 +0100
|
||||||
|
|
||||||
|
libnfc (1.1.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* Initial debian package.
|
||||||
|
|
||||||
|
-- Romuald Conty <rconty@il4p.fr> Wed, 22 Apr 2009 10:42:42 +0100
|
||||||
|
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
7
|
||||||
41
debian/control
vendored
Normal file
41
debian/control
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Source: libnfc
|
||||||
|
Section: devel
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Romuald Conty <rconty@il4p.fr>
|
||||||
|
Build-Depends: debhelper (>= 5.0.37.2), automake, libtool, pkg-config, libusb-dev, libpcsclite-dev
|
||||||
|
Standards-Version: 3.7.3
|
||||||
|
Homepage: http://www.libnfc.org/
|
||||||
|
|
||||||
|
Package: libnfc0
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, libusb-0.1-4, libpcsclite1 (>= 1.5), libccid (>= 1.3.10), pcscd (>= 1.5)
|
||||||
|
Description: Near Field Communication (NFC) library
|
||||||
|
libnfc is a Free Software library for Near Field Communication. Supported NFC hardware
|
||||||
|
devices are, theorically, all hardware based on the NXP PN531, PN532 or PN533 NFC
|
||||||
|
controller chip.
|
||||||
|
|
||||||
|
Package: libnfc-dev
|
||||||
|
Architecture: any
|
||||||
|
Depends: libnfc0, libusb-dev, libpcsclite-dev
|
||||||
|
Description: Near Field Communication library (development files)
|
||||||
|
libnfc is a Free Software library for Near Field Communication. Supported NFC hardware
|
||||||
|
devices are, theorically, all hardware based on the NXP PN531, PN532 or PN533 NFC
|
||||||
|
controller chip.
|
||||||
|
|
||||||
|
Package: libnfc-bin
|
||||||
|
Architecture: any
|
||||||
|
Depends: libnfc0
|
||||||
|
Description: Near Field Communication binaries
|
||||||
|
Some binaries are provided with libnfc useful for developement (nfc-list, nfc-mfclassic, nfc-mfultralight, etc.).
|
||||||
|
|
||||||
|
Package: libnfc-examples
|
||||||
|
Architecture: any
|
||||||
|
Depends: libnfc0
|
||||||
|
Description: Near Field Communication examples
|
||||||
|
Some examples are provided with libnfc for debugging and/or educational purpose (nfc-anticol, nfc-emulate, etc.).
|
||||||
|
|
||||||
|
Package: libnfc-pn53x-examples
|
||||||
|
Architecture: any
|
||||||
|
Depends: libnfc0
|
||||||
|
Description: Near Field Communication examples for PN53x chips only
|
||||||
|
Some PN53x-only examples are provided with libnfc for debugging and/or educational purpose (pn53x-sam, pn53x-tamashell, etc.).
|
||||||
27
debian/copyright
vendored
Normal file
27
debian/copyright
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
This package was debianized by Romuald Conty <romuald.conty@free.fr> on
|
||||||
|
Wed, 22 Apr 2009 10:42:42 +0100.
|
||||||
|
|
||||||
|
It was downloaded from: http://www.libnfc.org/
|
||||||
|
|
||||||
|
Copyright (C) 2009 by Roel Verdult <roel@libnfc.org>
|
||||||
|
|
||||||
|
License: GNU Lesser General Public License version 3
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 3
|
||||||
|
as published by the Free Software Foundation
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||||
|
License, version 3, can be found in `/usr/share/common-licenses/LGPL-3'.
|
||||||
|
|
||||||
|
The Debian packaging is (C) 2009, Romuald Conty <romuald.conty@free.fr> and
|
||||||
|
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
|
||||||
6
debian/libnfc-bin.install
vendored
Normal file
6
debian/libnfc-bin.install
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
debian/tmp/usr/bin/nfc-list
|
||||||
|
debian/tmp/usr/bin/nfc-mfclassic
|
||||||
|
debian/tmp/usr/bin/nfc-mfultralight
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-list.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-mfclassic.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-mfultralight.1
|
||||||
3
debian/libnfc-dev.install
vendored
Normal file
3
debian/libnfc-dev.install
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
debian/tmp/usr/include/nfc
|
||||||
|
debian/tmp/usr/lib/libnfc.{a,la,so}
|
||||||
|
debian/tmp/usr/lib/pkgconfig/libnfc.pc
|
||||||
18
debian/libnfc-examples.install
vendored
Normal file
18
debian/libnfc-examples.install
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
debian/tmp/usr/bin/nfc-anticol
|
||||||
|
debian/tmp/usr/bin/nfc-dep-initiator
|
||||||
|
debian/tmp/usr/bin/nfc-dep-target
|
||||||
|
debian/tmp/usr/bin/nfc-emulate-forum-tag4
|
||||||
|
debian/tmp/usr/bin/nfc-emulate-tag
|
||||||
|
debian/tmp/usr/bin/nfc-emulate-uid
|
||||||
|
debian/tmp/usr/bin/nfc-poll
|
||||||
|
debian/tmp/usr/bin/nfc-relay
|
||||||
|
debian/tmp/usr/bin/nfc-relay-picc
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-anticol.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-dep-initiator.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-dep-target.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-emulate-forum-tag4.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-emulate-tag.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-emulate-uid.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-poll.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-relay-picc.1
|
||||||
|
debian/tmp/usr/share/man/man1/nfc-relay.1
|
||||||
3
debian/libnfc-pn53x-examples.install
vendored
Normal file
3
debian/libnfc-pn53x-examples.install
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
debian/tmp/usr/bin/pn53x-*
|
||||||
|
debian/tmp/usr/share/man/man1/pn53x-*
|
||||||
|
examples/pn53x-tamashell-scripts/*.cmd usr/share/doc/libnfc-pn53x-examples/scripts
|
||||||
2
debian/libnfc0.install
vendored
Normal file
2
debian/libnfc0.install
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
debian/tmp/usr/lib/libnfc.so.*
|
||||||
|
pn53x.rules etc/udev/rules.d/
|
||||||
117
debian/rules
vendored
Executable file
117
debian/rules
vendored
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
# -*- makefile -*-
|
||||||
|
# Sample debian/rules that uses debhelper.
|
||||||
|
# This file was originally written by Joey Hess and Craig Small.
|
||||||
|
# As a special exception, when this file is copied by dh-make into a
|
||||||
|
# dh-make output file, you may use that output file without restriction.
|
||||||
|
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||||
|
|
||||||
|
# Uncomment this to turn on verbose mode.
|
||||||
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
|
|
||||||
|
# These are used for cross-compiling and for saving the configure script
|
||||||
|
# from having to guess our platform (since we know it already)
|
||||||
|
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||||
|
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||||
|
ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
|
||||||
|
CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
|
||||||
|
CROSS_CFLAGS=-I/usr/$(DEB_HOST_GNU_TYPE)/include -I/usr/$(DEB_HOST_GNU_TYPE)/usr/include
|
||||||
|
LDFLAGS=-L/usr/$(DEB_HOST_GNU_TYPE)/lib -L/usr/$(DEB_HOST_GNU_TYPE)/usr/lib
|
||||||
|
MAKE_LDFLAGS=-inst-prefix-dir /usr/$(DEB_HOST_GNU_TYPE) -Wl,-rpath-link /usr/$(DEB_HOST_GNU_TYPE)/lib -Wl,-rpath-link /usr/$(DEB_HOST_GNU_TYPE)/usr/lib
|
||||||
|
DH_STRIP=
|
||||||
|
DH_SHLIBDEPS=
|
||||||
|
else
|
||||||
|
CROSS= --build $(DEB_BUILD_GNU_TYPE)
|
||||||
|
DH_STRIP=dh_strip
|
||||||
|
DH_SHLIBDEPS=dh_shlibdeps
|
||||||
|
endif
|
||||||
|
|
||||||
|
# shared library versions, option 1
|
||||||
|
version=2.0.5
|
||||||
|
major=2
|
||||||
|
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
|
||||||
|
#version=`ls src/.libs/lib*.so.* | \
|
||||||
|
# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
|
||||||
|
#major=`ls src/.libs/lib*.so.* | \
|
||||||
|
# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
|
||||||
|
|
||||||
|
config.status: configure
|
||||||
|
dh_testdir
|
||||||
|
# Add here commands to configure the package.
|
||||||
|
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
|
||||||
|
cp -f /usr/share/misc/config.sub config.sub
|
||||||
|
endif
|
||||||
|
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
|
||||||
|
cp -f /usr/share/misc/config.guess config.guess
|
||||||
|
endif
|
||||||
|
./configure $(CROSS) --enable-serial-autoprobe --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS) $(CROSS_CFLAGS)" LDFLAGS="-Wl,-z,defs $(LDFLAGS)"
|
||||||
|
|
||||||
|
|
||||||
|
build: build-stamp
|
||||||
|
build-stamp: config.status
|
||||||
|
dh_testdir
|
||||||
|
|
||||||
|
# Add here commands to compile the package.
|
||||||
|
$(MAKE) LDFLAGS="$(MAKE_LDFLAGS) $(LDFLAGS)"
|
||||||
|
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
rm -f build-stamp
|
||||||
|
|
||||||
|
# Add here commands to clean up after the build process.
|
||||||
|
[ ! -f Makefile ] || $(MAKE) distclean
|
||||||
|
rm -f config.sub config.guess
|
||||||
|
|
||||||
|
dh_clean
|
||||||
|
|
||||||
|
install: build
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
dh_clean -k
|
||||||
|
dh_installdirs
|
||||||
|
|
||||||
|
# Add here commands to install the package into debian/tmp
|
||||||
|
$(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
|
||||||
|
|
||||||
|
|
||||||
|
# Build architecture-independent files here.
|
||||||
|
binary-indep: build install
|
||||||
|
# We have nothing to do by default.
|
||||||
|
|
||||||
|
# Build architecture-dependent files here.
|
||||||
|
binary-arch: build install
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
dh_installchangelogs ChangeLog
|
||||||
|
dh_installdocs
|
||||||
|
dh_installexamples
|
||||||
|
dh_install
|
||||||
|
# dh_installmenu
|
||||||
|
# dh_installdebconf
|
||||||
|
# dh_installlogrotate
|
||||||
|
# dh_installemacsen
|
||||||
|
# dh_installpam
|
||||||
|
# dh_installmime
|
||||||
|
# dh_installinit
|
||||||
|
# dh_installcron
|
||||||
|
# dh_installinfo
|
||||||
|
dh_installman
|
||||||
|
dh_link
|
||||||
|
$(DH_STRIP)
|
||||||
|
dh_compress
|
||||||
|
dh_fixperms
|
||||||
|
# dh_perl
|
||||||
|
# dh_python
|
||||||
|
dh_makeshlibs
|
||||||
|
dh_installdeb
|
||||||
|
$(DH_SHLIBDEPS)
|
||||||
|
dh_gencontrol
|
||||||
|
dh_md5sums
|
||||||
|
dh_builddeb
|
||||||
|
|
||||||
|
binary: binary-indep binary-arch
|
||||||
|
.PHONY: build clean binary-indep binary-arch binary install
|
||||||
@ -1,43 +1,23 @@
|
|||||||
SET(EXAMPLES-SOURCES
|
SET(EXAMPLES-SOURCES nfc-anticol nfc-dep-initiator nfc-dep-target nfc-emulate-forum-tag4 nfc-emulate-tag nfc-emulate-uid nfc-list nfc-poll nfc-relay nfc-relay-picc nfc-mfclassic nfc-mfultralight)
|
||||||
nfc-anticol
|
#TODO pn53x-diagnose pn53x-sam pn53x-tamashell
|
||||||
nfc-dep-initiator
|
|
||||||
nfc-dep-target
|
|
||||||
nfc-emulate-forum-tag2
|
|
||||||
nfc-emulate-tag
|
|
||||||
nfc-emulate-uid
|
|
||||||
nfc-mfsetuid
|
|
||||||
nfc-poll
|
|
||||||
nfc-relay
|
|
||||||
nfc-st25tb
|
|
||||||
pn53x-diagnose
|
|
||||||
pn53x-sam
|
|
||||||
pn53x-tamashell
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# XXX: Examples should not use private API!
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS} ${PCSC_INCLUDE_DIRS})
|
||||||
|
LINK_DIRECTORIES(${LIBUSB_LIBRARY_DIRS} ${PCSC_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
ADD_LIBRARY(nfc-utils nfc-utils)
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
FOREACH(source ${EXAMPLES-SOURCES})
|
FOREACH(source ${EXAMPLES-SOURCES})
|
||||||
SET (TARGETS ${source}.c)
|
IF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic"))
|
||||||
|
ADD_EXECUTABLE(${source} ${source}.c mifare)
|
||||||
IF(WIN32)
|
ELSE()
|
||||||
SET(RC_COMMENT "${PACKAGE_NAME} example")
|
ADD_EXECUTABLE(${source} ${source}.c)
|
||||||
SET(RC_INTERNAL_NAME ${source})
|
ENDIF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic"))
|
||||||
SET(RC_ORIGINAL_NAME ${source}.exe)
|
|
||||||
# RC_FILE_TYPE: VFT_APP
|
|
||||||
SET(RC_FILE_TYPE 0x00000001L)
|
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
|
|
||||||
LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
|
|
||||||
|
|
||||||
|
|
||||||
IF(${source} MATCHES "nfc-st25tb")
|
|
||||||
LIST(APPEND TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/getopt.c)
|
|
||||||
ENDIF()
|
|
||||||
ENDIF(WIN32)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(${source} ${TARGETS})
|
|
||||||
TARGET_LINK_LIBRARIES(${source} nfc)
|
TARGET_LINK_LIBRARIES(${source} nfc)
|
||||||
TARGET_LINK_LIBRARIES(${source} nfcutils)
|
TARGET_LINK_LIBRARIES(${source} nfc-utils)
|
||||||
INSTALL(TARGETS ${source} RUNTIME DESTINATION bin COMPONENT examples)
|
INSTALL(TARGETS ${source} RUNTIME DESTINATION bin COMPONENT examples)
|
||||||
ENDFOREACH(source)
|
ENDFOREACH(source)
|
||||||
|
|
||||||
|
|||||||
@ -4,13 +4,15 @@ bin_PROGRAMS = \
|
|||||||
nfc-anticol \
|
nfc-anticol \
|
||||||
nfc-dep-initiator \
|
nfc-dep-initiator \
|
||||||
nfc-dep-target \
|
nfc-dep-target \
|
||||||
nfc-emulate-forum-tag2 \
|
nfc-emulate-forum-tag4 \
|
||||||
nfc-emulate-tag \
|
nfc-emulate-tag \
|
||||||
nfc-emulate-uid \
|
nfc-emulate-uid \
|
||||||
nfc-mfsetuid \
|
nfc-list \
|
||||||
|
nfc-mfclassic \
|
||||||
|
nfc-mfultralight \
|
||||||
nfc-poll \
|
nfc-poll \
|
||||||
nfc-relay \
|
nfc-relay \
|
||||||
nfc-st25tb \
|
nfc-relay-picc \
|
||||||
pn53x-diagnose \
|
pn53x-diagnose \
|
||||||
pn53x-sam
|
pn53x-sam
|
||||||
|
|
||||||
@ -19,89 +21,91 @@ bin_PROGRAMS += \
|
|||||||
pn53x-tamashell
|
pn53x-tamashell
|
||||||
endif
|
endif
|
||||||
|
|
||||||
check_PROGRAMS = \
|
|
||||||
quick_start_example1 \
|
|
||||||
quick_start_example2
|
|
||||||
|
|
||||||
# set the include path found by configure
|
# set the include path found by configure
|
||||||
AM_CPPFLAGS = $(all_includes) $(LIBNFC_CFLAGS)
|
INCLUDES= $(all_includes) $(LIBNFC_CFLAGS)
|
||||||
|
|
||||||
AM_CFLAGS = -I$(top_srcdir)/libnfc -I$(top_srcdir)
|
AM_CFLAGS = -I$(top_srcdir)/libnfc
|
||||||
|
|
||||||
|
noinst_HEADERS = mifare.h nfc-utils.h
|
||||||
|
noinst_LTLIBRARIES = libnfcutils.la
|
||||||
|
|
||||||
|
libnfcutils_la_SOURCES = nfc-utils.c
|
||||||
|
|
||||||
nfc_poll_SOURCES = nfc-poll.c
|
nfc_poll_SOURCES = nfc-poll.c
|
||||||
nfc_poll_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_poll_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_anticol_SOURCES = nfc-anticol.c
|
nfc_anticol_SOURCES = nfc-anticol.c
|
||||||
nfc_anticol_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_anticol_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
|
nfc_list_SOURCES = nfc-list.c
|
||||||
|
nfc_list_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
|
libnfcutils.la
|
||||||
|
|
||||||
|
nfc_mfultralight_SOURCES = nfc-mfultralight.c mifare.c mifare.h
|
||||||
|
nfc_mfultralight_LDADD = $(top_builddir)/libnfc/libnfc.la
|
||||||
|
|
||||||
|
nfc_mfclassic_SOURCES = nfc-mfclassic.c mifare.c mifare.h
|
||||||
|
nfc_mfclassic_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_relay_SOURCES = nfc-relay.c
|
nfc_relay_SOURCES = nfc-relay.c
|
||||||
nfc_relay_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_relay_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_emulate_forum_tag2_SOURCES = nfc-emulate-forum-tag2.c
|
nfc_relay_picc_SOURCES = nfc-relay-picc.c
|
||||||
nfc_emulate_forum_tag2_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_relay_picc_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
|
nfc_emulate_forum_tag4_SOURCES = nfc-emulate-forum-tag4.c
|
||||||
|
nfc_emulate_forum_tag4_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_emulate_tag_SOURCES = nfc-emulate-tag.c
|
nfc_emulate_tag_SOURCES = nfc-emulate-tag.c
|
||||||
nfc_emulate_tag_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_emulate_tag_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_emulate_uid_SOURCES = nfc-emulate-uid.c
|
nfc_emulate_uid_SOURCES = nfc-emulate-uid.c
|
||||||
nfc_emulate_uid_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_emulate_uid_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_dep_target_SOURCES = nfc-dep-target.c
|
nfc_dep_target_SOURCES = nfc-dep-target.c
|
||||||
nfc_dep_target_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_dep_target_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_dep_initiator_SOURCES = nfc-dep-initiator.c
|
nfc_dep_initiator_SOURCES = nfc-dep-initiator.c
|
||||||
nfc_dep_initiator_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_dep_initiator_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
nfc_mfsetuid_SOURCES = nfc-mfsetuid.c
|
|
||||||
nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.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
|
libnfcutils.la
|
||||||
|
|
||||||
pn53x_sam_SOURCES = pn53x-sam.c
|
pn53x_sam_SOURCES = pn53x-sam.c
|
||||||
pn53x_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
pn53x_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
|
|
||||||
pn53x_tamashell_SOURCES = pn53x-tamashell.c
|
pn53x_tamashell_SOURCES = pn53x-tamashell.c
|
||||||
pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
libnfcutils.la
|
||||||
pn53x_tamashell_CFLAGS = @READLINE_INCLUDES@ -I$(top_srcdir)
|
|
||||||
pn53x_tamashell_LDFLAGS = @READLINE_LIBS@
|
pn53x_tamashell_LDFLAGS = @READLINE_LIBS@
|
||||||
|
|
||||||
quick_start_example1_SOURCES = doc/quick_start_example1.c
|
|
||||||
quick_start_example1_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
|
||||||
|
|
||||||
quick_start_example2_SOURCES = doc/quick_start_example2.c
|
|
||||||
quick_start_example2_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
|
||||||
|
|
||||||
|
|
||||||
dist_man_MANS = \
|
dist_man_MANS = \
|
||||||
nfc-anticol.1 \
|
nfc-anticol.1 \
|
||||||
nfc-dep-initiator.1 \
|
nfc-dep-initiator.1 \
|
||||||
nfc-dep-target.1 \
|
nfc-dep-target.1 \
|
||||||
|
nfc-emulate-forum-tag4.1 \
|
||||||
nfc-emulate-tag.1 \
|
nfc-emulate-tag.1 \
|
||||||
nfc-emulate-uid.1 \
|
nfc-emulate-uid.1 \
|
||||||
|
nfc-list.1 \
|
||||||
|
nfc-mfclassic.1 \
|
||||||
|
nfc-mfultralight.1 \
|
||||||
nfc-poll.1 \
|
nfc-poll.1 \
|
||||||
nfc-relay.1 \
|
nfc-relay.1 \
|
||||||
nfc-mfsetuid.1 \
|
nfc-relay-picc.1 \
|
||||||
pn53x-diagnose.1 \
|
pn53x-diagnose.1 \
|
||||||
pn53x-sam.1 \
|
pn53x-sam.1 \
|
||||||
pn53x-tamashell.1 \
|
pn53x-tamashell.1
|
||||||
nfc-emulate-forum-tag2.1
|
|
||||||
|
|
||||||
EXTRA_DIST = CMakeLists.txt
|
EXTRA_DIST = CMakeLists.txt
|
||||||
|
|||||||
@ -1,86 +1,56 @@
|
|||||||
/**
|
#ifdef HAVE_CONFIG_H
|
||||||
* @file quick_start_example1.c
|
# include "config.h"
|
||||||
* @brief Quick start example that presents how to use libnfc
|
#endif // HAVE_CONFIG_H
|
||||||
*/
|
|
||||||
|
|
||||||
// To compile this simple example:
|
|
||||||
// $ gcc -o quick_start_example1 quick_start_example1.c -lnfc
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
static void
|
#include "nfc-utils.h"
|
||||||
print_hex(const uint8_t *pbtData, const size_t szBytes)
|
|
||||||
{
|
|
||||||
size_t szPos;
|
|
||||||
|
|
||||||
for (szPos = 0; szPos < szBytes; szPos++) {
|
|
||||||
printf("%02x ", pbtData[szPos]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
nfc_device *pnd;
|
nfc_device_t *pnd;
|
||||||
nfc_target nt;
|
nfc_target_info_t nti;
|
||||||
|
|
||||||
// Allocate only a pointer to nfc_context
|
|
||||||
nfc_context *context;
|
|
||||||
|
|
||||||
// Initialize libnfc and set the nfc_context
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
printf("Unable to init libnfc (malloc)\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
const char *acLibnfcVersion = nfc_version();
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
(void)argc;
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
|
||||||
|
|
||||||
// Open, using the first available NFC device which can be in order of selection:
|
// Connect using the first available NFC device
|
||||||
// - default device specified using environment variable or
|
pnd = nfc_connect (NULL);
|
||||||
// - first specified device in libnfc.conf (/etc/nfc) or
|
|
||||||
// - first specified device in device-configuration directory (/etc/nfc/devices.d) or
|
|
||||||
// - first auto-detected (if feature is not disabled in libnfc.conf) device
|
|
||||||
pnd = nfc_open(context, NULL);
|
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
printf("ERROR: %s\n", "Unable to open NFC device.");
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
exit(EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
}
|
|
||||||
// Set opened NFC device to initiator mode
|
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
// Set connected NFC device to initiator mode
|
||||||
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
|
// Enable field so more power consuming cards can power themselves up
|
||||||
|
nfc_configure (pnd, NDO_ACTIVATE_FIELD, true);
|
||||||
|
|
||||||
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
// Poll for a ISO14443A (MIFARE) tag
|
// Poll for a ISO14443A (MIFARE) tag
|
||||||
const nfc_modulation nmMifare = {
|
const nfc_modulation_t nmMifare = {
|
||||||
.nmt = NMT_ISO14443A,
|
.nmt = NMT_ISO14443A,
|
||||||
.nbr = NBR_106,
|
.nbr = NBR_106,
|
||||||
};
|
};
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) > 0) {
|
if (nfc_initiator_select_passive_target (pnd, PM_ISO14443A_106, NULL, 0, &nti)) {
|
||||||
printf("The following (NFC) ISO14443A tag was found:\n");
|
printf ("The following (NFC) ISO14443A tag was found:\n");
|
||||||
printf(" ATQA (SENS_RES): ");
|
printf (" ATQA (SENS_RES): ");
|
||||||
print_hex(nt.nti.nai.abtAtqa, 2);
|
print_hex (nti.nai.abtAtqa, 2);
|
||||||
printf(" UID (NFCID%c): ", (nt.nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
|
printf (" UID (NFCID%c): ", (nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
|
||||||
print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
|
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
||||||
printf(" SAK (SEL_RES): ");
|
printf (" SAK (SEL_RES): ");
|
||||||
print_hex(&nt.nti.nai.btSak, 1);
|
print_hex (&nti.nai.btSak, 1);
|
||||||
if (nt.nti.nai.szAtsLen) {
|
if (nti.nai.szAtsLen) {
|
||||||
printf(" ATS (ATR): ");
|
printf (" ATS (ATR): ");
|
||||||
print_hex(nt.nti.nai.abtAts, nt.nti.nai.szAtsLen);
|
print_hex (nti.nai.abtAts, nti.nai.szAtsLen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Close NFC device
|
// Disconnect from NFC device
|
||||||
nfc_close(pnd);
|
nfc_disconnect (pnd);
|
||||||
// Release the context
|
return EXIT_SUCCESS;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file quick_start_example2.c
|
|
||||||
* @brief Quick start example that presents how to use libnfc
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This is same example as quick_start_example1.c but using
|
|
||||||
// some helper functions existing in libnfc.
|
|
||||||
// Those functions are not available yet in a library
|
|
||||||
// so binary object must be linked statically:
|
|
||||||
// $ gcc -o quick_start_example2 -lnfc -I../.. quick_start_example2.c ../../utils/nfc-utils.o
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <nfc/nfc.h>
|
|
||||||
#include "utils/nfc-utils.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
nfc_device *pnd;
|
|
||||||
nfc_target nt;
|
|
||||||
|
|
||||||
// Allocate only a pointer to nfc_context
|
|
||||||
nfc_context *context;
|
|
||||||
|
|
||||||
// Initialize libnfc and set the nfc_context
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display libnfc version
|
|
||||||
const char *acLibnfcVersion = nfc_version();
|
|
||||||
(void)argc;
|
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
|
||||||
|
|
||||||
// Open, using the first available NFC device which can be in order of selection:
|
|
||||||
// - default device specified using environment variable or
|
|
||||||
// - first specified device in libnfc.conf (/etc/nfc) or
|
|
||||||
// - first specified device in device-configuration directory (/etc/nfc/devices.d) or
|
|
||||||
// - first auto-detected (if feature is not disabled in libnfc.conf) device
|
|
||||||
pnd = nfc_open(context, NULL);
|
|
||||||
|
|
||||||
if (pnd == NULL) {
|
|
||||||
ERR("%s", "Unable to open NFC device.");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
// Set opened NFC device to initiator mode
|
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
|
|
||||||
|
|
||||||
// Poll for a ISO14443A (MIFARE) tag
|
|
||||||
const nfc_modulation nmMifare = {
|
|
||||||
.nmt = NMT_ISO14443A,
|
|
||||||
.nbr = NBR_106,
|
|
||||||
};
|
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) > 0) {
|
|
||||||
printf("The following (NFC) ISO14443A tag was found:\n");
|
|
||||||
printf(" ATQA (SENS_RES): ");
|
|
||||||
print_hex(nt.nti.nai.abtAtqa, 2);
|
|
||||||
printf(" UID (NFCID%c): ", (nt.nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
|
|
||||||
print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
|
|
||||||
printf(" SAK (SEL_RES): ");
|
|
||||||
print_hex(&nt.nti.nai.btSak, 1);
|
|
||||||
if (nt.nti.nai.szAtsLen) {
|
|
||||||
printf(" ATS (ATR): ");
|
|
||||||
print_hex(nt.nti.nai.abtAts, nt.nti.nai.szAtsLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Close NFC device
|
|
||||||
nfc_close(pnd);
|
|
||||||
// Release the context
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,14 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -33,10 +27,7 @@
|
|||||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
* @file mifare.c
|
|
||||||
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
|
||||||
*/
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -52,88 +43,84 @@
|
|||||||
* @note There are three different types of information (Authenticate, Data and Value).
|
* @note There are three different types of information (Authenticate, Data and Value).
|
||||||
*
|
*
|
||||||
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
|
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
|
||||||
* They are both used to initialize the internal cipher-state of the PN53X chip.
|
* They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip).
|
||||||
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
||||||
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
|
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
|
||||||
{
|
{
|
||||||
uint8_t abtRx[265];
|
byte_t abtRx[265];
|
||||||
|
size_t szRx = sizeof(abtRx);
|
||||||
size_t szParamLen;
|
size_t szParamLen;
|
||||||
uint8_t abtCmd[265];
|
byte_t abtCmd[265];
|
||||||
//bool bEasyFraming;
|
bool bEasyFraming;
|
||||||
|
|
||||||
abtCmd[0] = mc; // The MIFARE Classic command
|
abtCmd[0] = mc; // The MIFARE Classic command
|
||||||
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
||||||
|
|
||||||
switch (mc) {
|
switch (mc) {
|
||||||
// Read and store command have no parameter
|
// Read and store command have no parameter
|
||||||
case MC_READ:
|
case MC_READ:
|
||||||
case MC_STORE:
|
case MC_STORE:
|
||||||
szParamLen = 0;
|
szParamLen = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Authenticate command
|
// Authenticate command
|
||||||
case MC_AUTH_A:
|
case MC_AUTH_A:
|
||||||
case MC_AUTH_B:
|
case MC_AUTH_B:
|
||||||
szParamLen = sizeof(struct mifare_param_auth);
|
szParamLen = sizeof (mifare_param_auth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Data command
|
// Data command
|
||||||
case MC_WRITE:
|
case MC_WRITE:
|
||||||
szParamLen = sizeof(struct mifare_param_data);
|
szParamLen = sizeof (mifare_param_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Value command
|
// Value command
|
||||||
case MC_DECREMENT:
|
case MC_DECREMENT:
|
||||||
case MC_INCREMENT:
|
case MC_INCREMENT:
|
||||||
case MC_TRANSFER:
|
case MC_TRANSFER:
|
||||||
szParamLen = sizeof(struct mifare_param_value);
|
szParamLen = sizeof (mifare_param_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Please fix your code, you never should reach this statement
|
// Please fix your code, you never should reach this statement
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When available, copy the parameter bytes
|
// When available, copy the parameter bytes
|
||||||
if (szParamLen)
|
if (szParamLen)
|
||||||
memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen);
|
memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
|
||||||
|
|
||||||
// FIXME: Save and restore bEasyFraming
|
bEasyFraming = pnd->bEasyFraming;
|
||||||
// bEasyFraming = nfc_device_get_property_bool (pnd, NP_EASY_FRAMING, &bEasyFraming);
|
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
|
||||||
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
|
nfc_perror (pnd, "nfc_configure");
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Fire the mifare command
|
// Fire the mifare command
|
||||||
int res;
|
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx)) {
|
||||||
if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
|
if (pnd->iLastError == EINVRXFRAM) {
|
||||||
if (res == NFC_ERFTRANS) {
|
// "Invalid received frame" AKA EINVRXFRAM, usual means we are
|
||||||
// "Invalid received frame", usual means we are
|
|
||||||
// authenticated on a sector but the requested MIFARE cmd (read, write)
|
// authenticated on a sector but the requested MIFARE cmd (read, write)
|
||||||
// is not permitted by current acces bytes;
|
// is not permitted by current acces bytes;
|
||||||
// So there is nothing to do here.
|
// So there is nothing to do here.
|
||||||
} else {
|
} else {
|
||||||
nfc_perror(pnd, "nfc_initiator_transceive_bytes");
|
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
|
||||||
}
|
}
|
||||||
// XXX nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming);
|
nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* XXX
|
if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
|
||||||
if (nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming) < 0) {
|
nfc_perror (pnd, "nfc_configure");
|
||||||
nfc_perror (pnd, "nfc_device_set_property_bool");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// When we have executed a read command, copy the received bytes into the param
|
// When we have executed a read command, copy the received bytes into the param
|
||||||
if (mc == MC_READ) {
|
if (mc == MC_READ) {
|
||||||
|
if (szRx == 16) {
|
||||||
//Check the length of response data, with PCSC reader, there have 2 bytes for SW value
|
memcpy (pmp->mpd.abtData, abtRx, 16);
|
||||||
if (res == 16 || res == (16 + 2)) {
|
|
||||||
memcpy(pmp->mpd.abtData, abtRx, 16);
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
139
examples/mifare.h
Normal file
139
examples/mifare.h
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
|
*
|
||||||
|
* 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 mifaretag.h
|
||||||
|
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBNFC_MIFARE_H_
|
||||||
|
# define _LIBNFC_MIFARE_H_
|
||||||
|
|
||||||
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
|
# pragma pack(1)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MC_AUTH_A = 0x60,
|
||||||
|
MC_AUTH_B = 0x61,
|
||||||
|
MC_READ = 0x30,
|
||||||
|
MC_WRITE = 0xA0,
|
||||||
|
MC_TRANSFER = 0xB0,
|
||||||
|
MC_DECREMENT = 0xC0,
|
||||||
|
MC_INCREMENT = 0xC1,
|
||||||
|
MC_STORE = 0xC2
|
||||||
|
} mifare_cmd;
|
||||||
|
|
||||||
|
// MIFARE command params
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtKey[6];
|
||||||
|
byte_t abtUid[4];
|
||||||
|
} mifare_param_auth;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtData[16];
|
||||||
|
} mifare_param_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtValue[4];
|
||||||
|
} mifare_param_value;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
mifare_param_auth mpa;
|
||||||
|
mifare_param_data mpd;
|
||||||
|
mifare_param_value mpv;
|
||||||
|
} mifare_param;
|
||||||
|
|
||||||
|
// Reset struct alignment to default
|
||||||
|
# pragma pack()
|
||||||
|
|
||||||
|
bool nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp);
|
||||||
|
|
||||||
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
|
# pragma pack(1)
|
||||||
|
|
||||||
|
// MIFARE Classic
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtUID[4];
|
||||||
|
byte_t btBCC;
|
||||||
|
byte_t btUnknown;
|
||||||
|
byte_t abtATQA[2];
|
||||||
|
byte_t abtUnknown[8];
|
||||||
|
} mifare_classic_block_manufacturer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtData[16];
|
||||||
|
} mifare_classic_block_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtKeyA[6];
|
||||||
|
byte_t abtAccessBits[4];
|
||||||
|
byte_t abtKeyB[6];
|
||||||
|
} mifare_classic_block_trailer;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
mifare_classic_block_manufacturer mbm;
|
||||||
|
mifare_classic_block_data mbd;
|
||||||
|
mifare_classic_block_trailer mbt;
|
||||||
|
} mifare_classic_block;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mifare_classic_block amb[256];
|
||||||
|
} mifare_classic_tag;
|
||||||
|
|
||||||
|
// MIFARE Ultralight
|
||||||
|
typedef struct {
|
||||||
|
byte_t sn0[3];
|
||||||
|
byte_t btBCC0;
|
||||||
|
byte_t sn1[4];
|
||||||
|
byte_t btBCC1;
|
||||||
|
byte_t internal;
|
||||||
|
byte_t lock[2];
|
||||||
|
byte_t otp[4];
|
||||||
|
} mifareul_block_manufacturer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtData[16];
|
||||||
|
} mifareul_block_data;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
mifareul_block_manufacturer mbm;
|
||||||
|
mifareul_block_data mbd;
|
||||||
|
} mifareul_block;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mifareul_block amb[4];
|
||||||
|
} mifareul_tag;
|
||||||
|
|
||||||
|
// Reset struct alignment to default
|
||||||
|
# pragma pack()
|
||||||
|
|
||||||
|
#endif // _LIBNFC_MIFARE_H_
|
||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-anticol 1 "June 26, 2009" "libnfc" "libnfc's examples"
|
.TH NFC-ANTICOL 1 "June 26, 2009"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-anticol \- Demonstration of NFC anti-collision command line tool based on libnfc
|
nfc-anticol \- Demonstration of NFC anti-collision command line tool based on libnfc
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -21,17 +21,13 @@ are neither 0 nor 1.
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Roel Verdult <roel@libnfc.org>
|
Roel Verdult <roel@libnfc.org>
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@ -1,14 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -52,60 +45,47 @@
|
|||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define SAK_FLAG_ATS_SUPPORTED 0x20
|
#define SAK_FLAG_ATS_SUPPORTED 0x20
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
static uint8_t abtRx[MAX_FRAME_LEN];
|
static byte_t abtRx[MAX_FRAME_LEN];
|
||||||
static int szRxBits;
|
static size_t szRxBits;
|
||||||
static size_t szRx = sizeof(abtRx);
|
static size_t szRx = sizeof(abtRx);
|
||||||
static uint8_t abtRawUid[12];
|
static byte_t abtRawUid[12];
|
||||||
static uint8_t abtAtqa[2];
|
static byte_t abtAtqa[2];
|
||||||
static uint8_t abtSak;
|
static byte_t abtSak;
|
||||||
static uint8_t abtAts[MAX_FRAME_LEN];
|
|
||||||
static uint8_t szAts = 0;
|
|
||||||
static size_t szCL = 1;//Always start with Cascade Level 1 (CL1)
|
static size_t szCL = 1;//Always start with Cascade Level 1 (CL1)
|
||||||
static nfc_device *pnd;
|
static nfc_device_t *pnd;
|
||||||
|
|
||||||
bool quiet_output = false;
|
bool quiet_output = false;
|
||||||
bool force_rats = false;
|
|
||||||
bool timed = false;
|
|
||||||
bool iso_ats_supported = false;
|
|
||||||
|
|
||||||
// ISO14443A Anti-Collision Commands
|
// ISO14443A Anti-Collision Commands
|
||||||
uint8_t abtReqa[1] = { 0x26 };
|
byte_t abtReqa[1] = { 0x26 };
|
||||||
uint8_t abtSelectAll[2] = { 0x93, 0x20 };
|
byte_t abtSelectAll[2] = { 0x93, 0x20 };
|
||||||
uint8_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
byte_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
uint8_t abtRats[4] = { 0xe0, 0x50, 0x00, 0x00 };
|
byte_t abtRats[4] = { 0xe0, 0x50, 0x00, 0x00 };
|
||||||
uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
|
byte_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
|
||||||
#define CASCADE_BIT 0x04
|
#define CASCADE_BIT 0x04
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
|
transmit_bits (const byte_t * pbtTx, const size_t szTxBits)
|
||||||
{
|
{
|
||||||
uint32_t cycles = 0;
|
|
||||||
// Show transmitted command
|
// Show transmitted command
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("Sent bits: ");
|
printf ("Sent bits: ");
|
||||||
print_hex_bits(pbtTx, szTxBits);
|
print_hex_bits (pbtTx, szTxBits);
|
||||||
}
|
}
|
||||||
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
||||||
if (timed) {
|
if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL))
|
||||||
if ((szRxBits = nfc_initiator_transceive_bits_timed(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL, &cycles)) < 0)
|
return false;
|
||||||
return false;
|
|
||||||
if ((!quiet_output) && (szRxBits > 0)) {
|
|
||||||
printf("Response after %u cycles\n", cycles);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Show received answer
|
// Show received answer
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("Received bits: ");
|
printf ("Received bits: ");
|
||||||
print_hex_bits(abtRx, szRxBits);
|
print_hex_bits (abtRx, szRxBits);
|
||||||
}
|
}
|
||||||
// Succesful transfer
|
// Succesful transfer
|
||||||
return true;
|
return true;
|
||||||
@ -113,129 +93,115 @@ transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
|
|||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
|
transmit_bytes (const byte_t * pbtTx, const size_t szTx)
|
||||||
{
|
{
|
||||||
uint32_t cycles = 0;
|
|
||||||
// Show transmitted command
|
// Show transmitted command
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("Sent bits: ");
|
printf ("Sent bits: ");
|
||||||
print_hex(pbtTx, szTx);
|
print_hex (pbtTx, szTx);
|
||||||
}
|
}
|
||||||
int res;
|
|
||||||
// Transmit the command bytes
|
// Transmit the command bytes
|
||||||
if (timed) {
|
if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTx, abtRx, &szRx))
|
||||||
if ((res = nfc_initiator_transceive_bytes_timed(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), &cycles)) < 0)
|
return false;
|
||||||
return false;
|
|
||||||
if ((!quiet_output) && (res > 0)) {
|
|
||||||
printf("Response after %u cycles\n", cycles);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
szRx = res;
|
|
||||||
// Show received answer
|
// Show received answer
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("Received bits: ");
|
printf ("Received bits: ");
|
||||||
print_hex(abtRx, szRx);
|
print_hex (abtRx, szRx);
|
||||||
}
|
}
|
||||||
// Succesful transfer
|
// Succesful transfer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_usage(char *argv[])
|
print_usage (char *argv[])
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS]\n", argv[0]);
|
printf ("Usage: %s [OPTIONS]\n", argv[0]);
|
||||||
printf("Options:\n");
|
printf ("Options:\n");
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||||
printf("\t-f\tForce RATS.\n");
|
|
||||||
printf("\t-t\tMeasure response time (in cycles).\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int arg;
|
int arg;
|
||||||
|
|
||||||
// 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")) {
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
quiet_output = true;
|
quiet_output = true;
|
||||||
} else if (0 == strcmp(argv[arg], "-f")) {
|
|
||||||
force_rats = true;
|
|
||||||
} else if (0 == strcmp(argv[arg], "-t")) {
|
|
||||||
timed = true;
|
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_context *context;
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
pnd = nfc_open(context, NULL);
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (!pnd) {
|
||||||
ERR("Error opening NFC reader");
|
printf ("Error connecting NFC reader\n");
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise NFC device as "initiator"
|
// Initialise NFC device as "initiator"
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
nfc_initiator_init (pnd);
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
|
||||||
nfc_close(pnd);
|
// Drop the field for a while
|
||||||
nfc_exit(context);
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
exit(EXIT_FAILURE);
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the CRC
|
// Configure the CRC
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
nfc_close(pnd);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
}
|
||||||
exit(EXIT_FAILURE);
|
// Configure parity settings
|
||||||
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
// Use raw send/receive methods
|
// Use raw send/receive methods
|
||||||
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
|
if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
nfc_close(pnd);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
// Disable 14443-4 autoswitching
|
// Disable 14443-4 autoswitching
|
||||||
if (nfc_device_set_property_bool(pnd, NP_AUTO_ISO14443_4, false) < 0) {
|
if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, false)) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
nfc_close(pnd);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
}
|
||||||
exit(EXIT_FAILURE);
|
// Force 14443-A mode
|
||||||
|
if (!nfc_configure (pnd, NDO_FORCE_ISO14443_A, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("NFC reader: %s opened\n\n", nfc_device_get_name(pnd));
|
// Enable field so more power consuming cards can power themselves up
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Connected to NFC reader: %s\n\n", pnd->acName);
|
||||||
|
|
||||||
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
||||||
if (!transmit_bits(abtReqa, 7)) {
|
if (!transmit_bits (abtReqa, 7)) {
|
||||||
printf("Error: No tag available\n");
|
printf ("Error: No tag available\n");
|
||||||
nfc_close(pnd);
|
nfc_disconnect (pnd);
|
||||||
nfc_exit(context);
|
return 1;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
memcpy(abtAtqa, abtRx, 2);
|
memcpy (abtAtqa, abtRx, 2);
|
||||||
|
|
||||||
// Anti-collision
|
// Anti-collision
|
||||||
transmit_bytes(abtSelectAll, 2);
|
transmit_bytes (abtSelectAll, 2);
|
||||||
|
|
||||||
// Check answer
|
// Check answer
|
||||||
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
||||||
@ -243,12 +209,12 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save the UID CL1
|
// Save the UID CL1
|
||||||
memcpy(abtRawUid, abtRx, 4);
|
memcpy (abtRawUid, abtRx, 4);
|
||||||
|
|
||||||
//Prepare and send CL1 Select-Command
|
//Prepare and send CL1 Select-Command
|
||||||
memcpy(abtSelectTag + 2, abtRx, 5);
|
memcpy (abtSelectTag + 2, abtRx, 5);
|
||||||
iso14443a_crc_append(abtSelectTag, 7);
|
iso14443a_crc_append (abtSelectTag, 7);
|
||||||
transmit_bytes(abtSelectTag, 9);
|
transmit_bytes (abtSelectTag, 9);
|
||||||
abtSak = abtRx[0];
|
abtSak = abtRx[0];
|
||||||
|
|
||||||
// Test if we are dealing with a CL2
|
// Test if we are dealing with a CL2
|
||||||
@ -260,14 +226,14 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szCL == 2) {
|
if(szCL == 2) {
|
||||||
// We have to do the anti-collision for cascade level 2
|
// We have to do the anti-collision for cascade level 2
|
||||||
|
|
||||||
// Prepare CL2 commands
|
// Prepare CL2 commands
|
||||||
abtSelectAll[0] = 0x95;
|
abtSelectAll[0] = 0x95;
|
||||||
|
|
||||||
// Anti-collision
|
// Anti-collision
|
||||||
transmit_bytes(abtSelectAll, 2);
|
transmit_bytes (abtSelectAll, 2);
|
||||||
|
|
||||||
// Check answer
|
// Check answer
|
||||||
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
||||||
@ -275,13 +241,13 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save UID CL2
|
// Save UID CL2
|
||||||
memcpy(abtRawUid + 4, abtRx, 4);
|
memcpy (abtRawUid + 4, abtRx, 4);
|
||||||
|
|
||||||
// Selection
|
// Selection
|
||||||
abtSelectTag[0] = 0x95;
|
abtSelectTag[0] = 0x95;
|
||||||
memcpy(abtSelectTag + 2, abtRx, 5);
|
memcpy (abtSelectTag + 2, abtRx, 5);
|
||||||
iso14443a_crc_append(abtSelectTag, 7);
|
iso14443a_crc_append (abtSelectTag, 7);
|
||||||
transmit_bytes(abtSelectTag, 9);
|
transmit_bytes (abtSelectTag, 9);
|
||||||
abtSak = abtRx[0];
|
abtSak = abtRx[0];
|
||||||
|
|
||||||
// Test if we are dealing with a CL3
|
// Test if we are dealing with a CL3
|
||||||
@ -293,12 +259,12 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szCL == 3) {
|
if ( szCL == 3) {
|
||||||
// We have to do the anti-collision for cascade level 3
|
// We have to do the anti-collision for cascade level 3
|
||||||
|
|
||||||
// Prepare and send CL3 AC-Command
|
// Prepare and send CL3 AC-Command
|
||||||
abtSelectAll[0] = 0x97;
|
abtSelectAll[0] = 0x97;
|
||||||
transmit_bytes(abtSelectAll, 2);
|
transmit_bytes (abtSelectAll, 2);
|
||||||
|
|
||||||
// Check answer
|
// Check answer
|
||||||
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
||||||
@ -306,59 +272,45 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save UID CL3
|
// Save UID CL3
|
||||||
memcpy(abtRawUid + 8, abtRx, 4);
|
memcpy (abtRawUid + 8, abtRx, 4);
|
||||||
|
|
||||||
// Prepare and send final Select-Command
|
// Prepare and send final Select-Command
|
||||||
abtSelectTag[0] = 0x97;
|
abtSelectTag[0] = 0x97;
|
||||||
memcpy(abtSelectTag + 2, abtRx, 5);
|
memcpy (abtSelectTag + 2, abtRx, 5);
|
||||||
iso14443a_crc_append(abtSelectTag, 7);
|
iso14443a_crc_append (abtSelectTag, 7);
|
||||||
transmit_bytes(abtSelectTag, 9);
|
transmit_bytes (abtSelectTag, 9);
|
||||||
abtSak = abtRx[0];
|
abtSak = abtRx[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request ATS, this only applies to tags that support ISO 14443A-4
|
// Request ATS, this only applies to tags that support ISO 14443A-4
|
||||||
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
|
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
|
||||||
iso_ats_supported = true;
|
|
||||||
}
|
|
||||||
if ((abtRx[0] & SAK_FLAG_ATS_SUPPORTED) || force_rats) {
|
|
||||||
iso14443a_crc_append(abtRats, 2);
|
iso14443a_crc_append(abtRats, 2);
|
||||||
if (transmit_bytes(abtRats, 4)) {
|
transmit_bytes (abtRats, 4);
|
||||||
memcpy(abtAts, abtRx, szRx);
|
|
||||||
szAts = szRx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done, halt the tag now
|
// Done, halt the tag now
|
||||||
iso14443a_crc_append(abtHalt, 2);
|
iso14443a_crc_append(abtHalt, 2);
|
||||||
transmit_bytes(abtHalt, 4);
|
transmit_bytes (abtHalt, 4);
|
||||||
|
|
||||||
printf("\nFound tag with\n UID: ");
|
printf ("\nFound tag with\n UID: ");
|
||||||
switch (szCL) {
|
switch (szCL) {
|
||||||
case 1:
|
case 1:
|
||||||
printf("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
printf ("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
printf("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
||||||
printf("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
|
printf ("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
printf("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
||||||
printf("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
|
printf ("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
|
||||||
printf("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
|
printf ("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);
|
printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);
|
||||||
if (szAts > 1) { // if = 1, it's not actual ATS but error code
|
|
||||||
if (force_rats && ! iso_ats_supported) {
|
|
||||||
printf(" RATS forced\n");
|
|
||||||
}
|
|
||||||
printf(" ATS: ");
|
|
||||||
print_hex(abtAts, szAts);
|
|
||||||
}
|
|
||||||
|
|
||||||
nfc_close(pnd);
|
nfc_disconnect (pnd);
|
||||||
nfc_exit(context);
|
return 0;
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-dep-initiator 1 "October 8, 2010" "libnfc" "libnfc's examples"
|
.TH NFC-DEP-INITIATOR 1 "October 8, 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-dep-initiator \- Demonstration tool to send/received data as D.E.P. initiator
|
nfc-dep-initiator \- Demonstration tool to send/received data as D.E.P. initiator
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -7,30 +7,23 @@ nfc-dep-initiator \- Demonstration tool to send/received data as D.E.P. initiato
|
|||||||
.B nfc-dep-initiator
|
.B nfc-dep-initiator
|
||||||
is a demonstration tool for putting NFC device in D.E.P. initiator mode.
|
is a demonstration tool for putting NFC device in D.E.P. initiator mode.
|
||||||
|
|
||||||
This example will attempt to select a passive D.E.P. target and exchange a
|
This example will attempt to select a passive D.E.P. target and exchange a simple "Hello" data with target.
|
||||||
simple "Hello" data with target.
|
|
||||||
|
|
||||||
Note: this example is designed to work with a D.E.P. target driven by
|
Note: this example is designed to work with a D.E.P. target driven by \fBnfc-dep-target\fP
|
||||||
\fBnfc-dep-target\fP
|
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Roel Verdult <roel@libnfc.org>,
|
Roel Verdult <roel@libnfc.org>
|
||||||
.br
|
Romuald Conty <romuald@libnfc.org>
|
||||||
Romuald Conty <romuald@libnfc.org>.
|
|
||||||
.PP
|
.PP
|
||||||
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
||||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -50,87 +44,64 @@
|
|||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
static nfc_device *pnd;
|
static nfc_device_t *pnd;
|
||||||
static nfc_context *context;
|
|
||||||
|
|
||||||
static void stop_dep_communication(int sig)
|
void stop_dep_communication (int sig)
|
||||||
{
|
{
|
||||||
(void) sig;
|
(void) sig;
|
||||||
if (pnd != NULL) {
|
if (pnd)
|
||||||
nfc_abort_command(pnd);
|
nfc_abort_command (pnd);
|
||||||
} else {
|
else
|
||||||
nfc_exit(context);
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
nfc_target nt;
|
nfc_target_t nt;
|
||||||
uint8_t abtRx[MAX_FRAME_LEN];
|
byte_t abtRx[MAX_FRAME_LEN];
|
||||||
uint8_t abtTx[] = "Hello World!";
|
size_t szRx = sizeof(abtRx);
|
||||||
|
byte_t abtTx[] = "Hello World!";
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
printf("Usage: %s\n", argv[0]);
|
printf ("Usage: %s\n", argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_init(&context);
|
pnd = nfc_connect (NULL);
|
||||||
if (context == NULL) {
|
if (!pnd) {
|
||||||
ERR("Unable to init libnfc (malloc)");
|
printf("Unable to connect to NFC device.\n");
|
||||||
exit(EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
|
|
||||||
pnd = nfc_open(context, NULL);
|
signal (SIGINT, stop_dep_communication);
|
||||||
if (pnd == NULL) {
|
|
||||||
ERR("Unable to open NFC device.");
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
printf("NFC device: %s\n opened", nfc_device_get_name(pnd));
|
|
||||||
|
|
||||||
signal(SIGINT, stop_dep_communication);
|
if (!nfc_initiator_init (pnd)) {
|
||||||
|
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
nfc_perror(pnd, "nfc_initiator_init");
|
||||||
nfc_close(pnd);
|
return EXIT_FAILURE;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfc_initiator_select_dep_target(pnd, NDM_PASSIVE, NBR_212, NULL, &nt, 1000) < 0) {
|
if(!nfc_initiator_select_dep_target (pnd, NDM_PASSIVE, NBR_212, NULL, &nt)) {
|
||||||
nfc_perror(pnd, "nfc_initiator_select_dep_target");
|
nfc_perror(pnd, "nfc_initiator_select_dep_target");
|
||||||
nfc_close(pnd);
|
return EXIT_FAILURE;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
print_nfc_target(&nt, false);
|
print_nfc_target (nt, false);
|
||||||
|
|
||||||
printf("Sending: %s\n", abtTx);
|
printf ("Sending: %s\n", abtTx);
|
||||||
int res;
|
if (!nfc_initiator_transceive_bytes (pnd, abtTx, sizeof(abtTx), abtRx, &szRx)) {
|
||||||
if ((res = nfc_initiator_transceive_bytes(pnd, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 0)) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_transceive_bytes");
|
nfc_perror(pnd, "nfc_initiator_transceive_bytes");
|
||||||
nfc_close(pnd);
|
return EXIT_FAILURE;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abtRx[res] = 0;
|
abtRx[szRx] = 0;
|
||||||
printf("Received: %s\n", abtRx);
|
printf ("Received: %s\n", abtRx);
|
||||||
|
|
||||||
if (nfc_initiator_deselect_target(pnd) < 0) {
|
nfc_initiator_deselect_target (pnd);
|
||||||
nfc_perror(pnd, "nfc_initiator_deselect_target");
|
nfc_disconnect (pnd);
|
||||||
nfc_close(pnd);
|
return EXIT_SUCCESS;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-dep-target 1 "October 8, 2010" "libnfc" "libnfc's examples"
|
.TH NFC-DEP-INITIATOR 1 "October 8, 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-dep-target \- Demonstration tool to send/received data as D.E.P. target
|
nfc-dep-target \- Demonstration tool to send/received data as D.E.P. target
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -7,30 +7,23 @@ nfc-dep-target \- Demonstration tool to send/received data as D.E.P. target
|
|||||||
.B nfc-dep-target
|
.B nfc-dep-target
|
||||||
is a demonstration tool for putting NFC device in D.E.P. target mode.
|
is a demonstration tool for putting NFC device in D.E.P. target mode.
|
||||||
|
|
||||||
This example will listen for a D.E.P. initiator and exchange a simple "Hello"
|
This example will listen for a D.E.P. initiator and exchange a simple "Hello" data with initiator.
|
||||||
data with initiator.
|
|
||||||
|
|
||||||
Note: this example is designed to work with a D.E.P. initiator driven by
|
Note: this example is designed to work with a D.E.P. initiator driven by \fBnfc-dep-initiator\fP.
|
||||||
\fBnfc-dep-initiator\fP.
|
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Roel Verdult <roel@libnfc.org>,
|
Roel Verdult <roel@libnfc.org>
|
||||||
.br
|
Romuald Conty <romuald@libnfc.org>
|
||||||
Romuald Conty <romuald@libnfc.org>.
|
|
||||||
.PP
|
.PP
|
||||||
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
||||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -49,59 +43,50 @@
|
|||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
static nfc_device *pnd;
|
static nfc_device_t *pnd;
|
||||||
static nfc_context *context;
|
|
||||||
|
|
||||||
static void stop_dep_communication(int sig)
|
void stop_dep_communication (int sig)
|
||||||
{
|
{
|
||||||
(void) sig;
|
(void) sig;
|
||||||
if (pnd != NULL) {
|
if (pnd)
|
||||||
nfc_abort_command(pnd);
|
nfc_abort_command (pnd);
|
||||||
} else {
|
else
|
||||||
nfc_exit(context);
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
uint8_t abtRx[MAX_FRAME_LEN];
|
byte_t abtRx[MAX_FRAME_LEN];
|
||||||
int szRx;
|
size_t szRx = sizeof(abtRx);
|
||||||
uint8_t abtTx[] = "Hello Mars!";
|
size_t szDeviceFound;
|
||||||
|
byte_t abtTx[] = "Hello Mars!";
|
||||||
if (argc > 1) {
|
#define MAX_DEVICE_COUNT 2
|
||||||
printf("Usage: %s\n", argv[0]);
|
nfc_device_desc_t pnddDevices[MAX_DEVICE_COUNT];
|
||||||
exit(EXIT_FAILURE);
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound);
|
||||||
}
|
|
||||||
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
#define MAX_DEVICE_COUNT 2
|
|
||||||
nfc_connstring connstrings[MAX_DEVICE_COUNT];
|
|
||||||
size_t szDeviceFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);
|
|
||||||
// Little hack to allow using nfc-dep-initiator & nfc-dep-target from
|
// Little hack to allow using nfc-dep-initiator & nfc-dep-target from
|
||||||
// the same machine: if there is more than one readers opened
|
// the same machine: if there is more than one readers connected
|
||||||
// nfc-dep-target will open the second reader
|
// nfc-dep-target will connect to the second reader
|
||||||
// (we hope they're always detected in the same order)
|
// (we hope they're always detected in the same order)
|
||||||
if (szDeviceFound == 1) {
|
if (szDeviceFound == 1) {
|
||||||
pnd = nfc_open(context, connstrings[0]);
|
pnd = nfc_connect (&(pnddDevices[0]));
|
||||||
} else if (szDeviceFound > 1) {
|
} else if (szDeviceFound > 1) {
|
||||||
pnd = nfc_open(context, connstrings[1]);
|
pnd = nfc_connect (&(pnddDevices[1]));
|
||||||
} else {
|
} else {
|
||||||
printf("No device found.\n");
|
printf("No device found.");
|
||||||
nfc_exit(context);
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_target nt = {
|
if (argc > 1) {
|
||||||
|
printf ("Usage: %s\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_target_t nt = {
|
||||||
.nm = {
|
.nm = {
|
||||||
.nmt = NMT_DEP,
|
.nmt = NMT_DEP,
|
||||||
.nbr = NBR_UNDEFINED
|
.nbr = NBR_UNDEFINED
|
||||||
@ -111,7 +96,6 @@ main(int argc, const char *argv[])
|
|||||||
.abtNFCID3 = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00, 0x00 },
|
.abtNFCID3 = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00, 0x00 },
|
||||||
.szGB = 4,
|
.szGB = 4,
|
||||||
.abtGB = { 0x12, 0x34, 0x56, 0x78 },
|
.abtGB = { 0x12, 0x34, 0x56, 0x78 },
|
||||||
.ndm = NDM_UNDEFINED,
|
|
||||||
/* These bytes are not used by nfc_target_init: the chip will provide them automatically to the initiator */
|
/* These bytes are not used by nfc_target_init: the chip will provide them automatically to the initiator */
|
||||||
.btDID = 0x00,
|
.btDID = 0x00,
|
||||||
.btBS = 0x00,
|
.btBS = 0x00,
|
||||||
@ -122,46 +106,38 @@ main(int argc, const char *argv[])
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (!pnd) {
|
||||||
printf("Unable to open NFC device.\n");
|
printf("Unable to connect to NFC device.\n");
|
||||||
nfc_exit(context);
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
|
|
||||||
signal(SIGINT, stop_dep_communication);
|
signal (SIGINT, stop_dep_communication);
|
||||||
|
|
||||||
printf("NFC device will now act as: ");
|
printf ("NFC device will now act as: ");
|
||||||
print_nfc_target(&nt, false);
|
print_nfc_target (nt, false);
|
||||||
|
|
||||||
printf("Waiting for initiator request...\n");
|
printf ("Waiting for initiator request...\n");
|
||||||
if ((szRx = nfc_target_init(pnd, &nt, abtRx, sizeof(abtRx), 0)) < 0) {
|
if(!nfc_target_init (pnd, &nt, abtRx, &szRx)) {
|
||||||
nfc_perror(pnd, "nfc_target_init");
|
nfc_perror(pnd, "nfc_target_init");
|
||||||
nfc_close(pnd);
|
return EXIT_FAILURE;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Initiator request received. Waiting for data...\n");
|
printf("Initiator request received. Waiting for data...\n");
|
||||||
if ((szRx = nfc_target_receive_bytes(pnd, abtRx, sizeof(abtRx), 0)) < 0) {
|
if (!nfc_target_receive_bytes (pnd, abtRx, &szRx)) {
|
||||||
nfc_perror(pnd, "nfc_target_receive_bytes");
|
nfc_perror(pnd, "nfc_target_receive_bytes");
|
||||||
nfc_close(pnd);
|
return EXIT_FAILURE;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
abtRx[(size_t) szRx] = '\0';
|
abtRx[szRx] = '\0';
|
||||||
printf("Received: %s\n", abtRx);
|
printf ("Received: %s\n", abtRx);
|
||||||
|
|
||||||
printf("Sending: %s\n", abtTx);
|
printf ("Sending: %s\n", abtTx);
|
||||||
if (nfc_target_send_bytes(pnd, abtTx, sizeof(abtTx), 0) < 0) {
|
if (!nfc_target_send_bytes (pnd, abtTx, sizeof(abtTx))) {
|
||||||
nfc_perror(pnd, "nfc_target_send_bytes");
|
nfc_perror(pnd, "nfc_target_send_bytes");
|
||||||
nfc_close(pnd);
|
return EXIT_FAILURE;
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
printf("Data sent.\n");
|
printf("Data sent.\n");
|
||||||
|
|
||||||
nfc_close(pnd);
|
nfc_disconnect (pnd);
|
||||||
nfc_exit(context);
|
return EXIT_SUCCESS;
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
.Dd September 19, 2012
|
|
||||||
.Dt NFC-EMULATE-FORUM-TAG2 1 URM
|
|
||||||
.Sh NAME
|
|
||||||
.Nm nfc-emulate-forum-tag2
|
|
||||||
.Nd NFC Forum tag type 2 emulation command line demonstration tool
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
is a demonstration tool that emulates a NFC-Forum Tag Type 2 with NDEF content.
|
|
||||||
.Pp
|
|
||||||
Some devices compliant with NFC-Forum Tag Type 2 can be used with this example,
|
|
||||||
in read mode only.
|
|
||||||
.Sh IMPORTANT
|
|
||||||
This example has been developed using PN533 USB hardware as target and Google
|
|
||||||
Nexus S phone as initiator.
|
|
||||||
.Pp
|
|
||||||
This is know to NOT work with Nokia 6212 Classic and could fail with several
|
|
||||||
NFC Forum compliant devices due to the following reasons:
|
|
||||||
.Pp
|
|
||||||
- The emulated target has only a 4-byte UID while most devices assume a
|
|
||||||
Tag Type 2 has always a 7-byte UID (as a real Mifare Ultralight tag);
|
|
||||||
.Pp
|
|
||||||
- The chip is emulating an ISO/IEC 14443-3 tag, without any hardware helper.
|
|
||||||
If the initiator have too strict timeouts for software-based emulation
|
|
||||||
(which is usually the case), this example will fail.
|
|
||||||
This is not a bug and we can't do anything using this hardware (PN531/PN533).
|
|
||||||
.Pp
|
|
||||||
ACR122 devices (like touchatag, etc.) can be used by this example, but if
|
|
||||||
something goes wrong, you will have to unplug/replug your device.
|
|
||||||
This is not a
|
|
||||||
.Em libnfc's
|
|
||||||
bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532).
|
|
||||||
.Sh BUGS
|
|
||||||
Please report any bugs on the
|
|
||||||
.Em libnfc
|
|
||||||
issue tracker at:
|
|
||||||
.Em https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.Sh LICENCE
|
|
||||||
.Em libnfc
|
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.Em libnfc-utils
|
|
||||||
and
|
|
||||||
.Em libnfc-examples
|
|
||||||
are covered by the BSD 2-Clause license.
|
|
||||||
.Sh AUTHORS
|
|
||||||
.An Roel Verdult Aq roel@libnfc.org
|
|
||||||
.An Romain Tartière Aq romain@libnfc.org
|
|
||||||
.An Romuald Conty Aq romuald@libnfc.org
|
|
||||||
.Pp
|
|
||||||
This manual page was written by Romuald Conty.
|
|
||||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
|
||||||
@ -1,223 +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-emulate-forum-tag2.c
|
|
||||||
* @brief Emulates a NFC-Forum Tag Type 2 with a NDEF message
|
|
||||||
* This example allow to emulate an NFC-Forum Tag Type 2 that contains
|
|
||||||
* a read-only NDEF message.
|
|
||||||
*
|
|
||||||
* This example has been developed using PN533 USB hardware as target and
|
|
||||||
* Google Nexus S phone as initiator.
|
|
||||||
*
|
|
||||||
* This is know to NOT work with Nokia 6212 Classic and could fail with
|
|
||||||
* several NFC Forum compliant devices due to the following reasons:
|
|
||||||
* - The emulated target has only a 4-byte UID while most devices assume a Tag
|
|
||||||
* Type 2 has always a 7-byte UID (as a real Mifare Ultralight tag);
|
|
||||||
* - The chip is emulating an ISO/IEC 14443-3 tag, without any hardware helper.
|
|
||||||
* If the initiator has too strict timeouts for software-based emulation
|
|
||||||
* (which is usually the case), this example will fail. This is not a bug
|
|
||||||
* and we can't do anything using this hardware (PN531/PN533).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This implementation was written based on information provided by the
|
|
||||||
* following documents:
|
|
||||||
*
|
|
||||||
* NFC Forum Type 2 Tag Operation
|
|
||||||
* Technical Specification
|
|
||||||
* NFCForum-TS-Type-2-Tag_1.0 - 2007-07-09
|
|
||||||
*
|
|
||||||
* ISO/IEC 14443-3
|
|
||||||
* First edition - 2001-02-01
|
|
||||||
* Identification cards — Contactless integrated circuit(s) cards — Proximity cards
|
|
||||||
* Part 3: Initialization and anticollision
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
|
||||||
#include <nfc/nfc-emulation.h>
|
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
|
||||||
|
|
||||||
static nfc_device *pnd;
|
|
||||||
static nfc_context *context;
|
|
||||||
|
|
||||||
static void
|
|
||||||
stop_emulation(int sig)
|
|
||||||
{
|
|
||||||
(void)sig;
|
|
||||||
if (pnd != NULL) {
|
|
||||||
nfc_abort_command(pnd);
|
|
||||||
} else {
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t __nfcforum_tag2_memory_area[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Block 0
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xFF, 0xFF, // Block 2 (Static lock bytes: CC area and data area are read-only locked)
|
|
||||||
0xE1, 0x10, 0x06, 0x0F, // Block 3 (CC - NFC-Forum Tag Type 2 version 1.0, Data area (from block 4 to the end) is 48 bytes, Read-only mode)
|
|
||||||
|
|
||||||
0x03, 33, 0xd1, 0x02, // Block 4 (NDEF)
|
|
||||||
0x1c, 0x53, 0x70, 0x91,
|
|
||||||
0x01, 0x09, 0x54, 0x02,
|
|
||||||
0x65, 0x6e, 0x4c, 0x69,
|
|
||||||
|
|
||||||
0x62, 0x6e, 0x66, 0x63,
|
|
||||||
0x51, 0x01, 0x0b, 0x55,
|
|
||||||
0x03, 0x6c, 0x69, 0x62,
|
|
||||||
0x6e, 0x66, 0x63, 0x2e,
|
|
||||||
|
|
||||||
0x6f, 0x72, 0x67, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define READ 0x30
|
|
||||||
#define WRITE 0xA2
|
|
||||||
#define SECTOR_SELECT 0xC2
|
|
||||||
|
|
||||||
#define HALT 0x50
|
|
||||||
static int
|
|
||||||
nfcforum_tag2_io(struct nfc_emulator *emulator, const uint8_t *data_in, const size_t data_in_len, uint8_t *data_out, const size_t data_out_len)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
uint8_t *nfcforum_tag2_memory_area = (uint8_t *)(emulator->user_data);
|
|
||||||
|
|
||||||
printf(" In: ");
|
|
||||||
print_hex(data_in, data_in_len);
|
|
||||||
|
|
||||||
switch (data_in[0]) {
|
|
||||||
case READ:
|
|
||||||
if (data_out_len >= 16) {
|
|
||||||
memcpy(data_out, nfcforum_tag2_memory_area + (data_in[1] * 4), 16);
|
|
||||||
res = 16;
|
|
||||||
} else {
|
|
||||||
res = -ENOSPC;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HALT:
|
|
||||||
printf("HALT sent\n");
|
|
||||||
res = -ECONNABORTED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Unknown command: 0x%02x\n", data_in[0]);
|
|
||||||
res = -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
ERR("%s (%d)", strerror(-res), -res);
|
|
||||||
} else {
|
|
||||||
printf(" Out: ");
|
|
||||||
print_hex(data_out, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
nfc_target nt = {
|
|
||||||
.nm = {
|
|
||||||
.nmt = NMT_ISO14443A,
|
|
||||||
.nbr = NBR_UNDEFINED, // Will be updated by nfc_target_init()
|
|
||||||
},
|
|
||||||
.nti = {
|
|
||||||
.nai = {
|
|
||||||
.abtAtqa = { 0x00, 0x04 },
|
|
||||||
.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
|
|
||||||
.szUidLen = 4,
|
|
||||||
.btSak = 0x00,
|
|
||||||
.szAtsLen = 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nfc_emulation_state_machine state_machine = {
|
|
||||||
.io = nfcforum_tag2_io
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nfc_emulator emulator = {
|
|
||||||
.target = &nt,
|
|
||||||
.state_machine = &state_machine,
|
|
||||||
.user_data = __nfcforum_tag2_memory_area,
|
|
||||||
};
|
|
||||||
|
|
||||||
signal(SIGINT, stop_emulation);
|
|
||||||
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
pnd = nfc_open(context, NULL);
|
|
||||||
|
|
||||||
if (pnd == NULL) {
|
|
||||||
ERR("Unable to open NFC device");
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
|
|
||||||
printf("Emulating NDEF tag now, please touch it with a second NFC device\n");
|
|
||||||
|
|
||||||
if (nfc_emulate_target(pnd, &emulator, 0) < 0) {
|
|
||||||
nfc_perror(pnd, argv[0]);
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -5,18 +5,14 @@
|
|||||||
.Nd NFC Forum tag type 4 emulation command line demonstration tool
|
.Nd NFC Forum tag type 4 emulation command line demonstration tool
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op -1
|
|
||||||
.Op infile Op outfile
|
.Op infile Op outfile
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
is a demonstration tool that emulates a NFC Forum tag type 4 v2.0 (or v1.0) with NDEF content.
|
is a demonstration tool that emulates a NFC Forum tag type 4 with NDEF content.
|
||||||
.Pp
|
|
||||||
.Ar -1
|
|
||||||
can be provided to force old Tag Type 4 version 1.0 behavior.
|
|
||||||
.Pp
|
.Pp
|
||||||
.Ar infile
|
.Ar infile
|
||||||
is the file which contains NDEF message you want to share with the NFC-Forum
|
is the file which contains NDEF message you want to share with the NFC-Forum
|
||||||
compliant initiator device (e.g. Nokia 6212 Classic for a v1.0 tag)
|
compiliant initiator device (e.g. Nokia 6212 Classic)
|
||||||
.Pp
|
.Pp
|
||||||
If you want to save a shared content by the initiator device, we have to give
|
If you want to save a shared content by the initiator device, we have to give
|
||||||
.Ar outfile
|
.Ar outfile
|
||||||
@ -25,7 +21,7 @@ argument to point where the NDEF message will be saved.
|
|||||||
This example uses the hardware capability of PN532 to handle ISO/IEC 14443-4
|
This example uses the hardware capability of PN532 to handle ISO/IEC 14443-4
|
||||||
low-level frames like RATS/ATS, WTX, etc.
|
low-level frames like RATS/ATS, WTX, etc.
|
||||||
.Pp
|
.Pp
|
||||||
All devices compliant with NFC-Forum Tag Type 4 (Version 2.0 or 1.0) can be used with
|
All devices compiliant with NFC-Forum Tag Type 4 (Version 1.0) can be used with
|
||||||
this example in read-write mode.
|
this example in read-write mode.
|
||||||
.Pp
|
.Pp
|
||||||
If no argument is given, a default NDEF file is available.
|
If no argument is given, a default NDEF file is available.
|
||||||
@ -45,15 +41,13 @@ bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532).
|
|||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.Em libnfc
|
.Em libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.Em https://github.com/nfc-tools/libnfc/issues
|
.Em http://www.libnfc.org/community/ "."
|
||||||
.Sh LICENCE
|
.Sh LICENCE
|
||||||
.Em libnfc
|
.Em libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.Em libnfc-utils
|
|
||||||
and
|
and
|
||||||
.Em libnfc-examples
|
.Em libnfc-examples
|
||||||
are covered by the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An Roel Verdult Aq roel@libnfc.org
|
.An Roel Verdult Aq roel@libnfc.org
|
||||||
.An Romain Tartière Aq romain@libnfc.org
|
.An Romain Tartière Aq romain@libnfc.org
|
||||||
366
examples/nfc-emulate-forum-tag4.c
Normal file
366
examples/nfc-emulate-forum-tag4.c
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010, Roel Verdult, Romuald Conty
|
||||||
|
* Copyright (C) 2011, Romain Tartière, Romuald Conty
|
||||||
|
*
|
||||||
|
* 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-emulate-forum-tag4.c
|
||||||
|
* @brief Emulates a NFC Forum Tag Type 4 with a NDEF message
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Notes & differences with nfc-emulate-tag:
|
||||||
|
// - This example only works with PN532 because it relies on
|
||||||
|
// its internal handling of ISO14443-4 specificities.
|
||||||
|
// - Thanks to this internal handling & injection of WTX frames,
|
||||||
|
// this example works on readers very strict on timing
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
#include <nfc/nfc-emulation.h>
|
||||||
|
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
static nfc_device_t *pnd;
|
||||||
|
static bool quiet_output = false;
|
||||||
|
|
||||||
|
#define SYMBOL_PARAM_fISO14443_4_PICC 0x20
|
||||||
|
|
||||||
|
typedef enum { NONE, CC_FILE, NDEF_FILE } file;
|
||||||
|
|
||||||
|
struct nfcforum_tag4_ndef_data {
|
||||||
|
uint8_t *ndef_file;
|
||||||
|
size_t ndef_file_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfcforum_tag4_state_machine_data {
|
||||||
|
file current_file;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t nfcforum_capability_container[] = {
|
||||||
|
0x00, 0x0F, /* CCLEN 15 bytes */
|
||||||
|
0x10, /* Mapping version 1.0 */
|
||||||
|
0x00, 0x54, /* MLe Maximum R-ADPU data size */
|
||||||
|
// Notes:
|
||||||
|
// - I (Romuald) don't know why Nokia 6212 Classic refuses the NDEF message if MLe is more than 0xFD (any suggests are welcome);
|
||||||
|
// - ARYGON devices doesn't support extended frame sending, consequently these devices can't sent more than 0xFE bytes as APDU, so 0xFB APDU data bytes.
|
||||||
|
// - I (Romuald) don't know why ARYGON device doesn't ACK when MLe > 0x54 (ARYGON frame lenght = 0xC2 (192 bytes))
|
||||||
|
0x00, 0xFF, /* MLc Maximum C-ADPU data size */
|
||||||
|
0x04, /* T field of the NDEF File-Control TLV */
|
||||||
|
0x06, /* L field of the NDEF File-Control TLV */
|
||||||
|
/* V field of the NDEF File-Control TLV */
|
||||||
|
0xE1, 0x04, /* File identifier */
|
||||||
|
0xFF, 0xFE, /* Maximum NDEF Size */
|
||||||
|
0x00, /* NDEF file read access condition */
|
||||||
|
0x00, /* NDEF file write access condition */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* C-ADPU offsets */
|
||||||
|
#define CLA 0
|
||||||
|
#define INS 1
|
||||||
|
#define P1 2
|
||||||
|
#define P2 3
|
||||||
|
#define LC 4
|
||||||
|
#define DATA 5
|
||||||
|
|
||||||
|
#define ISO144434A_RATS 0xE0
|
||||||
|
|
||||||
|
int
|
||||||
|
nfcforum_tag4_io (struct nfc_emulator *emulator, const byte_t *data_in, const size_t data_in_len, byte_t *data_out, const size_t data_out_len)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
struct nfcforum_tag4_ndef_data *ndef_data = (struct nfcforum_tag4_ndef_data *)(emulator->user_data);
|
||||||
|
struct nfcforum_tag4_state_machine_data *state_machine_data = (struct nfcforum_tag4_state_machine_data *)(emulator->state_machine->data);
|
||||||
|
|
||||||
|
// Show transmitted command
|
||||||
|
if (!quiet_output) {
|
||||||
|
printf (" In: ");
|
||||||
|
print_hex (data_in, data_in_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The PN532 already handle RATS
|
||||||
|
*/
|
||||||
|
if ((data_in_len == 2) && (data_in[0] == ISO144434A_RATS))
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if(data_in_len >= 4) {
|
||||||
|
if (data_in[CLA] != 0x00)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
#define ISO7816_SELECT 0xA4
|
||||||
|
#define ISO7816_READ_BINARY 0xB0
|
||||||
|
#define ISO7816_UPDATE_BINARY 0xD6
|
||||||
|
|
||||||
|
switch(data_in[INS]) {
|
||||||
|
case ISO7816_SELECT:
|
||||||
|
|
||||||
|
switch (data_in[P1]) {
|
||||||
|
case 0x00: /* Select by ID */
|
||||||
|
if ((data_in[P2] | 0x0C) != 0x0C)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
const uint8_t ndef_capability_container[] = { 0xE1, 0x03 };
|
||||||
|
const uint8_t ndef_file[] = { 0xE1, 0x04 };
|
||||||
|
if ((data_in[LC] == sizeof (ndef_capability_container)) && (0 == memcmp (ndef_capability_container, data_in + DATA, data_in[LC]))) {
|
||||||
|
memcpy (data_out, "\x90\x00", res = 2);
|
||||||
|
state_machine_data->current_file = CC_FILE;
|
||||||
|
} else if ((data_in[LC] == sizeof (ndef_file)) && (0 == memcmp (ndef_file, data_in + DATA, data_in[LC]))) {
|
||||||
|
memcpy (data_out, "\x90\x00", res = 2);
|
||||||
|
state_machine_data->current_file = NDEF_FILE;
|
||||||
|
} else {
|
||||||
|
memcpy (data_out, "\x6a\x00", res = 2);
|
||||||
|
state_machine_data->current_file = NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x04: /* Select by name */
|
||||||
|
if (data_in[P2] != 0x00)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
const uint8_t ndef_tag_application_name[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 };
|
||||||
|
if ((data_in[LC] == sizeof (ndef_tag_application_name)) && (0 == memcmp (ndef_tag_application_name, data_in + DATA, data_in[LC])))
|
||||||
|
memcpy (data_out, "\x90\x00", res = 2);
|
||||||
|
else
|
||||||
|
memcpy (data_out, "\x6a\x82", res = 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ISO7816_READ_BINARY:
|
||||||
|
if ((size_t)(data_in[LC] + 2) > data_out_len) {
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
switch (state_machine_data->current_file) {
|
||||||
|
case NONE:
|
||||||
|
memcpy (data_out, "\x6a\x82", res = 2);
|
||||||
|
break;
|
||||||
|
case CC_FILE:
|
||||||
|
memcpy (data_out, nfcforum_capability_container + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
|
||||||
|
memcpy (data_out + data_in[LC], "\x90\x00", 2);
|
||||||
|
res = data_in[LC] + 2;
|
||||||
|
break;
|
||||||
|
case NDEF_FILE:
|
||||||
|
memcpy (data_out, ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
|
||||||
|
memcpy (data_out + data_in[LC], "\x90\x00", 2);
|
||||||
|
res = data_in[LC] + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ISO7816_UPDATE_BINARY:
|
||||||
|
memcpy (ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in + DATA, data_in[LC]);
|
||||||
|
if ((data_in[P1] << 8) + data_in[P2] == 0) {
|
||||||
|
ndef_data->ndef_file_len = (ndef_data->ndef_file[0] << 8) + ndef_data->ndef_file[1] + 2;
|
||||||
|
}
|
||||||
|
memcpy (data_out, "\x90\x00", res = 2);
|
||||||
|
break;
|
||||||
|
default: // Unknown
|
||||||
|
if (!quiet_output) {
|
||||||
|
printf("Unknown frame, emulated target abort.\n");
|
||||||
|
}
|
||||||
|
res = -ENOTSUP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show transmitted command
|
||||||
|
if (!quiet_output) {
|
||||||
|
printf (" Out: ");
|
||||||
|
if (res < 0)
|
||||||
|
printf ("No data (returning with an error %d)\n", res);
|
||||||
|
else
|
||||||
|
print_hex (data_out, res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_emulation (int sig)
|
||||||
|
{
|
||||||
|
(void) sig;
|
||||||
|
if (pnd)
|
||||||
|
nfc_abort_command (pnd);
|
||||||
|
else
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ndef_message_load (char *filename, struct nfcforum_tag4_ndef_data *tag_data)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
if (stat (filename, &sb) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check file size */
|
||||||
|
if (sb.st_size > 0xFFFF) {
|
||||||
|
errx (EXIT_FAILURE, "file size too large '%s'", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
tag_data->ndef_file_len = sb.st_size + 2;
|
||||||
|
|
||||||
|
tag_data->ndef_file[0] = (uint8_t)(sb.st_size >> 8);
|
||||||
|
tag_data->ndef_file[1] = (uint8_t)(sb.st_size);
|
||||||
|
|
||||||
|
FILE *F;
|
||||||
|
if (!(F = fopen (filename, "r")))
|
||||||
|
err (EXIT_FAILURE, "fopen (%s, \"r\")", filename);
|
||||||
|
|
||||||
|
if (1 != fread (tag_data->ndef_file + 2, sb.st_size, 1, F))
|
||||||
|
err (EXIT_FAILURE, "Can't read from %s", filename);
|
||||||
|
|
||||||
|
fclose (F);
|
||||||
|
return sb.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ndef_message_save (char *filename, struct nfcforum_tag4_ndef_data *tag_data)
|
||||||
|
{
|
||||||
|
FILE *F;
|
||||||
|
if (!(F= fopen (filename, "w")))
|
||||||
|
err (EXIT_FAILURE, "fopen (%s, w)", filename);
|
||||||
|
|
||||||
|
if (1 != fwrite (tag_data->ndef_file + 2, tag_data->ndef_file_len - 2, 1, F)) {
|
||||||
|
err (EXIT_FAILURE, "fwrite (%lu)", tag_data->ndef_file_len -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (F);
|
||||||
|
|
||||||
|
return tag_data->ndef_file_len - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage (char *progname)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "usage: %s [infile [outfile]]\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
nfc_target_t nt = {
|
||||||
|
.nm = {
|
||||||
|
.nmt = NMT_ISO14443A,
|
||||||
|
.nbr = NBR_UNDEFINED, // Will be updated by nfc_target_init()
|
||||||
|
},
|
||||||
|
.nti = {
|
||||||
|
.nai = {
|
||||||
|
.abtAtqa = { 0x00, 0x04 },
|
||||||
|
.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
|
||||||
|
.szUidLen = 4,
|
||||||
|
.btSak = 0x20,
|
||||||
|
.abtAts = { 0x75, 0x33, 0x92, 0x03 }, /* Not used by PN532 */
|
||||||
|
.szAtsLen = 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t ndef_file[0xfffe] = {
|
||||||
|
0x00, 33,
|
||||||
|
0xd1, 0x02, 0x1c, 0x53, 0x70, 0x91, 0x01, 0x09, 0x54, 0x02,
|
||||||
|
0x65, 0x6e, 0x4c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x51, 0x01,
|
||||||
|
0x0b, 0x55, 0x03, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x2e,
|
||||||
|
0x6f, 0x72, 0x67
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfcforum_tag4_ndef_data nfcforum_tag4_data = {
|
||||||
|
.ndef_file = ndef_file,
|
||||||
|
.ndef_file_len = ndef_file[1] + 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfcforum_tag4_state_machine_data state_machine_data = {
|
||||||
|
.current_file = NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfc_emulation_state_machine state_machine = {
|
||||||
|
.io = nfcforum_tag4_io,
|
||||||
|
.data = &state_machine_data,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfc_emulator emulator = {
|
||||||
|
.target = &nt,
|
||||||
|
.state_machine = &state_machine,
|
||||||
|
.user_data = &nfcforum_tag4_data,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If some file is provided load it
|
||||||
|
if (argc >= 2) {
|
||||||
|
if (!ndef_message_load (argv[1], &nfcforum_tag4_data)) {
|
||||||
|
err (EXIT_FAILURE, "Can't load NDEF file '%s'", argv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to open the NFC reader
|
||||||
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
|
if (pnd == NULL) {
|
||||||
|
ERR("Unable to connect to NFC device");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal (SIGINT, stop_emulation);
|
||||||
|
|
||||||
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
|
printf ("Emulating NDEF tag now, please touch it with a second NFC device\n");
|
||||||
|
|
||||||
|
nfc_emulate_target (pnd, &emulator);
|
||||||
|
|
||||||
|
nfc_disconnect(pnd);
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
if (!(ndef_message_save (argv[2], &nfcforum_tag4_data))) {
|
||||||
|
err (EXIT_FAILURE, "Can't save NDEF file '%s'", argv[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-emulate-tag 1 "October 8, 2010" "libnfc" "libnfc's examples"
|
.TH NFC-EMULATE-TAG 1 "October 8, 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-emulate-tag \- Simple tag emulation command line demonstration tool
|
nfc-emulate-tag \- Simple tag emulation command line demonstration tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -37,17 +37,13 @@ bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532).
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Romuald Conty <romuald@libnfc.org>
|
Romuald Conty <romuald@libnfc.org>
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@ -1,14 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -56,48 +49,44 @@
|
|||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define MAX_FRAME_LEN (264)
|
#define MAX_FRAME_LEN (264)
|
||||||
#define SAK_ISO14443_4_COMPLIANT 0x20
|
#define SAK_ISO14443_4_COMPLIANT 0x20
|
||||||
|
|
||||||
static uint8_t abtRx[MAX_FRAME_LEN];
|
static byte_t abtRx[MAX_FRAME_LEN];
|
||||||
static int szRx;
|
static size_t szRx = sizeof(abtRx);
|
||||||
static nfc_context *context;
|
static nfc_device_t *pnd;
|
||||||
static nfc_device *pnd;
|
|
||||||
static bool quiet_output = false;
|
static bool quiet_output = false;
|
||||||
static bool init_mfc_auth = false;
|
static bool init_mfc_auth = false;
|
||||||
|
|
||||||
static void
|
void
|
||||||
intr_hdlr(int sig)
|
intr_hdlr (void)
|
||||||
{
|
{
|
||||||
(void) sig;
|
printf ("\nQuitting...\n");
|
||||||
printf("\nQuitting...\n");
|
|
||||||
if (pnd != NULL) {
|
if (pnd != NULL) {
|
||||||
nfc_abort_command(pnd);
|
nfc_disconnect(pnd);
|
||||||
}
|
}
|
||||||
nfc_close(pnd);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
target_io(nfc_target *pnt, const uint8_t *pbtInput, const size_t szInput, uint8_t *pbtOutput, size_t *pszOutput)
|
target_io( nfc_target_t * pnt, const byte_t * pbtInput, const size_t szInput, byte_t * pbtOutput, size_t *pszOutput )
|
||||||
{
|
{
|
||||||
bool loop = true;
|
bool loop = true;
|
||||||
*pszOutput = 0;
|
*pszOutput = 0;
|
||||||
|
|
||||||
// Show transmitted command
|
// Show transmitted command
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf(" In: ");
|
printf (" In: ");
|
||||||
print_hex(pbtInput, szInput);
|
print_hex (pbtInput, szInput);
|
||||||
}
|
}
|
||||||
if (szInput) {
|
if(szInput) {
|
||||||
switch (pbtInput[0]) {
|
switch(pbtInput[0]) {
|
||||||
case 0x30: // Mifare read
|
case 0x30: // Mifare read
|
||||||
// block address is in pbtInput[1]
|
// block address is in pbtInput[1]
|
||||||
*pszOutput = 15;
|
*pszOutput = 15;
|
||||||
strcpy((char *)pbtOutput, "You read block ");
|
strcpy((char*)pbtOutput, "You read block ");
|
||||||
pbtOutput[15] = pbtInput[1];
|
pbtOutput[15] = pbtInput[1];
|
||||||
break;
|
break;
|
||||||
case 0x50: // HLTA (ISO14443-3)
|
case 0x50: // HLTA (ISO14443-3)
|
||||||
@ -118,9 +107,9 @@ target_io(nfc_target *pnt, const uint8_t *pbtInput, const size_t szInput, uint8_
|
|||||||
case 0xe0: // RATS (ISO14443-4)
|
case 0xe0: // RATS (ISO14443-4)
|
||||||
// Send ATS
|
// Send ATS
|
||||||
*pszOutput = pnt->nti.nai.szAtsLen + 1;
|
*pszOutput = pnt->nti.nai.szAtsLen + 1;
|
||||||
pbtOutput[0] = pnt->nti.nai.szAtsLen + 1; // ISO14443-4 says that ATS contains ATS_Length as first byte
|
pbtOutput[0] = pnt->nti.nai.szAtsLen + 1; // ISO14443-4 says that ATS contains ATS_Lenght as first byte
|
||||||
if (pnt->nti.nai.szAtsLen) {
|
if(pnt->nti.nai.szAtsLen) {
|
||||||
memcpy(pbtOutput + 1, pnt->nti.nai.abtAts, pnt->nti.nai.szAtsLen);
|
memcpy(pbtOutput+1, pnt->nti.nai.abtAts, pnt->nti.nai.szAtsLen);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xc2: // S-block DESELECT
|
case 0xc2: // S-block DESELECT
|
||||||
@ -138,44 +127,39 @@ target_io(nfc_target *pnt, const uint8_t *pbtInput, const size_t szInput, uint8_
|
|||||||
}
|
}
|
||||||
// Show transmitted command
|
// Show transmitted command
|
||||||
if ((!quiet_output) && *pszOutput) {
|
if ((!quiet_output) && *pszOutput) {
|
||||||
printf(" Out: ");
|
printf (" Out: ");
|
||||||
print_hex(pbtOutput, *pszOutput);
|
print_hex (pbtOutput, *pszOutput);
|
||||||
}
|
}
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
nfc_target_emulate_tag(nfc_device *dev, nfc_target *pnt)
|
nfc_target_emulate_tag(nfc_device_t* pnd, nfc_target_t * pnt)
|
||||||
{
|
{
|
||||||
size_t szTx;
|
size_t szTx;
|
||||||
uint8_t abtTx[MAX_FRAME_LEN];
|
byte_t abtTx[MAX_FRAME_LEN];
|
||||||
bool loop = true;
|
bool loop = true;
|
||||||
|
|
||||||
if ((szRx = nfc_target_init(dev, pnt, abtRx, sizeof(abtRx), 0)) < 0) {
|
if (!nfc_target_init (pnd, pnt, abtRx, &szRx)) {
|
||||||
nfc_perror(dev, "nfc_target_init");
|
nfc_perror (pnd, "nfc_target_init");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (loop) {
|
while ( loop ) {
|
||||||
loop = target_io(pnt, abtRx, (size_t) szRx, abtTx, &szTx);
|
loop = target_io( pnt, abtRx, szRx, abtTx, &szTx );
|
||||||
if (szTx) {
|
if (szTx) {
|
||||||
if (nfc_target_send_bytes(dev, abtTx, szTx, 0) < 0) {
|
if (!nfc_target_send_bytes(pnd, abtTx, szTx)) {
|
||||||
nfc_perror(dev, "nfc_target_send_bytes");
|
nfc_perror (pnd, "nfc_target_send_bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (loop) {
|
if ( loop ) {
|
||||||
if (init_mfc_auth) {
|
if ( init_mfc_auth ) {
|
||||||
if (nfc_device_set_property_bool(dev, NP_HANDLE_CRC, false) < 0) {
|
nfc_configure (pnd, NDO_HANDLE_CRC, false);
|
||||||
nfc_perror(pnd, "nfc_target_emulate_tag");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
init_mfc_auth = false;
|
init_mfc_auth = false;
|
||||||
}
|
}
|
||||||
if ((szRx = nfc_target_receive_bytes(dev, abtRx, sizeof(abtRx), 0)) < 0) {
|
if (!nfc_target_receive_bytes(pnd, abtRx, &szRx)) {
|
||||||
nfc_perror(dev, "nfc_target_receive_bytes");
|
nfc_perror (pnd, "nfc_target_receive_bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,37 +168,30 @@ nfc_target_emulate_tag(nfc_device *dev, nfc_target *pnt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
const char *acLibnfcVersion;
|
const char *acLibnfcVersion;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
signal(SIGINT, (void (__cdecl *)(int)) intr_hdlr);
|
signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
|
||||||
#else
|
#else
|
||||||
signal(SIGINT, intr_hdlr);
|
signal (SIGINT, (void (*)()) intr_hdlr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nfc_init(&context);
|
// Try to open the NFC reader
|
||||||
if (context == NULL) {
|
pnd = nfc_connect (NULL);
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
acLibnfcVersion = nfc_version();
|
acLibnfcVersion = nfc_version ();
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
// Try to open the NFC reader
|
|
||||||
pnd = nfc_open(context, NULL);
|
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
ERR("Unable to open NFC device");
|
ERR("Unable to connect to NFC device");
|
||||||
nfc_exit(context);
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
|
|
||||||
// Notes for ISO14443-A emulated tags:
|
// Notes for ISO14443-A emulated tags:
|
||||||
// * Only short UIDs are supported
|
// * Only short UIDs are supported
|
||||||
@ -226,7 +203,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Example of a Mifare Classic Mini
|
// Example of a Mifare Classic Mini
|
||||||
// Note that crypto1 is not implemented in this example
|
// Note that crypto1 is not implemented in this example
|
||||||
nfc_target nt = {
|
nfc_target_t nt = {
|
||||||
.nm = {
|
.nm = {
|
||||||
.nmt = NMT_ISO14443A,
|
.nmt = NMT_ISO14443A,
|
||||||
.nbr = NBR_UNDEFINED,
|
.nbr = NBR_UNDEFINED,
|
||||||
@ -241,62 +218,42 @@ main(int argc, char *argv[])
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
// Example of a FeliCa
|
// Example of a FeliCa
|
||||||
nfc_target nt = {
|
nfc_target_t nt = {
|
||||||
.nm = {
|
.nm.nmt = NMT_FELICA,
|
||||||
.nmt = NMT_FELICA,
|
.nm.nbr = NBR_UNDEFINED,
|
||||||
.nbr = NBR_UNDEFINED,
|
.nti.nfi.abtId = { 0x01, 0xFE, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
|
||||||
},
|
.nti.nfi.abtPad = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
|
||||||
.nti = {
|
.nti.nfi.abtSysCode = { 0xFF, 0xFF },
|
||||||
.nfi = {
|
|
||||||
.abtId = { 0x01, 0xFE, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
|
|
||||||
.abtPad = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
|
|
||||||
.abtSysCode = { 0xFF, 0xFF },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
// Example of a ISO14443-4 (DESfire)
|
// Example of a ISO14443-4 (DESfire)
|
||||||
nfc_target nt = {
|
nfc_target_t nt = {
|
||||||
.nm = {
|
.nm.nmt = NMT_ISO14443A,
|
||||||
.nmt = NMT_ISO14443A,
|
.nm.nbr = NBR_UNDEFINED,
|
||||||
.nbr = NBR_UNDEFINED,
|
.nti.nai.abtAtqa = { 0x03, 0x44 },
|
||||||
},
|
.nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
|
||||||
.nti = {
|
.nti.nai.btSak = 0x20,
|
||||||
.nai = {
|
.nti.nai.szUidLen = 4,
|
||||||
.abtAtqa = { 0x03, 0x44 },
|
.nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
|
||||||
.abtUid = { 0x08, 0xab, 0xcd, 0xef },
|
.nti.nai.szAtsLen = 5,
|
||||||
.btSak = 0x20,
|
|
||||||
.szUidLen = 4,
|
|
||||||
.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
|
|
||||||
.szAtsLen = 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
printf("%s will emulate this ISO14443-A tag:\n", argv[0]);
|
printf ("%s will emulate this ISO14443-A tag:\n", argv[0]);
|
||||||
print_nfc_target(&nt, true);
|
print_nfc_iso14443a_info (nt.nti.nai, true);
|
||||||
|
|
||||||
// Switch off NP_EASY_FRAMING if target is not ISO14443-4
|
// Switch off NDO_EASY_FRAMING if target is not ISO14443-4
|
||||||
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, (nt.nti.nai.btSak & SAK_ISO14443_4_COMPLIANT)) < 0) {
|
nfc_configure (pnd, NDO_EASY_FRAMING, (nt.nti.nai.btSak & SAK_ISO14443_4_COMPLIANT));
|
||||||
nfc_perror(pnd, "nfc_target_emulate_tag");
|
printf ("NFC device (configured as target) is now emulating the tag, please touch it with a second NFC device (initiator)\n");
|
||||||
nfc_close(pnd);
|
if (!nfc_target_emulate_tag (pnd, &nt)) {
|
||||||
nfc_exit(context);
|
nfc_perror (pnd, "nfc_target_emulate_tag");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
|
||||||
printf("NFC device (configured as target) is now emulating the tag, please touch it with a second NFC device (initiator)\n");
|
|
||||||
if (!nfc_target_emulate_tag(pnd, &nt)) {
|
|
||||||
nfc_perror(pnd, "nfc_target_emulate_tag");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_close(pnd);
|
nfc_disconnect(pnd);
|
||||||
nfc_exit(context);
|
exit (EXIT_SUCCESS);
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-emulate-uid 1 "June 26, 2009" "libnfc" "libnfc's examples"
|
.TH NFC-EMULATE-UID 1 "June 26, 2009"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-emulate-uid \- NFC target emulation command line tool based on libnfc
|
nfc-emulate-uid \- NFC target emulation command line tool based on libnfc
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -7,14 +7,14 @@ nfc-emulate-uid \- NFC target emulation command line tool based on libnfc
|
|||||||
.RI [ UID ]
|
.RI [ UID ]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B nfc-emulate-uid
|
.B nfc-emulate-uid
|
||||||
is a tag emulation tool that allows one to choose any tag UID. Tag emulation is one
|
is a tag emulation tool that allows to choose any tag UID. Tag emulation is one
|
||||||
of the main added features in NFC. But to avoid abuse of existing systems,
|
of the main added features in NFC. But to avoid abuse of existing systems,
|
||||||
manufacturers of the NFC controller intentionally did not support emulation of
|
manufacturers of the NFC controller intentionally did not support emulation of
|
||||||
fully customized UID but only of "random" UIDs, which always start with 0x08.
|
fully customized UID but only of "random" UIDs, which always start with 0x08.
|
||||||
The nfc-emulate-uid tool demonstrates that this can still be done using
|
The nfc-emulate-uid tool demonstrates that this can still be done using
|
||||||
transmission of raw frames, and the desired UID can be optionally specified.
|
transmission of raw frames, and the desired UID can be optionally specified.
|
||||||
|
|
||||||
This makes it a serious threat for security systems that rely only on the
|
This makes it a serious thread for security systems that rely only on the
|
||||||
uniqueness of the UID.
|
uniqueness of the UID.
|
||||||
|
|
||||||
Unfortunately, this example can't directly start in fully customisable
|
Unfortunately, this example can't directly start in fully customisable
|
||||||
@ -52,17 +52,13 @@ bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532).
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Roel Verdult <roel@libnfc.org>
|
Roel Verdult <roel@libnfc.org>
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -58,48 +52,44 @@
|
|||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
static uint8_t abtRecv[MAX_FRAME_LEN];
|
static byte_t abtRecv[MAX_FRAME_LEN];
|
||||||
static int szRecvBits;
|
static size_t szRecvBits;
|
||||||
static nfc_device *pnd;
|
static nfc_device_t *pnd;
|
||||||
static nfc_context *context;
|
|
||||||
|
|
||||||
// ISO14443A Anti-Collision response
|
// ISO14443A Anti-Collision response
|
||||||
uint8_t abtAtqa[2] = { 0x04, 0x00 };
|
byte_t abtAtqa[2] = { 0x04, 0x00 };
|
||||||
uint8_t abtUidBcc[5] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x22 };
|
byte_t abtUidBcc[5] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x62 };
|
||||||
uint8_t abtSak[9] = { 0x08, 0xb6, 0xdd };
|
byte_t abtSak[9] = { 0x08, 0xb6, 0xdd };
|
||||||
|
|
||||||
static void
|
void
|
||||||
intr_hdlr(int sig)
|
intr_hdlr (void)
|
||||||
{
|
{
|
||||||
(void) sig;
|
printf ("\nQuitting...\n");
|
||||||
if (pnd != NULL) {
|
if (pnd != NULL) {
|
||||||
printf("\nAborting current command...\n");
|
nfc_disconnect(pnd);
|
||||||
nfc_abort_command(pnd);
|
|
||||||
nfc_close(pnd);
|
|
||||||
}
|
}
|
||||||
nfc_exit(context);
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
print_usage(char *argv[])
|
print_usage (char *argv[])
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS] [UID]\n", argv[0]);
|
printf ("Usage: %s [OPTIONS] [UID]\n", argv[0]);
|
||||||
printf("Options:\n");
|
printf ("Options:\n");
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
printf("\t-q\tQuiet mode. Silent output: received and sent frames will not be shown (improves timing).\n");
|
printf ("\t-q\tQuiet mode. Silent output: received and sent frames will not be shown (improves timing).\n");
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
printf("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEEF).\n");
|
printf ("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEEF).\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
uint8_t *pbtTx = NULL;
|
byte_t *pbtTx = NULL;
|
||||||
size_t szTxBits;
|
size_t szTxBits;
|
||||||
bool quiet_output = false;
|
bool quiet_output = false;
|
||||||
|
|
||||||
@ -108,57 +98,50 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
// 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")) {
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
printf("Quiet mode.\n");
|
printf ("Quiet mode.\n");
|
||||||
quiet_output = true;
|
quiet_output = true;
|
||||||
} else if ((arg == argc - 1) && (strlen(argv[arg]) == 8)) { // See if UID was specified as HEX string
|
} else if ((arg == argc - 1) && (strlen (argv[arg]) == 8)) { // See if UID was specified as HEX string
|
||||||
uint8_t abtTmp[3] = { 0x00, 0x00, 0x00 };
|
byte_t abtTmp[3] = { 0x00, 0x00, 0x00 };
|
||||||
printf("[+] Using UID: %s\n", argv[arg]);
|
printf ("[+] Using UID: %s\n", argv[arg]);
|
||||||
abtUidBcc[4] = 0x00;
|
abtUidBcc[4] = 0x00;
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
memcpy(abtTmp, argv[arg] + i * 2, 2);
|
memcpy (abtTmp, argv[arg] + i * 2, 2);
|
||||||
abtUidBcc[i] = (uint8_t) strtol((char *) abtTmp, NULL, 16);
|
abtUidBcc[i] = (byte_t) strtol ((char *) abtTmp, NULL, 16);
|
||||||
abtUidBcc[4] ^= abtUidBcc[i];
|
abtUidBcc[4] ^= abtUidBcc[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
signal(SIGINT, (void (__cdecl *)(int)) intr_hdlr);
|
signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
|
||||||
#else
|
#else
|
||||||
signal(SIGINT, intr_hdlr);
|
signal (SIGINT, (void (*)()) intr_hdlr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to open the NFC device
|
// Try to open the NFC device
|
||||||
pnd = nfc_open(context, NULL);
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
ERR("Unable to open NFC device");
|
printf ("Unable to connect to NFC device\n");
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
printf("[+] Try to break out the auto-emulation, this requires a second NFC device!\n");
|
printf ("[+] Try to break out the auto-emulation, this requires a second NFC device!\n");
|
||||||
printf("[+] To do this, please send any command after the anti-collision\n");
|
printf ("[+] To do this, please send any command after the anti-collision\n");
|
||||||
printf("[+] For example, send a RATS command or use the \"nfc-anticol\" or \"nfc-list\" tool.\n");
|
printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" or \"nfc-list\" tool.\n");
|
||||||
|
|
||||||
// Note: We have to build a "fake" nfc_target in order to do exactly the same that was done before the new nfc_target_init() was introduced.
|
// Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
|
||||||
nfc_target nt = {
|
nfc_target_t nt = {
|
||||||
.nm = {
|
.nm = {
|
||||||
.nmt = NMT_ISO14443A,
|
.nmt = NMT_ISO14443A,
|
||||||
.nbr = NBR_UNDEFINED,
|
.nbr = NBR_UNDEFINED,
|
||||||
@ -173,71 +156,68 @@ main(int argc, char *argv[])
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if ((szRecvBits = nfc_target_init(pnd, &nt, abtRecv, sizeof(abtRecv), 0)) < 0) {
|
if (!nfc_target_init (pnd, &nt, abtRecv, &szRecvBits)) {
|
||||||
nfc_perror(pnd, "nfc_target_init");
|
nfc_perror (pnd, "nfc_target_init");
|
||||||
ERR("Could not come out of auto-emulation, no command was received");
|
ERR ("Could not come out of auto-emulation, no command was received");
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
printf("[+] Received initiator command: ");
|
printf ("[+] Received initiator command: ");
|
||||||
print_hex_bits(abtRecv, (size_t) szRecvBits);
|
print_hex_bits (abtRecv, szRecvBits);
|
||||||
printf("[+] Configuring communication\n");
|
printf ("[+] Configuring communication\n");
|
||||||
if ((nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) || (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true) < 0)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, false) || !nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
nfc_close(pnd);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
printf("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n", abtUidBcc[0], abtUidBcc[1],
|
printf ("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n", abtUidBcc[0], abtUidBcc[1],
|
||||||
abtUidBcc[2], abtUidBcc[3]);
|
abtUidBcc[2], abtUidBcc[3]);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Test if we received a frame
|
// Test if we received a frame
|
||||||
if ((szRecvBits = nfc_target_receive_bits(pnd, abtRecv, sizeof(abtRecv), 0)) > 0) {
|
if (nfc_target_receive_bits (pnd, abtRecv, &szRecvBits, NULL)) {
|
||||||
// Prepare the command to send back for the anti-collision request
|
// Prepare the command to send back for the anti-collision request
|
||||||
switch (szRecvBits) {
|
switch (szRecvBits) {
|
||||||
case 7: // Request or Wakeup
|
case 7: // Request or Wakeup
|
||||||
pbtTx = abtAtqa;
|
pbtTx = abtAtqa;
|
||||||
szTxBits = 16;
|
szTxBits = 16;
|
||||||
// New anti-collsion session started
|
// New anti-collsion session started
|
||||||
if (!quiet_output)
|
if (!quiet_output)
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16: // Select All
|
case 16: // Select All
|
||||||
pbtTx = abtUidBcc;
|
pbtTx = abtUidBcc;
|
||||||
szTxBits = 40;
|
szTxBits = 40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 72: // Select Tag
|
case 72: // Select Tag
|
||||||
pbtTx = abtSak;
|
pbtTx = abtSak;
|
||||||
szTxBits = 24;
|
szTxBits = 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // unknown length?
|
default: // unknown length?
|
||||||
szTxBits = 0;
|
szTxBits = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("R: ");
|
printf ("R: ");
|
||||||
print_hex_bits(abtRecv, (size_t) szRecvBits);
|
print_hex_bits (abtRecv, szRecvBits);
|
||||||
}
|
}
|
||||||
// Test if we know how to respond
|
// Test if we know how to respond
|
||||||
if (szTxBits) {
|
if (szTxBits) {
|
||||||
// Send and print the command to the screen
|
// Send and print the command to the screen
|
||||||
if (nfc_target_send_bits(pnd, pbtTx, szTxBits, NULL) < 0) {
|
if (!nfc_target_send_bits (pnd, pbtTx, szTxBits, NULL)) {
|
||||||
nfc_perror(pnd, "nfc_target_send_bits");
|
nfc_perror (pnd, "nfc_target_send_bits");
|
||||||
nfc_close(pnd);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("T: ");
|
printf ("T: ");
|
||||||
print_hex_bits(pbtTx, szTxBits);
|
print_hex_bits (pbtTx, szTxBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
44
examples/nfc-list.1
Normal file
44
examples/nfc-list.1
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
.TH NFC-LIST 1 "June 26, 2009"
|
||||||
|
.SH NAME
|
||||||
|
nfc-list \- List NFC targets
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B nfc-list
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B nfc-list
|
||||||
|
is a utility for listing any available tags like ISO14443-A, FeliCa, Jewel
|
||||||
|
or ISO14443-B (according to the device capabilities).
|
||||||
|
It may detect several tags at once thanks to a mechanism called anti-collision
|
||||||
|
but all types of tags don't support anti-collision and there is some physical
|
||||||
|
limitation of the number of tags the reader can discover.
|
||||||
|
|
||||||
|
This tool displays all available information at selection time.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
\fB-v\fP, \fB--verbose\fP
|
||||||
|
Verbose mode
|
||||||
|
Tries to interpret data
|
||||||
|
|
||||||
|
.SH EXAMPLE
|
||||||
|
For an ISO/IEC 14443-A tag (i.e.Mifare DESFire):
|
||||||
|
|
||||||
|
ATQA (SENS_RES): 03 44
|
||||||
|
UID (NFCID1): 04 45 35 01 db 24 80
|
||||||
|
SAK (SEL_RES): 20
|
||||||
|
ATS (ATR): 75 77 81 02 80
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
Please report any bugs on the
|
||||||
|
.B libnfc
|
||||||
|
forum at
|
||||||
|
.BR http://www.libnfc.org/community/ "."
|
||||||
|
.SH LICENCE
|
||||||
|
.B libnfc
|
||||||
|
and
|
||||||
|
.B libnfc-examples
|
||||||
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
|
.SH AUTHORS
|
||||||
|
Roel Verdult <roel@libnfc.org>
|
||||||
|
Romuald Conty <romuald@libnfc.org>
|
||||||
|
.PP
|
||||||
|
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
||||||
|
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||||
206
examples/nfc-list.c
Normal file
206
examples/nfc-list.c
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
|
*
|
||||||
|
* 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-list.c
|
||||||
|
* @brief Lists the first target present of each founded device
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
# ifdef DEBUG
|
||||||
|
# include <sys/param.h>
|
||||||
|
# include <usb.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
|
#define MAX_DEVICE_COUNT 16
|
||||||
|
#define MAX_TARGET_COUNT 16
|
||||||
|
|
||||||
|
static nfc_device_t *pnd;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
const char *acLibnfcVersion;
|
||||||
|
size_t szDeviceFound;
|
||||||
|
size_t szTargetFound;
|
||||||
|
size_t i;
|
||||||
|
bool verbose = false;
|
||||||
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
|
||||||
|
// Display libnfc version
|
||||||
|
acLibnfcVersion = nfc_version ();
|
||||||
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
|
pnddDevices = parse_args (argc, argv, &szDeviceFound, &verbose);
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
# ifdef DEBUG
|
||||||
|
usb_set_debug (4);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Lazy way to open an NFC device */
|
||||||
|
#if 0
|
||||||
|
pnd = nfc_connect (NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0 */
|
||||||
|
#if 0
|
||||||
|
nfc_device_desc_t ndd;
|
||||||
|
ndd.pcDriver = "ARYGON";
|
||||||
|
ndd.pcPort = "/dev/ttyUSB0";
|
||||||
|
ndd.uiSpeed = 115200;
|
||||||
|
pnd = nfc_connect (&ndd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If specific device is wanted, i.e. a SCL3711 on USB */
|
||||||
|
#if 0
|
||||||
|
nfc_device_desc_t ndd;
|
||||||
|
ndd.pcDriver = "PN533_USB";
|
||||||
|
strcpy(ndd.acDevice, "SCM Micro / SCL3711-NFC&RW");
|
||||||
|
pnd = nfc_connect (&ndd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (szDeviceFound == 0) {
|
||||||
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
|
fprintf (stderr, "malloc() failed\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (szDeviceFound == 0) {
|
||||||
|
printf ("No NFC device found.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < szDeviceFound; i++) {
|
||||||
|
nfc_target_t ant[MAX_TARGET_COUNT];
|
||||||
|
pnd = nfc_connect (&(pnddDevices[i]));
|
||||||
|
|
||||||
|
if (pnd == NULL) {
|
||||||
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
|
|
||||||
|
// List ISO14443A targets
|
||||||
|
nfc_modulation_t nm = {
|
||||||
|
.nmt = NMT_ISO14443A,
|
||||||
|
.nbr = NBR_106,
|
||||||
|
};
|
||||||
|
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
|
size_t n;
|
||||||
|
if (verbose || (szTargetFound > 0)) {
|
||||||
|
printf ("%d ISO14443A passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
|
||||||
|
}
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
|
print_nfc_iso14443a_info (ant[n].nti.nai, verbose);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm.nmt = NMT_FELICA;
|
||||||
|
nm.nbr = NBR_212;
|
||||||
|
// List Felica tags
|
||||||
|
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
|
size_t n;
|
||||||
|
if (verbose || (szTargetFound > 0)) {
|
||||||
|
printf ("%d Felica (212 kbps) passive target(s) found%s\n", (int) szTargetFound,
|
||||||
|
(szTargetFound == 0) ? ".\n" : ":");
|
||||||
|
}
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
|
print_nfc_felica_info (ant[n].nti.nfi, verbose);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm.nbr = NBR_424;
|
||||||
|
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
|
size_t n;
|
||||||
|
if (verbose || (szTargetFound > 0)) {
|
||||||
|
printf ("%d Felica (424 kbps) passive target(s) found%s\n", (int) szTargetFound,
|
||||||
|
(szTargetFound == 0) ? ".\n" : ":");
|
||||||
|
}
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
|
print_nfc_felica_info (ant[n].nti.nfi, verbose);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm.nmt = NMT_ISO14443B;
|
||||||
|
nm.nbr = NBR_106;
|
||||||
|
// List ISO14443B targets
|
||||||
|
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
|
size_t n;
|
||||||
|
if (verbose || (szTargetFound > 0)) {
|
||||||
|
printf ("%d ISO14443B passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
|
||||||
|
}
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
|
print_nfc_iso14443b_info (ant[n].nti.nbi, verbose);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm.nmt = NMT_JEWEL;
|
||||||
|
nm.nbr = NBR_106;
|
||||||
|
// List Jewel targets
|
||||||
|
if (nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound )) {
|
||||||
|
size_t n;
|
||||||
|
if (verbose || (szTargetFound > 0)) {
|
||||||
|
printf("%d Jewel passive target(s) found%s\n", (int)szTargetFound, (szTargetFound==0)?".\n":":");
|
||||||
|
}
|
||||||
|
for(n=0; n<szTargetFound; n++) {
|
||||||
|
print_nfc_jewel_info (ant[n].nti.nji, verbose);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (pnddDevices);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
64
examples/nfc-mfclassic.1
Normal file
64
examples/nfc-mfclassic.1
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
.TH NFC-MFCLASSIC 1 "Nov 02, 2009"
|
||||||
|
.SH NAME
|
||||||
|
nfc-mfclassic \- MIFARE Classic command line tool
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B nfc-mfclassic
|
||||||
|
.RI \fR\fBr\fR|\fBw\fR
|
||||||
|
.RI \fR\fBa\fR|\fBb\fR
|
||||||
|
.IR DUMP
|
||||||
|
.IR [KEYS]
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B nfc-mfclassic
|
||||||
|
is a MIFARE Classic tool that allow to read or write
|
||||||
|
.IR DUMP
|
||||||
|
file using Mifare keys provided in
|
||||||
|
.IR KEYS
|
||||||
|
file.
|
||||||
|
|
||||||
|
MIFARE Classic tag is one of the most widely used RFID tags.
|
||||||
|
|
||||||
|
The firmware in the NFC controller supports authenticating, reading and writing
|
||||||
|
to/from Mifare Classic tags. This tool demonstrates the speed of this library
|
||||||
|
and its ease-of-use. It's possible to read and write the complete content of a
|
||||||
|
Mifare Classic 4KB tag within 1 second. It uses a binary Mifare Dump file (MFD)
|
||||||
|
to store the keys and data for all sectors.
|
||||||
|
|
||||||
|
Be cautious that some parts of a Mifare Classic memory are used for r/w access
|
||||||
|
of the rest of the memory, so please read the tag documentation before experimenting too much!
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.BR r " | " w
|
||||||
|
Perform read from (
|
||||||
|
.B r
|
||||||
|
) or write to (
|
||||||
|
.B w
|
||||||
|
) card.
|
||||||
|
.TP
|
||||||
|
.BR a " | " b
|
||||||
|
Use A or B Mifare keys.
|
||||||
|
.TP
|
||||||
|
.IR DUMP
|
||||||
|
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
|
||||||
|
.TP
|
||||||
|
.IR KEYS
|
||||||
|
MiFare Dump (MFD) that contains the keys (optional). Data part of the dump is ignored.
|
||||||
|
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
Please report any bugs on the
|
||||||
|
.B libnfc
|
||||||
|
forum at
|
||||||
|
.BR http://www.libnfc.org/community/ "."
|
||||||
|
.SH LICENCE
|
||||||
|
.B libnfc
|
||||||
|
and
|
||||||
|
.B libnfc-examples
|
||||||
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
|
.SH AUTHORS
|
||||||
|
Roel Verdult <roel@libnfc.org>
|
||||||
|
Romuald Conty <romuald@libnfc.org>
|
||||||
|
Romain Tartière <romain@blogreen.org>
|
||||||
|
.PP
|
||||||
|
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
||||||
|
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||||
564
examples/nfc-mfclassic.c
Normal file
564
examples/nfc-mfclassic.c
Normal file
@ -0,0 +1,564 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
|
*
|
||||||
|
* 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-mfclassic.c
|
||||||
|
* @brief MIFARE Classic manipulation example
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
#include "mifare.h"
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
|
static nfc_device_t *pnd;
|
||||||
|
static nfc_target_t nt;
|
||||||
|
static mifare_param mp;
|
||||||
|
static mifare_classic_tag mtKeys;
|
||||||
|
static mifare_classic_tag mtDump;
|
||||||
|
static bool bUseKeyA;
|
||||||
|
static bool bUseKeyFile;
|
||||||
|
static uint8_t uiBlocks;
|
||||||
|
static byte_t keys[] = {
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7,
|
||||||
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||||
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
|
||||||
|
0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd,
|
||||||
|
0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a,
|
||||||
|
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
|
||||||
|
};
|
||||||
|
|
||||||
|
static const nfc_modulation_t nmMifare = {
|
||||||
|
.nmt = NMT_ISO14443A,
|
||||||
|
.nbr = NBR_106,
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t num_keys = sizeof (keys) / 6;
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_success_or_failure (bool bFailure, uint32_t * uiBlockCounter)
|
||||||
|
{
|
||||||
|
printf ("%c", (bFailure) ? 'x' : '.');
|
||||||
|
if (uiBlockCounter && !bFailure)
|
||||||
|
*uiBlockCounter += (*uiBlockCounter < 128) ? 4 : 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_first_block (uint32_t uiBlock)
|
||||||
|
{
|
||||||
|
// Test if we are in the small or big sectors
|
||||||
|
if (uiBlock < 128)
|
||||||
|
return ((uiBlock) % 4 == 0);
|
||||||
|
else
|
||||||
|
return ((uiBlock) % 16 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_trailer_block (uint32_t uiBlock)
|
||||||
|
{
|
||||||
|
// Test if we are in the small or big sectors
|
||||||
|
if (uiBlock < 128)
|
||||||
|
return ((uiBlock + 1) % 4 == 0);
|
||||||
|
else
|
||||||
|
return ((uiBlock + 1) % 16 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
get_trailer_block (uint32_t uiFirstBlock)
|
||||||
|
{
|
||||||
|
// Test if we are in the small or big sectors
|
||||||
|
uint32_t trailer_block = 0;
|
||||||
|
if (uiFirstBlock < 128) {
|
||||||
|
trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
|
||||||
|
} else {
|
||||||
|
trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
|
||||||
|
}
|
||||||
|
return trailer_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
authenticate (uint32_t uiBlock)
|
||||||
|
{
|
||||||
|
mifare_cmd mc;
|
||||||
|
uint32_t uiTrailerBlock;
|
||||||
|
size_t key_index;
|
||||||
|
|
||||||
|
// Key file authentication.
|
||||||
|
if (bUseKeyFile) {
|
||||||
|
// Set the authentication information (uid)
|
||||||
|
memcpy (mp.mpa.abtUid, nt.nti.nai.abtUid, 4);
|
||||||
|
|
||||||
|
// Locate the trailer (with the keys) used for this sector
|
||||||
|
uiTrailerBlock = get_trailer_block (uiBlock);
|
||||||
|
|
||||||
|
// Determin if we should use the a or the b key
|
||||||
|
if (bUseKeyA) {
|
||||||
|
mc = MC_AUTH_A;
|
||||||
|
memcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6);
|
||||||
|
} else {
|
||||||
|
mc = MC_AUTH_B;
|
||||||
|
memcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Auto authentication.
|
||||||
|
else {
|
||||||
|
// Determin if we should use the a or the b key
|
||||||
|
mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
|
||||||
|
|
||||||
|
// Set the authentication information (uid)
|
||||||
|
memcpy (mp.mpa.abtUid, nt.nti.nai.abtUid, 4);
|
||||||
|
|
||||||
|
for (key_index = 0; key_index < num_keys; key_index++) {
|
||||||
|
memcpy (mp.mpa.abtKey, keys + (key_index * 6), 6);
|
||||||
|
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp)) {
|
||||||
|
if (bUseKeyA)
|
||||||
|
memcpy (mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
|
||||||
|
else
|
||||||
|
memcpy (mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_initiator_select_passive_target (pnd, nmMifare, mp.mpa.abtUid, 4, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
read_card (void)
|
||||||
|
{
|
||||||
|
int32_t iBlock;
|
||||||
|
bool bFailure = false;
|
||||||
|
uint32_t uiReadBlocks = 0;
|
||||||
|
|
||||||
|
printf ("Reading out %d blocks |", uiBlocks + 1);
|
||||||
|
|
||||||
|
// Read the card from end to begin
|
||||||
|
for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
|
||||||
|
// Authenticate everytime we reach a trailer block
|
||||||
|
if (is_trailer_block (iBlock)) {
|
||||||
|
// Skip this the first time, bFailure it means nothing (yet)
|
||||||
|
if (iBlock != uiBlocks)
|
||||||
|
print_success_or_failure (bFailure, &uiReadBlocks);
|
||||||
|
|
||||||
|
// Show if the readout went well
|
||||||
|
if (bFailure) {
|
||||||
|
// When a failure occured we need to redo the anti-collision
|
||||||
|
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
|
||||||
|
printf ("!\nError: tag was removed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bFailure = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush (stdout);
|
||||||
|
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (!authenticate (iBlock)) {
|
||||||
|
printf ("!\nError: authentication failed for block 0x%02x\n", iBlock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Try to read out the trailer
|
||||||
|
if (nfc_initiator_mifare_cmd (pnd, MC_READ, iBlock, &mp)) {
|
||||||
|
// 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, 6);
|
||||||
|
memcpy (mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);
|
||||||
|
memcpy (mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
|
||||||
|
} else {
|
||||||
|
printf ("!\nError: unable to read trailer block 0x%02x\n", iBlock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Make sure a earlier readout did not fail
|
||||||
|
if (!bFailure) {
|
||||||
|
// Try to read out the data block
|
||||||
|
if (nfc_initiator_mifare_cmd (pnd, MC_READ, iBlock, &mp)) {
|
||||||
|
memcpy (mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
|
||||||
|
} else {
|
||||||
|
bFailure = true;
|
||||||
|
printf ("!\nError: unable to read block 0x%02x\n", iBlock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_success_or_failure (bFailure, &uiReadBlocks);
|
||||||
|
printf ("|\n");
|
||||||
|
printf ("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
|
||||||
|
fflush (stdout);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
write_card (void)
|
||||||
|
{
|
||||||
|
uint32_t uiBlock;
|
||||||
|
bool bFailure = false;
|
||||||
|
uint32_t uiWriteBlocks = 0;
|
||||||
|
|
||||||
|
printf ("Writing %d blocks |", uiBlocks + 1);
|
||||||
|
|
||||||
|
// Write the card from begin to end;
|
||||||
|
for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
|
||||||
|
// Authenticate everytime we reach the first sector of a new block
|
||||||
|
if (is_first_block (uiBlock)) {
|
||||||
|
// Skip this the first time, bFailure it means nothing (yet)
|
||||||
|
if (uiBlock != 0)
|
||||||
|
print_success_or_failure (bFailure, &uiWriteBlocks);
|
||||||
|
|
||||||
|
// Show if the readout went well
|
||||||
|
if (bFailure) {
|
||||||
|
// When a failure occured we need to redo the anti-collision
|
||||||
|
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
|
||||||
|
printf ("!\nError: tag was removed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bFailure = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush (stdout);
|
||||||
|
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (!authenticate (uiBlock)) {
|
||||||
|
printf ("!\nError: authentication failed for block %02x\n", uiBlock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_trailer_block (uiBlock)) {
|
||||||
|
// Copy the keys over from our key dump and store the retrieved access bits
|
||||||
|
memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6);
|
||||||
|
memcpy (mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4);
|
||||||
|
memcpy (mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6);
|
||||||
|
|
||||||
|
// Try to write the trailer
|
||||||
|
if (nfc_initiator_mifare_cmd (pnd, MC_WRITE, uiBlock, &mp) == false) {
|
||||||
|
printf ("failed to write trailer block %d \n", uiBlock);
|
||||||
|
bFailure = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The first block 0x00 is read only, skip this
|
||||||
|
if (uiBlock == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Make sure a earlier write did not fail
|
||||||
|
if (!bFailure) {
|
||||||
|
// Try to write the data block
|
||||||
|
memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16);
|
||||||
|
if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, uiBlock, &mp))
|
||||||
|
bFailure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_success_or_failure (bFailure, &uiWriteBlocks);
|
||||||
|
printf ("|\n");
|
||||||
|
printf ("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
||||||
|
fflush (stdout);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mifare_classic_extract_payload (const char *abDump, char *pbPayload)
|
||||||
|
{
|
||||||
|
uint8_t uiSectorIndex;
|
||||||
|
uint8_t uiBlockIndex;
|
||||||
|
size_t szDumpOffset;
|
||||||
|
size_t szPayloadIndex = 0;
|
||||||
|
|
||||||
|
for (uiSectorIndex = 1; uiSectorIndex < 16; uiSectorIndex++) {
|
||||||
|
for (uiBlockIndex = 0; uiBlockIndex < 3; uiBlockIndex++) {
|
||||||
|
szDumpOffset = uiSectorIndex * 16 * 4 + uiBlockIndex * 16;
|
||||||
|
// for(uint8_t uiByteIndex=0; uiByteIndex<16; uiByteIndex++) printf("%02x ", abDump[szPayloadIndex+uiByteIndex]);
|
||||||
|
memcpy (pbPayload + szPayloadIndex, abDump + szDumpOffset, 16);
|
||||||
|
szPayloadIndex += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ACTION_READ,
|
||||||
|
ACTION_WRITE,
|
||||||
|
ACTION_EXTRACT,
|
||||||
|
ACTION_USAGE
|
||||||
|
} action_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage (const char *pcProgramName)
|
||||||
|
{
|
||||||
|
printf ("Usage: ");
|
||||||
|
printf ("%s r|w a|b <dump.mfd> [<keys.mfd>]\n", pcProgramName);
|
||||||
|
printf (" r|w - Perform read from (r) or write to (w) card\n");
|
||||||
|
printf (" a|b - Use A or B keys for action\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 ("Or: ");
|
||||||
|
printf ("%s x <dump.mfd> <payload.bin>\n", pcProgramName);
|
||||||
|
printf (" x - Extract payload (data blocks) from MFD\n");
|
||||||
|
printf (" <dump.mfd> - MiFare Dump (MFD) that contains wanted payload\n");
|
||||||
|
printf (" <payload.bin> - Binary file where payload will be extracted\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
bool b4K;
|
||||||
|
action_t atAction = ACTION_USAGE;
|
||||||
|
byte_t *pbtUID;
|
||||||
|
FILE *pfKeys = NULL;
|
||||||
|
FILE *pfDump = NULL;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
print_usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
const char *command = argv[1];
|
||||||
|
|
||||||
|
if (strcmp (command, "r") == 0) {
|
||||||
|
if (argc < 4) {
|
||||||
|
print_usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
atAction = ACTION_READ;
|
||||||
|
bUseKeyA = tolower ((int) ((unsigned char) *(argv[2]))) == 'a';
|
||||||
|
bUseKeyFile = (argc > 4);
|
||||||
|
} else if (strcmp (command, "w") == 0) {
|
||||||
|
if (argc < 4) {
|
||||||
|
print_usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
atAction = ACTION_WRITE;
|
||||||
|
bUseKeyA = tolower ((int) ((unsigned char) *(argv[2]))) == 'a';
|
||||||
|
bUseKeyFile = (argc > 4);
|
||||||
|
} else if (strcmp (command, "x") == 0) {
|
||||||
|
if (argc < 4) {
|
||||||
|
print_usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
atAction = ACTION_EXTRACT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (atAction) {
|
||||||
|
case ACTION_USAGE:
|
||||||
|
print_usage (argv[0]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
case ACTION_READ:
|
||||||
|
case ACTION_WRITE:
|
||||||
|
if (bUseKeyFile) {
|
||||||
|
pfKeys = fopen (argv[4], "rb");
|
||||||
|
if (pfKeys == NULL) {
|
||||||
|
printf ("Could not open keys file: %s\n", argv[4]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (fread (&mtKeys, 1, sizeof (mtKeys), pfKeys) != sizeof (mtKeys)) {
|
||||||
|
printf ("Could not read keys file: %s\n", argv[4]);
|
||||||
|
fclose (pfKeys);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
fclose (pfKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atAction == ACTION_READ) {
|
||||||
|
memset (&mtDump, 0x00, sizeof (mtDump));
|
||||||
|
} else {
|
||||||
|
pfDump = fopen (argv[3], "rb");
|
||||||
|
|
||||||
|
if (pfDump == NULL) {
|
||||||
|
printf ("Could not open dump file: %s\n", argv[3]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
|
||||||
|
printf ("Could not read dump file: %s\n", argv[3]);
|
||||||
|
fclose (pfDump);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
fclose (pfDump);
|
||||||
|
}
|
||||||
|
// printf("Successfully opened required files\n");
|
||||||
|
|
||||||
|
// Try to open the NFC reader
|
||||||
|
pnd = nfc_connect (NULL);
|
||||||
|
if (pnd == NULL) {
|
||||||
|
printf ("Error connecting NFC reader\n");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
|
// Drop the field for a while
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Let the reader only try once to find a tag
|
||||||
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Enable field so more power consuming cards can power themselves up
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
|
||||||
|
nfc_configure (pnd, NDO_AUTO_ISO14443_4, false);
|
||||||
|
|
||||||
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
|
// Try to find a MIFARE Classic tag
|
||||||
|
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
|
||||||
|
printf ("Error: no tag was found\n");
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Test if we are dealing with a MIFARE compatible tag
|
||||||
|
if ((nt.nti.nai.btSak & 0x08) == 0) {
|
||||||
|
printf ("Error: tag is not a MIFARE Classic card\n");
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bUseKeyFile) {
|
||||||
|
// Get the info from the key dump
|
||||||
|
b4K = (mtKeys.amb[0].mbm.abtATQA[1] == 0x02);
|
||||||
|
pbtUID = mtKeys.amb[0].mbm.abtUID;
|
||||||
|
|
||||||
|
// Compare if key dump UID is the same as the current tag UID
|
||||||
|
if (memcmp (nt.nti.nai.abtUid, pbtUID, 4) != 0) {
|
||||||
|
printf ("Expected MIFARE Classic %ck card with UID: %02x%02x%02x%02x\n", b4K ? '4' : '1', pbtUID[0], pbtUID[1],
|
||||||
|
pbtUID[2], pbtUID[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get the info from the current tag
|
||||||
|
pbtUID = nt.nti.nai.abtUid;
|
||||||
|
b4K = (nt.nti.nai.abtAtqa[1] == 0x02);
|
||||||
|
printf ("Found MIFARE Classic %ck card:\n", b4K ? '4' : '1');
|
||||||
|
print_nfc_iso14443a_info (nt.nti.nai, false);
|
||||||
|
|
||||||
|
uiBlocks = (b4K) ? 0xff : 0x3f;
|
||||||
|
|
||||||
|
if (atAction == ACTION_READ) {
|
||||||
|
if (read_card ()) {
|
||||||
|
printf ("Writing data to file: %s ...", argv[3]);
|
||||||
|
fflush (stdout);
|
||||||
|
pfDump = fopen (argv[3], "wb");
|
||||||
|
if (pfDump == NULL) {
|
||||||
|
printf ("Could not open dump file: %s\n", argv[3]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (fwrite (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
|
||||||
|
printf ("\nCould not write to file: %s\n", argv[3]);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf ("Done.\n");
|
||||||
|
fclose (pfDump);
|
||||||
|
}
|
||||||
|
} else if (atAction == ACTION_WRITE) {
|
||||||
|
write_card ();
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION_EXTRACT:{
|
||||||
|
const char *pcDump = argv[2];
|
||||||
|
const char *pcPayload = argv[3];
|
||||||
|
|
||||||
|
FILE *pfDump = NULL;
|
||||||
|
FILE *pfPayload = NULL;
|
||||||
|
|
||||||
|
char abDump[4096];
|
||||||
|
char abPayload[4096];
|
||||||
|
|
||||||
|
pfDump = fopen (pcDump, "rb");
|
||||||
|
|
||||||
|
if (pfDump == NULL) {
|
||||||
|
printf ("Could not open dump file: %s\n", pcDump);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread (abDump, 1, sizeof (abDump), pfDump) != sizeof (abDump)) {
|
||||||
|
printf ("Could not read dump file: %s\n", pcDump);
|
||||||
|
fclose (pfDump);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
fclose (pfDump);
|
||||||
|
|
||||||
|
mifare_classic_extract_payload (abDump, abPayload);
|
||||||
|
|
||||||
|
printf ("Writing data to file: %s\n", pcPayload);
|
||||||
|
pfPayload = fopen (pcPayload, "wb");
|
||||||
|
if (pfPayload == NULL) {
|
||||||
|
printf ("Could not open file %s for writting.\n", pcPayload);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (fwrite (abPayload, 1, sizeof (abPayload), pfPayload) != sizeof (abPayload)) {
|
||||||
|
printf ("Could not write to file: %s\n", pcPayload);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
fclose (pfPayload);
|
||||||
|
printf ("Done, all bytes have been extracted!\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
@ -1,40 +0,0 @@
|
|||||||
.TH nfc-mfsetuid 1 "Sep 05, 2011" "libnfc" "NFC Utilities"
|
|
||||||
.SH NAME
|
|
||||||
nfc-mfsetuid \- MIFARE 1K special card UID setting and recovery tool
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B nfc-mfsetuid
|
|
||||||
[
|
|
||||||
.I UID
|
|
||||||
]
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B nfc-mfsetuid
|
|
||||||
is a MIFARE tool that allows setting of UID on special versions (Chinese clones) of Mifare 1K cards. It will also recover
|
|
||||||
damaged cards that have had invalid data written to block 0 (e.g. wrong BCC). Currently only 4 Byte UID is supported.
|
|
||||||
Specify an eight hex character UID or leave blank for the default '01234567'.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
.B -f
|
|
||||||
Format. Wipe all data (set to 0xFF) and reset ACLs to defaults.
|
|
||||||
|
|
||||||
.B -q
|
|
||||||
Quiet. Suppress output of commands and responses.
|
|
||||||
.SH BUGS
|
|
||||||
Please report any bugs on the
|
|
||||||
.B libnfc
|
|
||||||
issue tracker at:
|
|
||||||
.br
|
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
|
||||||
.B libnfc
|
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
|
||||||
.B libnfc-examples
|
|
||||||
are covered by the the BSD 2-Clause license.
|
|
||||||
.SH AUTHORS
|
|
||||||
Adam Laurie <adam@algroup.co.uk>
|
|
||||||
.PP
|
|
||||||
This manual page was written by Adam Laurie <adam@algroup.co.uk>.
|
|
||||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
|
||||||
@ -1,399 +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:
|
|
||||||
* Copyright (C) 2011 Adam Laurie
|
|
||||||
* Copyright (C) 2014 Dario Carluccio
|
|
||||||
*
|
|
||||||
* 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-mfsetuid.c
|
|
||||||
* @brief Set UID of special Mifare cards
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* based on nfc-anticol.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
|
||||||
|
|
||||||
#define SAK_FLAG_ATS_SUPPORTED 0x20
|
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
|
||||||
|
|
||||||
static uint8_t abtRx[MAX_FRAME_LEN];
|
|
||||||
static int szRxBits;
|
|
||||||
static uint8_t abtRawUid[12];
|
|
||||||
static uint8_t abtAtqa[2];
|
|
||||||
static uint8_t abtSak;
|
|
||||||
static uint8_t abtAts[MAX_FRAME_LEN];
|
|
||||||
static uint8_t szAts = 0;
|
|
||||||
static size_t szCL = 1;//Always start with Cascade Level 1 (CL1)
|
|
||||||
static nfc_device *pnd;
|
|
||||||
|
|
||||||
bool quiet_output = false;
|
|
||||||
bool iso_ats_supported = false;
|
|
||||||
|
|
||||||
// ISO14443A Anti-Collision Commands
|
|
||||||
uint8_t abtReqa[1] = { 0x26 };
|
|
||||||
uint8_t abtSelectAll[2] = { 0x93, 0x20 };
|
|
||||||
uint8_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
||||||
uint8_t abtRats[4] = { 0xe0, 0x50, 0x00, 0x00 };
|
|
||||||
uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
|
|
||||||
#define CASCADE_BIT 0x04
|
|
||||||
|
|
||||||
// special unlock command
|
|
||||||
uint8_t abtUnlock1[1] = { 0x40 };
|
|
||||||
uint8_t abtUnlock2[1] = { 0x43 };
|
|
||||||
uint8_t abtWipe[1] = { 0x41 };
|
|
||||||
uint8_t abtWrite[4] = { 0xa0, 0x00, 0x5f, 0xb1 };
|
|
||||||
uint8_t abtData[18] = { 0x01, 0x23, 0x45, 0x67, 0x00, 0x08, 0x04, 0x00, 0x46, 0x59, 0x25, 0x58, 0x49, 0x10, 0x23, 0x02, 0x23, 0xeb };
|
|
||||||
uint8_t abtBlank[18] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0xCC };
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
|
|
||||||
{
|
|
||||||
// Show transmitted command
|
|
||||||
if (!quiet_output) {
|
|
||||||
printf("Sent bits: ");
|
|
||||||
print_hex_bits(pbtTx, szTxBits);
|
|
||||||
}
|
|
||||||
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
|
||||||
if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Show received answer
|
|
||||||
if (!quiet_output) {
|
|
||||||
printf("Received bits: ");
|
|
||||||
print_hex_bits(abtRx, szRxBits);
|
|
||||||
}
|
|
||||||
// Succesful transfer
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
|
|
||||||
{
|
|
||||||
// Show transmitted command
|
|
||||||
if (!quiet_output) {
|
|
||||||
printf("Sent bits: ");
|
|
||||||
print_hex(pbtTx, szTx);
|
|
||||||
}
|
|
||||||
int res;
|
|
||||||
// Transmit the command bytes
|
|
||||||
if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Show received answer
|
|
||||||
if (!quiet_output) {
|
|
||||||
printf("Received bits: ");
|
|
||||||
print_hex(abtRx, res);
|
|
||||||
}
|
|
||||||
// Succesful transfer
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_usage(char *argv[])
|
|
||||||
{
|
|
||||||
printf("Usage: %s [OPTIONS] [UID|BLOCK0]\n", argv[0]);
|
|
||||||
printf("Options:\n");
|
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
|
||||||
printf("\t-f\tFormat. Delete all data (set to 0xFF) and reset ACLs to default.\n");
|
|
||||||
printf("\t-q\tQuiet mode. Suppress output of READER and CARD data (improves timing).\n");
|
|
||||||
printf("\n\tSpecify UID (4 HEX bytes) to set UID, or leave blank for default '01234567'.\n");
|
|
||||||
printf("\n\tSpecify BLOCK0 (16 HEX bytes) to set content of Block0. CRC (Byte 4) is recalculated an overwritten'.\n");
|
|
||||||
printf("\tThis utility can be used to recover cards that have been damaged by writing bad\n");
|
|
||||||
printf("\tdata (e.g. wrong BCC), thus making them non-selectable by most tools/readers.\n");
|
|
||||||
printf("\n\t*** Note: this utility only works with special Mifare 1K cards (Chinese clones).\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int arg, i;
|
|
||||||
bool format = false;
|
|
||||||
unsigned int c;
|
|
||||||
char tmp[3] = { 0x00, 0x00, 0x00 };
|
|
||||||
|
|
||||||
|
|
||||||
// Get commandline options
|
|
||||||
for (arg = 1; arg < argc; arg++) {
|
|
||||||
if (0 == strcmp(argv[arg], "-h")) {
|
|
||||||
print_usage(argv);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
} else if (0 == strcmp(argv[arg], "-f")) {
|
|
||||||
format = true;
|
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
|
||||||
quiet_output = true;
|
|
||||||
} else if (strlen(argv[arg]) == 8) {
|
|
||||||
for (i = 0 ; i < 4 ; ++i) {
|
|
||||||
memcpy(tmp, argv[arg] + i * 2, 2);
|
|
||||||
sscanf(tmp, "%02x", &c);
|
|
||||||
abtData[i] = (char) c;
|
|
||||||
}
|
|
||||||
abtData[4] = abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3];
|
|
||||||
iso14443a_crc_append(abtData, 16);
|
|
||||||
} else if (strlen(argv[arg]) == 32) {
|
|
||||||
for (i = 0 ; i < 16 ; ++i) {
|
|
||||||
memcpy(tmp, argv[arg] + i * 2, 2);
|
|
||||||
sscanf(tmp, "%02x", &c);
|
|
||||||
abtData[i] = (char) c;
|
|
||||||
}
|
|
||||||
abtData[4] = abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3];
|
|
||||||
iso14443a_crc_append(abtData, 16);
|
|
||||||
} else {
|
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
|
||||||
print_usage(argv);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nfc_context *context;
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to open the NFC reader
|
|
||||||
pnd = nfc_open(context, NULL);
|
|
||||||
|
|
||||||
if (pnd == NULL) {
|
|
||||||
ERR("Error opening NFC reader");
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise NFC device as "initiator"
|
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the CRC
|
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
// Use raw send/receive methods
|
|
||||||
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
// Disable 14443-4 autoswitching
|
|
||||||
if (nfc_device_set_property_bool(pnd, NP_AUTO_ISO14443_4, false) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
|
|
||||||
|
|
||||||
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
|
||||||
if (!transmit_bits(abtReqa, 7)) {
|
|
||||||
printf("Error: No tag available\n");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
memcpy(abtAtqa, abtRx, 2);
|
|
||||||
|
|
||||||
// Anti-collision
|
|
||||||
transmit_bytes(abtSelectAll, 2);
|
|
||||||
|
|
||||||
// Check answer
|
|
||||||
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
|
||||||
printf("WARNING: BCC check failed!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the UID CL1
|
|
||||||
memcpy(abtRawUid, abtRx, 4);
|
|
||||||
|
|
||||||
//Prepare and send CL1 Select-Command
|
|
||||||
memcpy(abtSelectTag + 2, abtRx, 5);
|
|
||||||
iso14443a_crc_append(abtSelectTag, 7);
|
|
||||||
transmit_bytes(abtSelectTag, 9);
|
|
||||||
abtSak = abtRx[0];
|
|
||||||
|
|
||||||
// Test if we are dealing with a CL2
|
|
||||||
if (abtSak & CASCADE_BIT) {
|
|
||||||
szCL = 2;//or more
|
|
||||||
// Check answer
|
|
||||||
if (abtRawUid[0] != 0x88) {
|
|
||||||
printf("WARNING: Cascade bit set but CT != 0x88!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (szCL == 2) {
|
|
||||||
// We have to do the anti-collision for cascade level 2
|
|
||||||
|
|
||||||
// Prepare CL2 commands
|
|
||||||
abtSelectAll[0] = 0x95;
|
|
||||||
|
|
||||||
// Anti-collision
|
|
||||||
transmit_bytes(abtSelectAll, 2);
|
|
||||||
|
|
||||||
// Check answer
|
|
||||||
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
|
||||||
printf("WARNING: BCC check failed!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save UID CL2
|
|
||||||
memcpy(abtRawUid + 4, abtRx, 4);
|
|
||||||
|
|
||||||
// Selection
|
|
||||||
abtSelectTag[0] = 0x95;
|
|
||||||
memcpy(abtSelectTag + 2, abtRx, 5);
|
|
||||||
iso14443a_crc_append(abtSelectTag, 7);
|
|
||||||
transmit_bytes(abtSelectTag, 9);
|
|
||||||
abtSak = abtRx[0];
|
|
||||||
|
|
||||||
// Test if we are dealing with a CL3
|
|
||||||
if (abtSak & CASCADE_BIT) {
|
|
||||||
szCL = 3;
|
|
||||||
// Check answer
|
|
||||||
if (abtRawUid[0] != 0x88) {
|
|
||||||
printf("WARNING: Cascade bit set but CT != 0x88!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (szCL == 3) {
|
|
||||||
// We have to do the anti-collision for cascade level 3
|
|
||||||
|
|
||||||
// Prepare and send CL3 AC-Command
|
|
||||||
abtSelectAll[0] = 0x97;
|
|
||||||
transmit_bytes(abtSelectAll, 2);
|
|
||||||
|
|
||||||
// Check answer
|
|
||||||
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
|
|
||||||
printf("WARNING: BCC check failed!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save UID CL3
|
|
||||||
memcpy(abtRawUid + 8, abtRx, 4);
|
|
||||||
|
|
||||||
// Prepare and send final Select-Command
|
|
||||||
abtSelectTag[0] = 0x97;
|
|
||||||
memcpy(abtSelectTag + 2, abtRx, 5);
|
|
||||||
iso14443a_crc_append(abtSelectTag, 7);
|
|
||||||
transmit_bytes(abtSelectTag, 9);
|
|
||||||
abtSak = abtRx[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request ATS, this only applies to tags that support ISO 14443A-4
|
|
||||||
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
|
|
||||||
iso_ats_supported = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nFound tag with\n UID: ");
|
|
||||||
switch (szCL) {
|
|
||||||
case 1:
|
|
||||||
printf("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printf("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
|
||||||
printf("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
printf("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
|
|
||||||
printf("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
|
|
||||||
printf("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);
|
|
||||||
if (szAts > 1) { // if = 1, it's not actual ATS but error code
|
|
||||||
printf(" ATS: ");
|
|
||||||
print_hex(abtAts, szAts);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
// now reset UID
|
|
||||||
iso14443a_crc_append(abtHalt, 2);
|
|
||||||
transmit_bytes(abtHalt, 4);
|
|
||||||
|
|
||||||
if (!transmit_bits(abtUnlock1, 7)) {
|
|
||||||
printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
|
|
||||||
} else {
|
|
||||||
if (format) {
|
|
||||||
transmit_bytes(abtWipe, 1);
|
|
||||||
transmit_bytes(abtHalt, 4);
|
|
||||||
transmit_bits(abtUnlock1, 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transmit_bytes(abtUnlock2, 1)) {
|
|
||||||
printf("Card unlocked\n");
|
|
||||||
} else {
|
|
||||||
printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
transmit_bytes(abtWrite, 4);
|
|
||||||
transmit_bytes(abtData, 18);
|
|
||||||
if (format) {
|
|
||||||
for (i = 3 ; i < 64 ; i += 4) {
|
|
||||||
abtWrite[1] = (char) i;
|
|
||||||
iso14443a_crc_append(abtWrite, 2);
|
|
||||||
transmit_bytes(abtWrite, 4);
|
|
||||||
transmit_bytes(abtBlank, 18);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-mfultralight 1 "Nov 02, 2009" "libnfc" "NFC Utilities"
|
.TH NFC-MFULTRALIGHT 1 "Nov 02, 2009"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-mfultralight \- MIFARE Ultralight command line tool
|
nfc-mfultralight \- MIFARE Ultralight command line tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -8,7 +8,7 @@ nfc-mfultralight \- MIFARE Ultralight command line tool
|
|||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B nfc-mfultralight
|
.B nfc-mfultralight
|
||||||
is a MIFARE Ultralight tool that allows one to read or write
|
is a MIFARE Ultralight tool that allows to read or write
|
||||||
a tag data to/from a
|
a tag data to/from a
|
||||||
.IR DUMP
|
.IR DUMP
|
||||||
file.
|
file.
|
||||||
@ -20,9 +20,6 @@ Be cautious that some parts of a Ultralight memory can be written only once
|
|||||||
and some parts are used as lock bits, so please read the tag documentation
|
and some parts are used as lock bits, so please read the tag documentation
|
||||||
before experimenting too much!
|
before experimenting too much!
|
||||||
|
|
||||||
To set the UID of a special writeable UID card, edit the first 7 bytes of a dump file and
|
|
||||||
then write it back, answering 'Y' to the question 'Write UID bytes?'.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.BR r " | " w
|
.BR r " | " w
|
||||||
Perform read from (
|
Perform read from (
|
||||||
@ -34,25 +31,20 @@ Perform read from (
|
|||||||
.IR DUMP
|
.IR DUMP
|
||||||
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
|
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
|
||||||
|
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Roel Verdult <roel@libnfc.org>,
|
Roel Verdult <roel@libnfc.org>
|
||||||
.br
|
Romuald Conty <romuald@libnfc.org>
|
||||||
Romuald Conty <romuald@libnfc.org>.
|
|
||||||
.PP
|
.PP
|
||||||
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
This manual page was written by Romuald Conty <romuald@libnfc.org>.
|
||||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||||
286
examples/nfc-mfultralight.c
Normal file
286
examples/nfc-mfultralight.c
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty
|
||||||
|
*
|
||||||
|
* 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-mfultralight.c
|
||||||
|
* @brief MIFARE Ultralight dump/restore tool
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
#include "mifare.h"
|
||||||
|
|
||||||
|
static nfc_device_t *pnd;
|
||||||
|
static nfc_target_t nt;
|
||||||
|
static mifare_param mp;
|
||||||
|
static mifareul_tag mtDump;
|
||||||
|
static uint32_t uiBlocks = 0xF;
|
||||||
|
|
||||||
|
static const nfc_modulation_t nmMifare = {
|
||||||
|
.nmt = NMT_ISO14443A,
|
||||||
|
.nbr = NBR_106,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_success_or_failure (bool bFailure, uint32_t * uiCounter)
|
||||||
|
{
|
||||||
|
printf ("%c", (bFailure) ? 'x' : '.');
|
||||||
|
if (uiCounter)
|
||||||
|
*uiCounter += (bFailure) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
read_card (void)
|
||||||
|
{
|
||||||
|
uint32_t page;
|
||||||
|
bool bFailure = false;
|
||||||
|
uint32_t uiReadedPages = 0;
|
||||||
|
|
||||||
|
printf ("Reading %d pages |", uiBlocks + 1);
|
||||||
|
|
||||||
|
for (page = 0; page <= uiBlocks; page += 4) {
|
||||||
|
// Try to read out the data block
|
||||||
|
if (nfc_initiator_mifare_cmd (pnd, MC_READ, page, &mp)) {
|
||||||
|
memcpy (mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16);
|
||||||
|
} else {
|
||||||
|
bFailure = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_success_or_failure (bFailure, &uiReadedPages);
|
||||||
|
print_success_or_failure (bFailure, &uiReadedPages);
|
||||||
|
print_success_or_failure (bFailure, &uiReadedPages);
|
||||||
|
print_success_or_failure (bFailure, &uiReadedPages);
|
||||||
|
}
|
||||||
|
printf ("|\n");
|
||||||
|
printf ("Done, %d of %d pages readed.\n", uiReadedPages, uiBlocks + 1);
|
||||||
|
fflush (stdout);
|
||||||
|
|
||||||
|
return (!bFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
write_card (void)
|
||||||
|
{
|
||||||
|
uint32_t uiBlock = 0;
|
||||||
|
bool bFailure = false;
|
||||||
|
uint32_t uiWritenPages = 0;
|
||||||
|
uint32_t uiSkippedPages;
|
||||||
|
|
||||||
|
char buffer[BUFSIZ];
|
||||||
|
bool write_otp;
|
||||||
|
bool write_lock;
|
||||||
|
|
||||||
|
printf ("Write OTP bytes ? [yN] ");
|
||||||
|
if (!fgets (buffer, BUFSIZ, stdin)) {
|
||||||
|
ERR ("Unable to read standard input.");
|
||||||
|
}
|
||||||
|
write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||||
|
printf ("Write Lock bytes ? [yN] ");
|
||||||
|
if (!fgets (buffer, BUFSIZ, stdin)) {
|
||||||
|
ERR ("Unable to read standard input.");
|
||||||
|
}
|
||||||
|
write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||||
|
|
||||||
|
printf ("Writing %d pages |", uiBlocks + 1);
|
||||||
|
/* We need to skip 2 first pages. */
|
||||||
|
printf ("ss");
|
||||||
|
uiSkippedPages = 2;
|
||||||
|
|
||||||
|
for (int page = 0x2; page <= 0xF; page++) {
|
||||||
|
if ((page==0x2) && (!write_lock)) {
|
||||||
|
printf ("s");
|
||||||
|
uiSkippedPages++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((page==0x3) && (!write_otp)) {
|
||||||
|
printf ("s");
|
||||||
|
uiSkippedPages++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Show if the readout went well
|
||||||
|
if (bFailure) {
|
||||||
|
// When a failure occured we need to redo the anti-collision
|
||||||
|
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
|
||||||
|
ERR ("tag was removed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bFailure = false;
|
||||||
|
}
|
||||||
|
// For the Mifare Ultralight, this write command can be used
|
||||||
|
// in compatibility mode, which only actually writes the first
|
||||||
|
// page (4 bytes). The Ultralight-specific Write command only
|
||||||
|
// writes one page at a time.
|
||||||
|
uiBlock = page / 4;
|
||||||
|
memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16);
|
||||||
|
if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, page, &mp))
|
||||||
|
bFailure = true;
|
||||||
|
|
||||||
|
print_success_or_failure (bFailure, &uiWritenPages);
|
||||||
|
}
|
||||||
|
printf ("|\n");
|
||||||
|
printf ("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
bool bReadAction;
|
||||||
|
FILE *pfDump;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
printf ("\n");
|
||||||
|
printf ("%s r|w <dump.mfd>\n", argv[0]);
|
||||||
|
printf ("\n");
|
||||||
|
printf ("r|w - Perform read from or write to card\n");
|
||||||
|
printf ("<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
|
||||||
|
printf ("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG ("\nChecking arguments and settings\n");
|
||||||
|
|
||||||
|
bReadAction = tolower ((int) ((unsigned char) *(argv[1])) == 'r');
|
||||||
|
|
||||||
|
if (bReadAction) {
|
||||||
|
memset (&mtDump, 0x00, sizeof (mtDump));
|
||||||
|
} else {
|
||||||
|
pfDump = fopen (argv[2], "rb");
|
||||||
|
|
||||||
|
if (pfDump == NULL) {
|
||||||
|
ERR ("Could not open dump file: %s\n", argv[2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
|
||||||
|
ERR ("Could not read from dump file: %s\n", argv[2]);
|
||||||
|
fclose (pfDump);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fclose (pfDump);
|
||||||
|
}
|
||||||
|
DBG ("Successfully opened the dump file\n");
|
||||||
|
|
||||||
|
// Try to open the NFC device
|
||||||
|
pnd = nfc_connect (NULL);
|
||||||
|
if (pnd == NULL) {
|
||||||
|
ERR ("Error connecting NFC device\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
|
// Drop the field for a while
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Let the device only try once to find a tag
|
||||||
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Enable field so more power consuming cards can power themselves up
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Connected to NFC device: %s\n", pnd->acName);
|
||||||
|
|
||||||
|
// Try to find a MIFARE Ultralight tag
|
||||||
|
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
|
||||||
|
ERR ("no tag was found\n");
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Test if we are dealing with a MIFARE compatible tag
|
||||||
|
|
||||||
|
if (nt.nti.nai.abtAtqa[1] != 0x44) {
|
||||||
|
ERR ("tag is not a MIFARE Ultralight card\n");
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
// Get the info from the current tag
|
||||||
|
printf ("Found MIFARE Ultralight card with UID: ");
|
||||||
|
size_t szPos;
|
||||||
|
for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) {
|
||||||
|
printf ("%02x", nt.nti.nai.abtUid[szPos]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (bReadAction) {
|
||||||
|
if (read_card ()) {
|
||||||
|
printf ("Writing data to file: %s ... ", argv[2]);
|
||||||
|
fflush (stdout);
|
||||||
|
pfDump = fopen (argv[2], "wb");
|
||||||
|
if (pfDump == NULL) {
|
||||||
|
printf ("Could not open file: %s\n", argv[2]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (fwrite (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
|
||||||
|
printf ("Could not write to file: %s\n", argv[2]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
fclose (pfDump);
|
||||||
|
printf ("Done.\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write_card ();
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
.TH nfc-poll 1 "June 26, 2009" "libnfc" "libnfc's examples"
|
.TH NFC-POLL 1 "June 26, 2009"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-poll \- poll first available NFC target
|
nfc-poll \- Poll for one NFC target
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B nfc-poll
|
.B nfc-poll
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@ -8,18 +8,8 @@ nfc-poll \- poll first available NFC target
|
|||||||
is a utility for polling any available target (tags but also NFCIP targets)
|
is a utility for polling any available target (tags but also NFCIP targets)
|
||||||
using ISO14443-A, FeliCa, Jewel and ISO14443-B modulations.
|
using ISO14443-A, FeliCa, Jewel and ISO14443-B modulations.
|
||||||
|
|
||||||
This tool uses hardware polling feature if available (ie. PN532) or switch back
|
This tool relies on a hardware polling feature of the PN532, it will display
|
||||||
to software polling, it will display available information retrieved from the
|
available information retrieved from the tag.
|
||||||
tag.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B \-v
|
|
||||||
Tells
|
|
||||||
.I
|
|
||||||
nfc-poll
|
|
||||||
to be verbose and display detailed information about the targets shown.
|
|
||||||
This includes SAK decoding and fingerprinting is available.
|
|
||||||
|
|
||||||
.SH IMPORTANT
|
.SH IMPORTANT
|
||||||
There are some well-know limits with this example:
|
There are some well-know limits with this example:
|
||||||
@ -40,17 +30,13 @@ ISO14443-4.
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Romuald Conty <romuald@libnfc.org>
|
Romuald Conty <romuald@libnfc.org>
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@ -1,15 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2011, Romain Tartiere, Romuald Conty
|
||||||
* 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:
|
|
||||||
* Copyright (C) 2020 Adam Laurie
|
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -36,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file nfc-poll.c
|
* @file nfc-poll
|
||||||
* @brief Polling example
|
* @brief Polling example
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -45,7 +38,6 @@
|
|||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -55,108 +47,116 @@
|
|||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
#include <nfc/nfc-types.h>
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define MAX_DEVICE_COUNT 16
|
#define MAX_DEVICE_COUNT 16
|
||||||
|
|
||||||
static nfc_device *pnd = NULL;
|
static nfc_device_t *pnd = NULL;
|
||||||
static nfc_context *context;
|
|
||||||
|
|
||||||
static void stop_polling(int sig)
|
void stop_polling (int sig)
|
||||||
{
|
{
|
||||||
(void) sig;
|
(void) sig;
|
||||||
if (pnd != NULL)
|
if (pnd)
|
||||||
nfc_abort_command(pnd);
|
nfc_abort_command (pnd);
|
||||||
else {
|
else
|
||||||
nfc_exit(context);
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_usage(const char *progname)
|
|
||||||
{
|
|
||||||
printf("usage: %s [-v]\n", progname);
|
|
||||||
printf(" -v\t verbose display\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
|
size_t szFound;
|
||||||
|
size_t i;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
|
||||||
signal(SIGINT, stop_polling);
|
signal (SIGINT, stop_polling);
|
||||||
|
|
||||||
|
pnddDevices = parse_args (argc, argv, &szFound, &verbose);
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
const char *acLibnfcVersion = nfc_version();
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
|
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
if (argc > 1) {
|
||||||
if (argc != 1) {
|
errx (1, "usage: %s", argv[0]);
|
||||||
if ((argc == 2) && (0 == strcmp("-v", argv[1]))) {
|
}
|
||||||
verbose = true;
|
|
||||||
} else {
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
print_usage(argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
if (szFound == 0) {
|
||||||
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
|
fprintf (stderr, "malloc() failed\n");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t uiPollNr = 20;
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
||||||
const uint8_t uiPeriod = 2;
|
|
||||||
const nfc_modulation nmModulations[6] = {
|
|
||||||
{ .nmt = NMT_ISO14443A, .nbr = NBR_106 },
|
|
||||||
{ .nmt = NMT_ISO14443B, .nbr = NBR_106 },
|
|
||||||
{ .nmt = NMT_FELICA, .nbr = NBR_212 },
|
|
||||||
{ .nmt = NMT_FELICA, .nbr = NBR_424 },
|
|
||||||
{ .nmt = NMT_JEWEL, .nbr = NBR_106 },
|
|
||||||
{ .nmt = NMT_ISO14443BICLASS, .nbr = NBR_106 },
|
|
||||||
};
|
|
||||||
const size_t szModulations = 6;
|
|
||||||
|
|
||||||
nfc_target nt;
|
if (szFound == 0) {
|
||||||
int res = 0;
|
printf ("No NFC device found.\n");
|
||||||
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pnd = nfc_open(context, NULL);
|
for (i = 0; i < szFound; i++) {
|
||||||
|
|
||||||
if (pnd == NULL) {
|
const byte_t btPollNr = 20;
|
||||||
ERR("%s", "Unable to open NFC device.");
|
const byte_t btPeriod = 2;
|
||||||
nfc_exit(context);
|
const nfc_modulation_t nmModulations[5] = {
|
||||||
exit(EXIT_FAILURE);
|
{ .nmt = NMT_ISO14443A, .nbr = NBR_106 },
|
||||||
|
{ .nmt = NMT_ISO14443B, .nbr = NBR_106 },
|
||||||
|
{ .nmt = NMT_FELICA, .nbr = NBR_212 },
|
||||||
|
{ .nmt = NMT_FELICA, .nbr = NBR_424 },
|
||||||
|
{ .nmt = NMT_JEWEL, .nbr = NBR_106 },
|
||||||
|
};
|
||||||
|
const size_t szModulations = 5;
|
||||||
|
|
||||||
|
nfc_target_t antTargets[2];
|
||||||
|
size_t szTargetFound;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
pnd = nfc_connect (&(pnddDevices[i]));
|
||||||
|
|
||||||
|
if (pnd == NULL) {
|
||||||
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
|
// Drop the field for a while
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Let the reader only try once to find a tag
|
||||||
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Enable field so more power consuming cards can power themselves up
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
|
nfc_perror (pnd, "nfc_configure");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
|
printf ("PN532 will poll during %ld ms\n", (unsigned long) btPollNr * szModulations * btPeriod * 150);
|
||||||
|
res = nfc_initiator_poll_targets (pnd, nmModulations, szModulations, btPollNr, btPeriod, antTargets, &szTargetFound);
|
||||||
|
if (res) {
|
||||||
|
uint8_t n;
|
||||||
|
printf ("%ld target(s) have been found.\n", (unsigned long) szTargetFound);
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
|
printf ("T%d: ", n + 1);
|
||||||
|
print_nfc_target ( antTargets[n], verbose );
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nfc_perror (pnd, "nfc_initiator_poll_targets");
|
||||||
|
nfc_disconnect (pnd);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
nfc_disconnect (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
free (pnddDevices);
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
exit (EXIT_SUCCESS);
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
|
|
||||||
printf("NFC device will poll during %ld ms (%u pollings of %lu ms for %" PRIdPTR " modulations)\n", (unsigned long) uiPollNr * szModulations * uiPeriod * 150, uiPollNr, (unsigned long) uiPeriod * 150, szModulations);
|
|
||||||
if ((res = nfc_initiator_poll_target(pnd, nmModulations, szModulations, uiPollNr, uiPeriod, &nt)) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_poll_target");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res > 0) {
|
|
||||||
print_nfc_target(&nt, verbose);
|
|
||||||
printf("Waiting for card removing...");
|
|
||||||
fflush(stdout);
|
|
||||||
while (0 == nfc_initiator_target_is_present(pnd, NULL)) {}
|
|
||||||
nfc_perror(pnd, "nfc_initiator_target_is_present");
|
|
||||||
printf("done.\n");
|
|
||||||
} else {
|
|
||||||
printf("No target found.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-relay-picc 1 "October 12, 2010" "libnfc" "NFC Utilities"
|
.TH NFC-RELAY-PICC 1 "October 12, 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-relay-picc \- Relay demonstration tool for ISO14443-4
|
nfc-relay-picc \- Relay demonstration tool for ISO14443-4
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -34,11 +34,6 @@ tag <---> initiator (relay) <---> target (relay) <---> original reader
|
|||||||
Commands are read from file descriptor 3
|
Commands are read from file descriptor 3
|
||||||
Responses are sent to file descriptor 4
|
Responses are sent to file descriptor 4
|
||||||
|
|
||||||
\fB-s\fP
|
|
||||||
Swap roles of found devices
|
|
||||||
Usually the first found device is used as target (emulator) and the second
|
|
||||||
as initiator (reader). Using this option these roles are inversed.
|
|
||||||
|
|
||||||
\fB-n\fP \fIN\fP
|
\fB-n\fP \fIN\fP
|
||||||
Adds a waiting time of \fIN\fP seconds (integer) in the loop
|
Adds a waiting time of \fIN\fP seconds (integer) in the loop
|
||||||
|
|
||||||
@ -51,10 +46,10 @@ Remote relay over TCP/IP:
|
|||||||
|
|
||||||
\fBsocat\fP
|
\fBsocat\fP
|
||||||
TCP-LISTEN:port,reuseaddr
|
TCP-LISTEN:port,reuseaddr
|
||||||
"EXEC:\fBnfc-relay-picc \-i\fP,fdin=3,fdout=4"
|
"EXEC:\fBnfc-relay-picc -i\fP,fdin=3,fdout=4"
|
||||||
\fBsocat\fP
|
\fBsocat\fP
|
||||||
TCP:remotehost:port
|
TCP:remotehost:port
|
||||||
"EXEC:\fBnfc-relay-picc \-t\fP,fdin=3,fdout=4"
|
"EXEC:\fBnfc-relay-picc -t\fP,fdin=3,fdout=4"
|
||||||
|
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
There are some differences with \fBnfc-relay\fP:
|
There are some differences with \fBnfc-relay\fP:
|
||||||
@ -68,16 +63,12 @@ this example works on readers very strict on timing.
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.PP
|
.PP
|
||||||
This manual page is licensed under the terms of the GNU GPL (version 2 or later).
|
This manual page is licensed under the terms of the GNU GPL (version 2 or later).
|
||||||
466
examples/nfc-relay-picc.c
Normal file
466
examples/nfc-relay-picc.c
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010, Romuald Conty
|
||||||
|
*
|
||||||
|
* 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-relay-picc.c
|
||||||
|
* @brief Relay example using two PN532 devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Notes & differences with nfc-relay:
|
||||||
|
// - This example only works with PN532 because it relies on
|
||||||
|
// its internal handling of ISO14443-4 specificities.
|
||||||
|
// - Thanks to this internal handling & injection of WTX frames,
|
||||||
|
// this example works on readers very strict on timing
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
|
// TODO Move this Windows conditional code in contrib/win32/ or contrib/windows.h
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Needed by sleep() under Unix
|
||||||
|
# include <unistd.h>
|
||||||
|
# define sleep sleep
|
||||||
|
# define SUSP_TIME 1 // secs.
|
||||||
|
#else
|
||||||
|
// Needed by Sleep() under Windows
|
||||||
|
# include <winbase.h>
|
||||||
|
# define sleep Sleep
|
||||||
|
# define SUSP_TIME 1000 // msecs.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_FRAME_LEN 264
|
||||||
|
#define MAX_DEVICE_COUNT 2
|
||||||
|
|
||||||
|
static byte_t abtCapdu[MAX_FRAME_LEN];
|
||||||
|
static size_t szCapduLen;
|
||||||
|
static byte_t abtRapdu[MAX_FRAME_LEN];
|
||||||
|
static size_t szRapduLen;
|
||||||
|
static nfc_device_t *pndInitiator;
|
||||||
|
static nfc_device_t *pndTarget;
|
||||||
|
static bool quitting = false;
|
||||||
|
static bool quiet_output = false;
|
||||||
|
static bool initiator_only_mode = false;
|
||||||
|
static bool target_only_mode = false;
|
||||||
|
static int waiting_time = 0;
|
||||||
|
FILE * fd3;
|
||||||
|
FILE * fd4;
|
||||||
|
|
||||||
|
void
|
||||||
|
intr_hdlr (void)
|
||||||
|
{
|
||||||
|
printf ("\nQuitting...\n");
|
||||||
|
printf ("Please send a last command to the emulator to quit properly.\n");
|
||||||
|
quitting = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_usage (char *argv[])
|
||||||
|
{
|
||||||
|
printf ("Usage: %s [OPTIONS]\n", argv[0]);
|
||||||
|
printf ("Options:\n");
|
||||||
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
|
printf ("\t-q\tQuiet mode. Suppress printing of relayed data (improves timing).\n");
|
||||||
|
printf ("\t-t\tTarget mode only (the one on reader side). Data expected from FD3 to FD4.\n");
|
||||||
|
printf ("\t-i\tInitiator mode only (the one on tag side). Data expected from FD3 to FD4.\n");
|
||||||
|
printf ("\t-n N\tAdds a waiting time of N seconds (integer) in the relay to mimic long distance.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool print_hex_fd4 (const byte_t * pbtData, const size_t szBytes, const char * pchPrefix)
|
||||||
|
{
|
||||||
|
size_t szPos;
|
||||||
|
if (szBytes > MAX_FRAME_LEN) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (fprintf (fd4, "#%s %04zx: ", pchPrefix, szBytes)<0) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
|
if (fprintf (fd4, "%02x ", pbtData[szPos])<0) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fprintf (fd4, "\n")<0) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
fflush(fd4);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool scan_hex_fd3 (byte_t *pbtData, size_t *pszBytes, const char * pchPrefix)
|
||||||
|
{
|
||||||
|
size_t szPos;
|
||||||
|
unsigned int uiBytes;
|
||||||
|
unsigned int uiData;
|
||||||
|
char pchScan[256];
|
||||||
|
int c;
|
||||||
|
// Look for our next sync marker
|
||||||
|
while ( (c=fgetc(fd3)) != '#') {
|
||||||
|
if (c == EOF) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strncpy(pchScan, pchPrefix, 250);
|
||||||
|
strcat(pchScan, " %04x:");
|
||||||
|
if (fscanf (fd3, pchScan, &uiBytes)<1) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
*pszBytes=uiBytes;
|
||||||
|
if (*pszBytes > MAX_FRAME_LEN) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
for (szPos = 0; szPos < *pszBytes; szPos++) {
|
||||||
|
if (fscanf (fd3, "%02x", &uiData)<1) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
pbtData[szPos]=uiData;
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int arg;
|
||||||
|
size_t szFound;
|
||||||
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
|
nfc_target_t ntRealTarget;
|
||||||
|
|
||||||
|
// Get commandline options
|
||||||
|
for (arg = 1; arg < argc; arg++) {
|
||||||
|
if (0 == strcmp (argv[arg], "-h")) {
|
||||||
|
print_usage (argv);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
|
quiet_output = true;
|
||||||
|
} else if (0 == strcmp (argv[arg], "-t")) {
|
||||||
|
printf ("INFO: %s\n", "Target mode only.");
|
||||||
|
initiator_only_mode = false;
|
||||||
|
target_only_mode = true;
|
||||||
|
} else if (0 == strcmp (argv[arg], "-i")) {
|
||||||
|
printf ("INFO: %s\n", "Initiator mode only.");
|
||||||
|
initiator_only_mode = true;
|
||||||
|
target_only_mode = false;
|
||||||
|
} else if (0 == strcmp (argv[arg], "-n")) {
|
||||||
|
if (++arg==argc || (sscanf(argv[arg], "%i", &waiting_time)<1)) {
|
||||||
|
ERR ("Missing or wrong waiting time value: %s.", argv[arg]);
|
||||||
|
print_usage (argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
printf ("Waiting time: %i secs.\n", waiting_time);
|
||||||
|
} else {
|
||||||
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
|
print_usage (argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display libnfc version
|
||||||
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
|
||||||
|
#else
|
||||||
|
signal (SIGINT, (void (*)()) intr_hdlr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Allocate memory to put the result of available devices listing
|
||||||
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
|
fprintf (stderr, "malloc() failed\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
// List available devices
|
||||||
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
||||||
|
|
||||||
|
if (initiator_only_mode || target_only_mode) {
|
||||||
|
if (szFound < 1) {
|
||||||
|
ERR ("No device found");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
fd3 = fdopen(3, "r");
|
||||||
|
fd4 = fdopen(4, "w");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (szFound < 2) {
|
||||||
|
ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target_only_mode) {
|
||||||
|
// Try to open the NFC reader used as initiator
|
||||||
|
// Little hack to allow using initiator no matter if
|
||||||
|
// there is already a target used locally or not on the same machine:
|
||||||
|
// if there is more than one readers connected we connect to the second reader
|
||||||
|
// (we hope they're always detected in the same order)
|
||||||
|
if (szFound == 1) {
|
||||||
|
pndInitiator = nfc_connect (&(pnddDevices[0]));
|
||||||
|
} else {
|
||||||
|
pndInitiator = nfc_connect (&(pnddDevices[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pndInitiator) {
|
||||||
|
printf ("Error connecting NFC reader\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Connected to the NFC reader device: %s\n", pndInitiator->acName);
|
||||||
|
|
||||||
|
// Try to find a ISO 14443-4A tag
|
||||||
|
nfc_modulation_t nm = {
|
||||||
|
.nmt = NMT_ISO14443A,
|
||||||
|
.nbr = NBR_106,
|
||||||
|
};
|
||||||
|
if (!nfc_initiator_select_passive_target (pndInitiator, nm, NULL, 0, &ntRealTarget)) {
|
||||||
|
printf ("Error: no tag was found\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Found tag:\n");
|
||||||
|
print_nfc_iso14443a_info (ntRealTarget.nti.nai, false);
|
||||||
|
if (initiator_only_mode) {
|
||||||
|
if (print_hex_fd4(ntRealTarget.nti.nai.abtUid, ntRealTarget.nti.nai.szUidLen, "UID") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while printing UID to FD4\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (print_hex_fd4(ntRealTarget.nti.nai.abtAtqa, 2, "ATQA") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while printing ATQA to FD4\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (print_hex_fd4(&(ntRealTarget.nti.nai.btSak), 1, "SAK") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while printing SAK to FD4\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (print_hex_fd4(ntRealTarget.nti.nai.abtAts, ntRealTarget.nti.nai.szAtsLen, "ATS") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while printing ATS to FD4\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initiator_only_mode) {
|
||||||
|
printf ("Hint: tag <---> *INITIATOR* (relay) <-FD3/FD4-> target (relay) <---> original reader\n\n");
|
||||||
|
} else if (target_only_mode) {
|
||||||
|
printf ("Hint: tag <---> initiator (relay) <-FD3/FD4-> *TARGET* (relay) <---> original reader\n\n");
|
||||||
|
} else {
|
||||||
|
printf ("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n");
|
||||||
|
}
|
||||||
|
if (!initiator_only_mode) {
|
||||||
|
nfc_target_t ntEmulatedTarget = {
|
||||||
|
.nm = {
|
||||||
|
.nmt = NMT_ISO14443A,
|
||||||
|
.nbr = NBR_106,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (target_only_mode) {
|
||||||
|
size_t foo;
|
||||||
|
if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtUid, &(ntEmulatedTarget.nti.nai.szUidLen), "UID") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while scanning UID from FD3\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAtqa, &foo, "ATQA") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while scanning ATQA from FD3\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (scan_hex_fd3(&(ntEmulatedTarget.nti.nai.btSak), &foo, "SAK") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while scanning SAK from FD3\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAts, &(ntEmulatedTarget.nti.nai.szAtsLen), "ATS") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while scanning ATS from FD3\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ntEmulatedTarget.nti = ntRealTarget.nti;
|
||||||
|
}
|
||||||
|
// We can only emulate a short UID, so fix length & ATQA bit:
|
||||||
|
ntEmulatedTarget.nti.nai.szUidLen = 4;
|
||||||
|
ntEmulatedTarget.nti.nai.abtAtqa[1] &= (0xFF-0x40);
|
||||||
|
// First byte of UID is always automatically replaced by 0x08 in this mode anyway
|
||||||
|
ntEmulatedTarget.nti.nai.abtUid[0] = 0x08;
|
||||||
|
// ATS is always automatically replaced by PN532, we've no control on it:
|
||||||
|
// ATS = (05) 75 33 92 03
|
||||||
|
// (TL) T0 TA TB TC
|
||||||
|
// | | | +-- CID supported, NAD supported
|
||||||
|
// | | +----- FWI=9 SFGI=2 => FWT=154ms, SFGT=1.21ms
|
||||||
|
// | +-------- DR=2,4 DS=2,4 => supports 106, 212 & 424bps in both directions
|
||||||
|
// +----------- TA,TB,TC, FSCI=5 => FSC=64
|
||||||
|
// It seems hazardous to tell we support NAD if the tag doesn't support NAD but I don't know how to disable it
|
||||||
|
// PC/SC pseudo-ATR = 3B 80 80 01 01 if there is no historical bytes
|
||||||
|
|
||||||
|
// Creates ATS and copy max 48 bytes of Tk:
|
||||||
|
byte_t * pbtTk;
|
||||||
|
size_t szTk;
|
||||||
|
pbtTk = iso14443a_locate_historical_bytes (ntEmulatedTarget.nti.nai.abtAts, ntEmulatedTarget.nti.nai.szAtsLen, &szTk);
|
||||||
|
szTk = (szTk > 48) ? 48 : szTk;
|
||||||
|
byte_t pbtTkt[48];
|
||||||
|
memcpy(pbtTkt, pbtTk, szTk);
|
||||||
|
ntEmulatedTarget.nti.nai.abtAts[0] = 0x75;
|
||||||
|
ntEmulatedTarget.nti.nai.abtAts[1] = 0x33;
|
||||||
|
ntEmulatedTarget.nti.nai.abtAts[2] = 0x92;
|
||||||
|
ntEmulatedTarget.nti.nai.abtAts[3] = 0x03;
|
||||||
|
ntEmulatedTarget.nti.nai.szAtsLen = 4 + szTk;
|
||||||
|
memcpy(&(ntEmulatedTarget.nti.nai.abtAts[4]), pbtTkt, szTk);
|
||||||
|
|
||||||
|
printf("We will emulate:\n");
|
||||||
|
print_nfc_iso14443a_info (ntEmulatedTarget.nti.nai, false);
|
||||||
|
|
||||||
|
// Try to open the NFC emulator device
|
||||||
|
pndTarget = nfc_connect (&(pnddDevices[0]));
|
||||||
|
if (pndTarget == NULL) {
|
||||||
|
printf ("Error connecting NFC emulator device\n");
|
||||||
|
if (!target_only_mode) {
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
}
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Connected to the NFC emulator device: %s\n", pndTarget->acName);
|
||||||
|
|
||||||
|
if (!nfc_target_init (pndTarget, &ntEmulatedTarget, abtCapdu, &szCapduLen)) {
|
||||||
|
ERR ("%s", "Initialization of NFC emulator failed");
|
||||||
|
if (!target_only_mode) {
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
}
|
||||||
|
nfc_disconnect (pndTarget);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf ("%s\n", "Done, relaying frames now!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while (!quitting) {
|
||||||
|
bool ret;
|
||||||
|
if (!initiator_only_mode) {
|
||||||
|
// Receive external reader command through target
|
||||||
|
if (!nfc_target_receive_bytes(pndTarget,abtCapdu,&szCapduLen)) {
|
||||||
|
nfc_perror (pndTarget, "nfc_target_receive_bytes");
|
||||||
|
if (!target_only_mode) {
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
}
|
||||||
|
nfc_disconnect (pndTarget);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (target_only_mode) {
|
||||||
|
if (print_hex_fd4(abtCapdu, szCapduLen, "C-APDU") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while printing C-APDU to FD4\n");
|
||||||
|
nfc_disconnect (pndTarget);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scan_hex_fd3(abtCapdu, &szCapduLen, "C-APDU") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while scanning C-APDU from FD3\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Show transmitted response
|
||||||
|
if (!quiet_output) {
|
||||||
|
printf ("Forwarding C-APDU: ");
|
||||||
|
print_hex (abtCapdu, szCapduLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target_only_mode) {
|
||||||
|
// Forward the frame to the original tag
|
||||||
|
ret = nfc_initiator_transceive_bytes
|
||||||
|
(pndInitiator, abtCapdu, szCapduLen, abtRapdu, &szRapduLen);
|
||||||
|
} else {
|
||||||
|
if (scan_hex_fd3(abtRapdu, &szRapduLen, "R-APDU") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while scanning R-APDU from FD3\n");
|
||||||
|
nfc_disconnect (pndTarget);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
// Redirect the answer back to the external reader
|
||||||
|
if (waiting_time > 0) {
|
||||||
|
if (!quiet_output) {
|
||||||
|
printf ("Waiting %is to simulate longer relay...\n", waiting_time);
|
||||||
|
}
|
||||||
|
sleep(waiting_time * SUSP_TIME);
|
||||||
|
}
|
||||||
|
// Show transmitted response
|
||||||
|
if (!quiet_output) {
|
||||||
|
printf ("Forwarding R-APDU: ");
|
||||||
|
print_hex (abtRapdu, szRapduLen);
|
||||||
|
}
|
||||||
|
if (!initiator_only_mode) {
|
||||||
|
// Transmit the response bytes
|
||||||
|
if (!nfc_target_send_bytes(pndTarget, abtRapdu, szRapduLen)) {
|
||||||
|
nfc_perror (pndTarget, "nfc_target_send_bytes");
|
||||||
|
if (!target_only_mode) {
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
}
|
||||||
|
if (!initiator_only_mode) {
|
||||||
|
nfc_disconnect (pndTarget);
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (print_hex_fd4(abtRapdu, szRapduLen, "R-APDU") != EXIT_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error while printing R-APDU to FD4\n");
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target_only_mode) {
|
||||||
|
nfc_disconnect (pndInitiator);
|
||||||
|
}
|
||||||
|
if (!initiator_only_mode) {
|
||||||
|
nfc_disconnect (pndTarget);
|
||||||
|
}
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
.TH nfc-relay 1 "June 26, 2009" "libnfc" "libnfc'examples"
|
.TH NFC-RELAY 1 "June 26, 2009"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nfc-relay \- Relay attack command line tool based on libnfc
|
nfc-relay \- Relay attack command line tool based on libnfc
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -20,17 +20,13 @@ therefore we advise you to try it against e.g. an OmniKey CardMan 5321 reader.
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Roel Verdult <roel@libnfc.org>
|
Roel Verdult <roel@libnfc.org>
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -43,7 +37,6 @@
|
|||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -52,101 +45,97 @@
|
|||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
#define MAX_DEVICE_COUNT 2
|
#define MAX_DEVICE_COUNT 2
|
||||||
|
|
||||||
static uint8_t abtReaderRx[MAX_FRAME_LEN];
|
static byte_t abtReaderRx[MAX_FRAME_LEN];
|
||||||
static uint8_t abtReaderRxPar[MAX_FRAME_LEN];
|
static byte_t abtReaderRxPar[MAX_FRAME_LEN];
|
||||||
static int szReaderRxBits;
|
static size_t szReaderRxBits;
|
||||||
static uint8_t abtTagRx[MAX_FRAME_LEN];
|
static byte_t abtTagRx[MAX_FRAME_LEN];
|
||||||
static uint8_t abtTagRxPar[MAX_FRAME_LEN];
|
static byte_t abtTagRxPar[MAX_FRAME_LEN];
|
||||||
static int szTagRxBits;
|
static size_t szTagRxBits;
|
||||||
static nfc_device *pndReader;
|
static nfc_device_t *pndReader;
|
||||||
static nfc_device *pndTag;
|
static nfc_device_t *pndTag;
|
||||||
static bool quitting = false;
|
static bool quitting = false;
|
||||||
|
|
||||||
static void
|
void
|
||||||
intr_hdlr(int sig)
|
intr_hdlr (void)
|
||||||
{
|
{
|
||||||
(void) sig;
|
printf ("\nQuitting...\n");
|
||||||
printf("\nQuitting...\n");
|
|
||||||
quitting = true;
|
quitting = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
print_usage(char *argv[])
|
print_usage (char *argv[])
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS]\n", argv[0]);
|
printf ("Usage: %s [OPTIONS]\n", argv[0]);
|
||||||
printf("Options:\n");
|
printf ("Options:\n");
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int arg;
|
int arg;
|
||||||
bool quiet_output = false;
|
bool quiet_output = false;
|
||||||
const char *acLibnfcVersion = nfc_version();
|
size_t szFound;
|
||||||
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
|
|
||||||
// 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")) {
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
exit(EXIT_SUCCESS);
|
return EXIT_SUCCESS;
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
quiet_output = true;
|
quiet_output = true;
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
exit(EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
signal(SIGINT, (void (__cdecl *)(int)) intr_hdlr);
|
signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
|
||||||
#else
|
#else
|
||||||
signal(SIGINT, intr_hdlr);
|
signal (SIGINT, (void (*)()) intr_hdlr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nfc_context *context;
|
// Allocate memory to put the result of available devices listing
|
||||||
nfc_init(&context);
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
if (context == NULL) {
|
fprintf (stderr, "malloc() failed\n");
|
||||||
ERR("Unable to init libnfc (malloc)");
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
nfc_connstring connstrings[MAX_DEVICE_COUNT];
|
|
||||||
// List available devices
|
// List available devices
|
||||||
size_t szFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
||||||
|
|
||||||
if (szFound < 2) {
|
if (szFound < 2) {
|
||||||
ERR("%" PRIdPTR " device found but two opened devices are needed to relay NFC.", szFound);
|
ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound);
|
||||||
nfc_exit(context);
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to open the NFC emulator device
|
// Try to open the NFC emulator device
|
||||||
pndTag = nfc_open(context, connstrings[0]);
|
pndTag = nfc_connect (&(pnddDevices[0]));
|
||||||
if (pndTag == NULL) {
|
if (pndTag == NULL) {
|
||||||
ERR("Error opening NFC emulator device");
|
printf ("Error connecting NFC emulator device\n");
|
||||||
nfc_exit(context);
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n");
|
printf ("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n");
|
||||||
|
|
||||||
printf("NFC emulator device: %s opened\n", nfc_device_get_name(pndTag));
|
printf ("Connected to the NFC emulator device: %s\n", pndTag->acName);
|
||||||
printf("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
||||||
printf("[+] To do this, please send any command after the anti-collision\n");
|
printf ("[+] To do this, please send any command after the anti-collision\n");
|
||||||
printf("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
||||||
|
|
||||||
nfc_target nt = {
|
nfc_target_t nt = {
|
||||||
.nm = {
|
.nm = {
|
||||||
.nmt = NMT_ISO14443A,
|
.nmt = NMT_ISO14443A,
|
||||||
.nbr = NBR_UNDEFINED,
|
.nbr = NBR_UNDEFINED,
|
||||||
@ -154,7 +143,7 @@ main(int argc, char *argv[])
|
|||||||
.nti = {
|
.nti = {
|
||||||
.nai = {
|
.nai = {
|
||||||
.abtAtqa = { 0x04, 0x00 },
|
.abtAtqa = { 0x04, 0x00 },
|
||||||
.abtUid = { 0x08, 0xad, 0xbe, 0xef },
|
.abtUid = { 0xde, 0xad, 0xbe, 0xef },
|
||||||
.btSak = 0x20,
|
.btSak = 0x20,
|
||||||
.szUidLen = 4,
|
.szUidLen = 4,
|
||||||
.szAtsLen = 0,
|
.szAtsLen = 0,
|
||||||
@ -162,102 +151,73 @@ main(int argc, char *argv[])
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((szReaderRxBits = nfc_target_init(pndTag, &nt, abtReaderRx, sizeof(abtReaderRx), 0)) < 0) {
|
if (!nfc_target_init (pndTag, &nt, abtReaderRx, &szReaderRxBits)) {
|
||||||
ERR("%s", "Initialization of NFC emulator failed");
|
ERR ("%s", "Initialization of NFC emulator failed");
|
||||||
nfc_close(pndTag);
|
nfc_disconnect (pndTag);
|
||||||
nfc_exit(context);
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
printf("%s", "Configuring emulator settings...");
|
printf ("%s", "Configuring emulator settings...");
|
||||||
if ((nfc_device_set_property_bool(pndTag, NP_HANDLE_CRC, false) < 0) ||
|
if (!nfc_configure (pndTag, NDO_HANDLE_CRC, false) ||
|
||||||
(nfc_device_set_property_bool(pndTag, NP_HANDLE_PARITY, false) < 0) || (nfc_device_set_property_bool(pndTag, NP_ACCEPT_INVALID_FRAMES, true)) < 0) {
|
!nfc_configure (pndTag, NDO_HANDLE_PARITY, false) || !nfc_configure (pndTag, NDO_ACCEPT_INVALID_FRAMES, true)) {
|
||||||
nfc_perror(pndTag, "nfc_device_set_property_bool");
|
nfc_perror (pndTag, "nfc_configure");
|
||||||
nfc_close(pndTag);
|
exit (EXIT_FAILURE);
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
printf("%s", "Done, emulated tag is initialized");
|
printf ("%s", "Done, emulated tag is initialized");
|
||||||
|
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
pndReader = nfc_open(context, connstrings[1]);
|
pndReader = nfc_connect (&(pnddDevices[1]));
|
||||||
if (pndReader == NULL) {
|
|
||||||
printf("Error opening NFC reader device\n");
|
|
||||||
nfc_close(pndTag);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NFC reader device: %s opened", nfc_device_get_name(pndReader));
|
printf ("Connected to the NFC reader device: %s", pndReader->acName);
|
||||||
printf("%s", "Configuring NFC reader settings...");
|
printf ("%s", "Configuring NFC reader settings...");
|
||||||
|
nfc_initiator_init (pndReader);
|
||||||
if (nfc_initiator_init(pndReader) < 0) {
|
if (!nfc_configure (pndReader, NDO_HANDLE_CRC, false) ||
|
||||||
nfc_perror(pndReader, "nfc_initiator_init");
|
!nfc_configure (pndReader, NDO_HANDLE_PARITY, false) ||
|
||||||
nfc_close(pndTag);
|
!nfc_configure (pndReader, NDO_ACCEPT_INVALID_FRAMES, true)) {
|
||||||
nfc_close(pndReader);
|
nfc_perror (pndReader, "nfc_configure");
|
||||||
nfc_exit(context);
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
if ((nfc_device_set_property_bool(pndReader, NP_HANDLE_CRC, false) < 0) ||
|
printf ("%s", "Done, relaying frames now!");
|
||||||
(nfc_device_set_property_bool(pndReader, NP_HANDLE_PARITY, false) < 0) ||
|
|
||||||
(nfc_device_set_property_bool(pndReader, NP_ACCEPT_INVALID_FRAMES, true)) < 0) {
|
|
||||||
nfc_perror(pndReader, "nfc_device_set_property_bool");
|
|
||||||
nfc_close(pndTag);
|
|
||||||
nfc_close(pndReader);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
printf("%s", "Done, relaying frames now!");
|
|
||||||
|
|
||||||
while (!quitting) {
|
while (!quitting) {
|
||||||
// Test if we received a frame from the reader
|
// Test if we received a frame from the reader
|
||||||
if ((szReaderRxBits = nfc_target_receive_bits(pndTag, abtReaderRx, sizeof(abtReaderRx), abtReaderRxPar)) > 0) {
|
if (nfc_target_receive_bits (pndTag, abtReaderRx, &szReaderRxBits, abtReaderRxPar)) {
|
||||||
// Drop down the field before sending a REQA command and start a new session
|
// Drop down the field before sending a REQA command and start a new session
|
||||||
if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26) {
|
if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26) {
|
||||||
// Drop down field for a very short time (original tag will reboot)
|
// Drop down field for a very short time (original tag will reboot)
|
||||||
if (nfc_device_set_property_bool(pndReader, NP_ACTIVATE_FIELD, false) < 0) {
|
if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pndReader, "nfc_device_set_property_bool");
|
nfc_perror (pndReader, "nfc_configure");
|
||||||
nfc_close(pndTag);
|
exit (EXIT_FAILURE);
|
||||||
nfc_close(pndReader);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
if (!quiet_output)
|
if (!quiet_output)
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
if (nfc_device_set_property_bool(pndReader, NP_ACTIVATE_FIELD, true) < 0) {
|
if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pndReader, "nfc_device_set_property_bool");
|
nfc_perror (pndReader, "nfc_configure");
|
||||||
nfc_close(pndTag);
|
exit (EXIT_FAILURE);
|
||||||
nfc_close(pndReader);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Print the reader frame to the screen
|
// Print the reader frame to the screen
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("R: ");
|
printf ("R: ");
|
||||||
print_hex_par(abtReaderRx, (size_t) szReaderRxBits, abtReaderRxPar);
|
print_hex_par (abtReaderRx, szReaderRxBits, abtReaderRxPar);
|
||||||
}
|
}
|
||||||
// Forward the frame to the original tag
|
// Forward the frame to the original tag
|
||||||
if ((szTagRxBits = nfc_initiator_transceive_bits
|
if (nfc_initiator_transceive_bits
|
||||||
(pndReader, abtReaderRx, (size_t) szReaderRxBits, abtReaderRxPar, abtTagRx, sizeof(abtTagRx), abtTagRxPar)) > 0) {
|
(pndReader, abtReaderRx, szReaderRxBits, abtReaderRxPar, abtTagRx, &szTagRxBits, abtTagRxPar)) {
|
||||||
// Redirect the answer back to the reader
|
// Redirect the answer back to the reader
|
||||||
if (nfc_target_send_bits(pndTag, abtTagRx, szTagRxBits, abtTagRxPar) < 0) {
|
if (!nfc_target_send_bits (pndTag, abtTagRx, szTagRxBits, abtTagRxPar)) {
|
||||||
nfc_perror(pndTag, "nfc_target_send_bits");
|
nfc_perror (pndTag, "nfc_target_send_bits");
|
||||||
nfc_close(pndTag);
|
exit (EXIT_FAILURE);
|
||||||
nfc_close(pndReader);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
// Print the tag frame to the screen
|
// Print the tag frame to the screen
|
||||||
if (!quiet_output) {
|
if (!quiet_output) {
|
||||||
printf("T: ");
|
printf ("T: ");
|
||||||
print_hex_par(abtTagRx, szTagRxBits, abtTagRxPar);
|
print_hex_par (abtTagRx, szTagRxBits, abtTagRxPar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_close(pndTag);
|
nfc_disconnect (pndTag);
|
||||||
nfc_close(pndReader);
|
nfc_disconnect (pndReader);
|
||||||
nfc_exit(context);
|
exit (EXIT_SUCCESS);
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
721
examples/nfc-utils.c
Normal file
721
examples/nfc-utils.c
Normal file
@ -0,0 +1,721 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
|
static const byte_t OddParity[256] = {
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||||
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
byte_t
|
||||||
|
oddparity (const byte_t bt)
|
||||||
|
{
|
||||||
|
return OddParity[bt];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
|
||||||
|
{
|
||||||
|
size_t szByteNr;
|
||||||
|
// Calculate the parity bits for the command
|
||||||
|
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
||||||
|
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_hex (const byte_t * pbtData, const size_t szBytes)
|
||||||
|
{
|
||||||
|
size_t szPos;
|
||||||
|
|
||||||
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
|
printf ("%02x ", pbtData[szPos]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_hex_bits (const byte_t * pbtData, const size_t szBits)
|
||||||
|
{
|
||||||
|
uint8_t uRemainder;
|
||||||
|
size_t szPos;
|
||||||
|
size_t szBytes = szBits / 8;
|
||||||
|
|
||||||
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
|
printf ("%02x ", pbtData[szPos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uRemainder = szBits % 8;
|
||||||
|
// Print the rest bits
|
||||||
|
if (uRemainder != 0) {
|
||||||
|
if (uRemainder < 5)
|
||||||
|
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
|
else
|
||||||
|
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar)
|
||||||
|
{
|
||||||
|
uint8_t uRemainder;
|
||||||
|
size_t szPos;
|
||||||
|
size_t szBytes = szBits / 8;
|
||||||
|
|
||||||
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
|
printf ("%02x", pbtData[szPos]);
|
||||||
|
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
|
||||||
|
printf ("! ");
|
||||||
|
} else {
|
||||||
|
printf (" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uRemainder = szBits % 8;
|
||||||
|
// Print the rest bits, these cannot have parity bit
|
||||||
|
if (uRemainder != 0) {
|
||||||
|
if (uRemainder < 5)
|
||||||
|
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
|
else
|
||||||
|
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SAK_UID_NOT_COMPLETE 0x04
|
||||||
|
#define SAK_ISO14443_4_COMPLIANT 0x20
|
||||||
|
#define SAK_ISO18092_COMPLIANT 0x40
|
||||||
|
|
||||||
|
void
|
||||||
|
print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose)
|
||||||
|
{
|
||||||
|
printf (" ATQA (SENS_RES): ");
|
||||||
|
print_hex (nai.abtAtqa, 2);
|
||||||
|
if (verbose) {
|
||||||
|
printf("* UID size: ");
|
||||||
|
switch ((nai.abtAtqa[1] & 0xc0)>>6) {
|
||||||
|
case 0:
|
||||||
|
printf("single\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("double\n");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("triple\n");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
printf("RFU\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("* bit frame anticollision ");
|
||||||
|
switch (nai.abtAtqa[1] & 0x1f) {
|
||||||
|
case 0x01:
|
||||||
|
case 0x02:
|
||||||
|
case 0x04:
|
||||||
|
case 0x08:
|
||||||
|
case 0x10:
|
||||||
|
printf("supported\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("not supported\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
|
||||||
|
print_hex (nai.abtUid, nai.szUidLen);
|
||||||
|
if (verbose) {
|
||||||
|
if (nai.abtUid[0] == 0x08) {
|
||||||
|
printf ("* Random UID\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf (" SAK (SEL_RES): ");
|
||||||
|
print_hex (&nai.btSak, 1);
|
||||||
|
if (verbose) {
|
||||||
|
if (nai.btSak & SAK_UID_NOT_COMPLETE) {
|
||||||
|
printf ("* Warning! Cascade bit set: UID not complete\n");
|
||||||
|
}
|
||||||
|
if (nai.btSak & SAK_ISO14443_4_COMPLIANT) {
|
||||||
|
printf ("* Compliant with ISO/IEC 14443-4\n");
|
||||||
|
} else {
|
||||||
|
printf ("* Not compliant with ISO/IEC 14443-4\n");
|
||||||
|
}
|
||||||
|
if (nai.btSak & SAK_ISO18092_COMPLIANT) {
|
||||||
|
printf ("* Compliant with ISO/IEC 18092\n");
|
||||||
|
} else {
|
||||||
|
printf ("* Not compliant with ISO/IEC 18092\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nai.szAtsLen) {
|
||||||
|
printf (" ATS: ");
|
||||||
|
print_hex (nai.abtAts, nai.szAtsLen);
|
||||||
|
}
|
||||||
|
if (nai.szAtsLen && verbose) {
|
||||||
|
// Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select)
|
||||||
|
const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
|
||||||
|
printf ("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]);
|
||||||
|
|
||||||
|
size_t offset = 1;
|
||||||
|
if (nai.abtAts[0] & 0x10) { // TA(1) present
|
||||||
|
byte_t TA = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
printf ("* Bit Rate Capability:\n");
|
||||||
|
if (TA == 0) {
|
||||||
|
printf (" * PICC supports only 106 kbits/s in both directions\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<7) {
|
||||||
|
printf (" * Same bitrate in both directions mandatory\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<4) {
|
||||||
|
printf (" * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<5) {
|
||||||
|
printf (" * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<6) {
|
||||||
|
printf (" * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<0) {
|
||||||
|
printf (" * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<1) {
|
||||||
|
printf (" * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<2) {
|
||||||
|
printf (" * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (TA & 1<<3) {
|
||||||
|
printf (" * ERROR unknown value\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nai.abtAts[0] & 0x20) { // TB(1) present
|
||||||
|
byte_t TB= nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((TB & 0xf0) >> 4))/13560.0);
|
||||||
|
if ((TB & 0x0f) == 0) {
|
||||||
|
printf ("* No Start-up Frame Guard Time required\n");
|
||||||
|
} else {
|
||||||
|
printf ("* Start-up Frame Guard Time: %.4g ms\n",256.0*16.0*(1<<(TB & 0x0f))/13560.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nai.abtAts[0] & 0x40) { // TC(1) present
|
||||||
|
byte_t TC = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
if (TC & 0x1) {
|
||||||
|
printf("* Node ADdress supported\n");
|
||||||
|
} else {
|
||||||
|
printf("* Node ADdress not supported\n");
|
||||||
|
}
|
||||||
|
if (TC & 0x2) {
|
||||||
|
printf("* Card IDentifier supported\n");
|
||||||
|
} else {
|
||||||
|
printf("* Card IDentifier not supported\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nai.szAtsLen > offset) {
|
||||||
|
printf ("* Historical bytes Tk: " );
|
||||||
|
print_hex (nai.abtAts + offset, (nai.szAtsLen - offset));
|
||||||
|
byte_t CIB = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) {
|
||||||
|
printf(" * Proprietary format\n");
|
||||||
|
if (CIB == 0xc1) {
|
||||||
|
printf(" * Tag byte: Mifare or virtual cards of various types\n");
|
||||||
|
byte_t L = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
if (L != (nai.szAtsLen - offset)) {
|
||||||
|
printf(" * Warning: Type Identification Coding length (%i)", L);
|
||||||
|
printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset));
|
||||||
|
}
|
||||||
|
if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes
|
||||||
|
byte_t CTC = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
printf(" * Chip Type: ");
|
||||||
|
switch (CTC & 0xf0) {
|
||||||
|
case 0x00:
|
||||||
|
printf("(Multiple) Virtual Cards\n");
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
printf("Mifare DESFire\n");
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
printf("Mifare Plus\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("RFU\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(" * Memory size: ");
|
||||||
|
switch (CTC & 0x0f) {
|
||||||
|
case 0x00:
|
||||||
|
printf("<1 kbyte\n");
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
printf("1 kbyte\n");
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
printf("2 kbyte\n");
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
printf("4 kbyte\n");
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
printf("8 kbyte\n");
|
||||||
|
break;
|
||||||
|
case 0x0f:
|
||||||
|
printf("Unspecified\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("RFU\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
|
||||||
|
byte_t CVC = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
printf(" * Chip Status: ");
|
||||||
|
switch (CVC & 0xf0) {
|
||||||
|
case 0x00:
|
||||||
|
printf("Engineering sample\n");
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
printf("Released\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("RFU\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(" * Chip Generation: ");
|
||||||
|
switch (CVC & 0x0f) {
|
||||||
|
case 0x00:
|
||||||
|
printf("Generation 1\n");
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
printf("Generation 2\n");
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
printf("Generation 3\n");
|
||||||
|
break;
|
||||||
|
case 0x0f:
|
||||||
|
printf("Unspecified\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("RFU\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
|
||||||
|
byte_t VCS = nai.abtAts[offset];
|
||||||
|
offset++;
|
||||||
|
printf(" * Specifics (Virtual Card Selection):\n");
|
||||||
|
if ((VCS & 0x09) == 0x00) {
|
||||||
|
printf(" * Only VCSL supported\n");
|
||||||
|
} else if ((VCS & 0x09) == 0x01) {
|
||||||
|
printf(" * VCS, VCSL and SVC supported\n");
|
||||||
|
}
|
||||||
|
if ((VCS & 0x0e) == 0x00) {
|
||||||
|
printf(" * SL1, SL2(?), SL3 supported\n");
|
||||||
|
} else if ((VCS & 0x0e) == 0x02) {
|
||||||
|
printf(" * SL3 only card\n");
|
||||||
|
} else if ((VCS & 0x0f) == 0x0e) {
|
||||||
|
printf(" * No VCS command supported\n");
|
||||||
|
} else if ((VCS & 0x0f) == 0x0f) {
|
||||||
|
printf(" * Unspecified\n");
|
||||||
|
} else {
|
||||||
|
printf(" * RFU\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (CIB == 0x00) {
|
||||||
|
printf(" * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n");
|
||||||
|
printf(" followed by a mandatory status indicator (the last three bytes, not in TLV)\n");
|
||||||
|
printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
|
||||||
|
}
|
||||||
|
if (CIB == 0x10) {
|
||||||
|
printf(" * DIR data reference: %02x\n", nai.abtAts[offset]);
|
||||||
|
}
|
||||||
|
if (CIB == 0x80) {
|
||||||
|
if (nai.szAtsLen == offset) {
|
||||||
|
printf(" * No COMPACT-TLV objects found, no status found\n");
|
||||||
|
} else {
|
||||||
|
printf(" * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n");
|
||||||
|
printf(" the last data object may carry a status indicator of one, two or three bytes.\n");
|
||||||
|
printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
printf("Fingerprinting based on ATQA & SAK values:\n");
|
||||||
|
uint32_t atqasak = 0;
|
||||||
|
atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff)<<16);
|
||||||
|
atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff)<<8);
|
||||||
|
atqasak += ((uint32_t)nai.btSak & 0xff);
|
||||||
|
bool found_possible_match = false;
|
||||||
|
switch (atqasak) {
|
||||||
|
case 0x000218:
|
||||||
|
printf("* Mifare Classic 4K\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000408:
|
||||||
|
printf("* Mifare Classic 1K\n");
|
||||||
|
printf("* Mifare Plus (4-byte UID) 2K SL1\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000409:
|
||||||
|
printf("* Mifare MINI\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000410:
|
||||||
|
printf("* Mifare Plus (4-byte UID) 2K SL2\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000411:
|
||||||
|
printf("* Mifare Plus (4-byte UID) 4K SL2\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000418:
|
||||||
|
printf("* Mifare Plus (4-byte UID) 4K SL1\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000420:
|
||||||
|
printf("* Mifare Plus (4-byte UID) 2K/4K SL3\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004400:
|
||||||
|
printf("* Mifare Ultralight\n");
|
||||||
|
printf("* Mifare UltralightC\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004208:
|
||||||
|
case 0x004408:
|
||||||
|
printf("* Mifare Plus (7-byte UID) 2K SL1\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004218:
|
||||||
|
case 0x004418:
|
||||||
|
printf("* Mifare Plus (7-byte UID) 4K SL1\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004210:
|
||||||
|
case 0x004410:
|
||||||
|
printf("* Mifare Plus (7-byte UID) 2K SL2\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004211:
|
||||||
|
case 0x004411:
|
||||||
|
printf("* Mifare Plus (7-byte UID) 4K SL2\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004220:
|
||||||
|
case 0x004420:
|
||||||
|
printf("* Mifare Plus (7-byte UID) 2K/4K SL3\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x034420:
|
||||||
|
printf("* Mifare DESFire / Desfire EV1\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other matches not described in
|
||||||
|
// AN MIFARE Type Identification Procedure
|
||||||
|
// but seen in the field:
|
||||||
|
switch (atqasak) {
|
||||||
|
case 0x000488:
|
||||||
|
printf("* Mifare Classic 1K Infineon\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000298:
|
||||||
|
printf("* Gemplus MPCOS\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x030428:
|
||||||
|
printf("* JCOP31\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x004820:
|
||||||
|
printf("* JCOP31 v2.4.1\n");
|
||||||
|
printf("* JCOP31 v2.2\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000428:
|
||||||
|
printf("* JCOP31 v2.3.1\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000453:
|
||||||
|
printf("* Fudan FM1208SH01\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000820:
|
||||||
|
printf("* Fudan FM1208\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000238:
|
||||||
|
printf("* MFC 4K emulated by Nokia 6212 Classic\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x000838:
|
||||||
|
printf("* MFC 4K emulated by Nokia 6131 NFC\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((nai.abtAtqa[0] & 0xf0) == 0) {
|
||||||
|
switch (nai.abtAtqa[1]) {
|
||||||
|
case 0x02:
|
||||||
|
printf("* SmartMX with Mifare 4K emulation\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
printf("* SmartMX with Mifare 1K emulation\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
case 0x48:
|
||||||
|
printf("* SmartMX with 7-byte UID\n");
|
||||||
|
found_possible_match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! found_possible_match) {
|
||||||
|
printf("* Unknown card, sorry\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
|
||||||
|
{
|
||||||
|
(void) verbose;
|
||||||
|
printf (" ID (NFCID2): ");
|
||||||
|
print_hex (nfi.abtId, 8);
|
||||||
|
printf (" Parameter (PAD): ");
|
||||||
|
print_hex (nfi.abtPad, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose)
|
||||||
|
{
|
||||||
|
(void) verbose;
|
||||||
|
printf (" ATQA (SENS_RES): ");
|
||||||
|
print_hex (nji.btSensRes, 2);
|
||||||
|
printf (" 4-LSB JEWELID: ");
|
||||||
|
print_hex (nji.btId, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PI_ISO14443_4_SUPPORTED 0x01
|
||||||
|
#define PI_NAD_SUPPORTED 0x01
|
||||||
|
#define PI_CID_SUPPORTED 0x02
|
||||||
|
void
|
||||||
|
print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose)
|
||||||
|
{
|
||||||
|
const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
|
||||||
|
printf (" PUPI: ");
|
||||||
|
print_hex (nbi.abtPupi, 4);
|
||||||
|
printf (" Application Data: ");
|
||||||
|
print_hex (nbi.abtApplicationData, 4);
|
||||||
|
printf (" Protocol Info: ");
|
||||||
|
print_hex (nbi.abtProtocolInfo, 3);
|
||||||
|
if (verbose) {
|
||||||
|
printf ("* Bit Rate Capability:\n");
|
||||||
|
if (nbi.abtProtocolInfo[0] == 0) {
|
||||||
|
printf (" * PICC supports only 106 kbits/s in both directions\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<7) {
|
||||||
|
printf (" * Same bitrate in both directions mandatory\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<4) {
|
||||||
|
printf (" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<5) {
|
||||||
|
printf (" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<6) {
|
||||||
|
printf (" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<0) {
|
||||||
|
printf (" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<1) {
|
||||||
|
printf (" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<2) {
|
||||||
|
printf (" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n");
|
||||||
|
}
|
||||||
|
if (nbi.abtProtocolInfo[0] & 1<<3) {
|
||||||
|
printf (" * ERROR unknown value\n");
|
||||||
|
}
|
||||||
|
if( (nbi.abtProtocolInfo[1] & 0xf0) <= 0x80 ) {
|
||||||
|
printf ("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]);
|
||||||
|
}
|
||||||
|
if((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) {
|
||||||
|
printf ("* Protocol types supported: ISO/IEC 14443-4\n");
|
||||||
|
}
|
||||||
|
printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((nbi.abtProtocolInfo[2] & 0xf0) >> 4))/13560.0);
|
||||||
|
if((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED|PI_CID_SUPPORTED)) != 0) {
|
||||||
|
printf ("* Frame options supported: ");
|
||||||
|
if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf ("NAD ");
|
||||||
|
if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf ("CID ");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose)
|
||||||
|
{
|
||||||
|
(void) verbose;
|
||||||
|
printf (" NFCID3: ");
|
||||||
|
print_hex (ndi.abtNFCID3, 10);
|
||||||
|
printf (" BS: %02x\n", ndi.btBS);
|
||||||
|
printf (" BR: %02x\n", ndi.btBR);
|
||||||
|
printf (" TO: %02x\n", ndi.btTO);
|
||||||
|
printf (" PP: %02x\n", ndi.btPP);
|
||||||
|
if (ndi.szGB) {
|
||||||
|
printf ("General Bytes: ");
|
||||||
|
print_hex (ndi.abtGB, ndi.szGB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tries to parse arguments to find device descriptions.
|
||||||
|
* @return Returns the list of found device descriptions.
|
||||||
|
*/
|
||||||
|
nfc_device_desc_t *
|
||||||
|
parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose)
|
||||||
|
{
|
||||||
|
nfc_device_desc_t *pndd = 0;
|
||||||
|
int arg;
|
||||||
|
*szFound = 0;
|
||||||
|
|
||||||
|
// Get commandline options
|
||||||
|
for (arg = 1; arg < argc; arg++) {
|
||||||
|
|
||||||
|
if (0 == strcmp (argv[arg], "--device")) {
|
||||||
|
// FIXME: this device selection by command line options is terrible & does not support USB/PCSC drivers
|
||||||
|
if (argc > arg + 1) {
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
pndd = malloc (sizeof (nfc_device_desc_t));
|
||||||
|
|
||||||
|
strncpy (buffer, argv[++arg], 256);
|
||||||
|
|
||||||
|
// Driver.
|
||||||
|
pndd->pcDriver = (char *) malloc (256);
|
||||||
|
strcpy (pndd->pcDriver, strtok (buffer, ":"));
|
||||||
|
|
||||||
|
// Port.
|
||||||
|
pndd->pcPort = (char *) malloc (256);
|
||||||
|
strcpy (pndd->pcPort, strtok (NULL, ":"));
|
||||||
|
|
||||||
|
// Speed.
|
||||||
|
sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed);
|
||||||
|
|
||||||
|
*szFound = 1;
|
||||||
|
} else {
|
||||||
|
errx (1, "usage: %s [--device driver:port:speed]", argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((0 == strcmp (argv[arg], "-v")) || (0 == strcmp (argv[arg], "--verbose"))) {
|
||||||
|
*verbose = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pndd;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
str_nfc_baud_rate (const nfc_baud_rate_t nbr)
|
||||||
|
{
|
||||||
|
switch(nbr) {
|
||||||
|
case NBR_UNDEFINED:
|
||||||
|
return "undefined baud rate";
|
||||||
|
break;
|
||||||
|
case NBR_106:
|
||||||
|
return "106 kbps";
|
||||||
|
break;
|
||||||
|
case NBR_212:
|
||||||
|
return "212 kbps";
|
||||||
|
break;
|
||||||
|
case NBR_424:
|
||||||
|
return "424 kbps";
|
||||||
|
break;
|
||||||
|
case NBR_847:
|
||||||
|
return "847 kbps";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_nfc_target (const nfc_target_t nt, bool verbose)
|
||||||
|
{
|
||||||
|
switch(nt.nm.nmt) {
|
||||||
|
case NMT_ISO14443A:
|
||||||
|
printf ("ISO/IEC 14443A (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||||
|
print_nfc_iso14443a_info (nt.nti.nai, verbose);
|
||||||
|
break;
|
||||||
|
case NMT_JEWEL:
|
||||||
|
printf ("Innovision Jewel (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||||
|
print_nfc_jewel_info (nt.nti.nji, verbose);
|
||||||
|
break;
|
||||||
|
case NMT_FELICA:
|
||||||
|
printf ("FeliCa (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||||
|
print_nfc_felica_info (nt.nti.nfi, verbose);
|
||||||
|
break;
|
||||||
|
case NMT_ISO14443B:
|
||||||
|
printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||||
|
print_nfc_iso14443b_info (nt.nti.nbi, verbose);
|
||||||
|
break;
|
||||||
|
case NMT_DEP:
|
||||||
|
printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||||
|
print_nfc_dep_info (nt.nti.ndi, verbose);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,14 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2009 Roel Verdult
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -85,20 +79,21 @@
|
|||||||
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MIN
|
byte_t oddparity (const byte_t bt);
|
||||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar);
|
||||||
#endif
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t oddparity(const uint8_t bt);
|
void print_hex (const byte_t * pbtData, const size_t szLen);
|
||||||
void oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar);
|
void print_hex_bits (const byte_t * pbtData, const size_t szBits);
|
||||||
|
void print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar);
|
||||||
|
|
||||||
void print_hex(const uint8_t *pbtData, const size_t szLen);
|
void print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose);
|
||||||
void print_hex_bits(const uint8_t *pbtData, const size_t szBits);
|
void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose);
|
||||||
void print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar);
|
void print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose);
|
||||||
|
void print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose);
|
||||||
|
void print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose);
|
||||||
|
|
||||||
void print_nfc_target(const nfc_target *pnt, bool verbose);
|
void print_nfc_target (const nfc_target_t nt, bool verbose);
|
||||||
|
|
||||||
|
nfc_device_desc_t *parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1,4 +1,4 @@
|
|||||||
.TH pn53x-diagnose 1 "June 15, 2010" "libnfc" "libnfc's examples"
|
.TH PN53X-DIAGNOSE 1 "June 15, 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
pn53x-diagnose \- PN53x diagnose tool
|
pn53x-diagnose \- PN53x diagnose tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -11,17 +11,13 @@ It runs communication, RAM and ROM tests.
|
|||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report any bugs on the
|
Please report any bugs on the
|
||||||
.B libnfc
|
.B libnfc
|
||||||
issue tracker at:
|
forum at
|
||||||
.br
|
.BR http://www.libnfc.org/community/ "."
|
||||||
.BR https://github.com/nfc-tools/libnfc/issues
|
|
||||||
.SH LICENCE
|
.SH LICENCE
|
||||||
.B libnfc
|
.B libnfc
|
||||||
is licensed under the GNU Lesser General Public License (LGPL), version 3.
|
|
||||||
.br
|
|
||||||
.B libnfc-utils
|
|
||||||
and
|
and
|
||||||
.B libnfc-examples
|
.B libnfc-examples
|
||||||
are covered by the the BSD 2-Clause license.
|
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Romuald Conty <romuald@libnfc.org>
|
Romuald Conty <romuald@libnfc.org>
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@ -1,14 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Libnfc historical contributors:
|
* Copyright (C) 2010, Romuald Conty
|
||||||
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -38,101 +31,84 @@
|
|||||||
* @file pn53x-diagnose.c
|
* @file pn53x-diagnose.c
|
||||||
* @brief Small application to diagnose PN53x using dedicated commands
|
* @brief Small application to diagnose PN53x using dedicated commands
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "utils/nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
#include "libnfc/chips/pn53x.h"
|
#include "chips/pn53x.h"
|
||||||
|
#include "chips/pn53x-internal.h"
|
||||||
|
|
||||||
#define MAX_DEVICE_COUNT 16
|
#define MAX_DEVICE_COUNT 16
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
|
size_t szFound;
|
||||||
size_t i;
|
size_t i;
|
||||||
nfc_device *pnd = NULL;
|
nfc_device_t *pnd;
|
||||||
|
nfc_device_desc_t *pnddDevices;
|
||||||
const char *acLibnfcVersion;
|
const char *acLibnfcVersion;
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
||||||
size_t szRx = sizeof(abtRx);
|
size_t szRx = sizeof(abtRx);
|
||||||
const uint8_t pncmd_diagnose_communication_line_test[] = { Diagnose, 0x00, 0x06, 'l', 'i', 'b', 'n', 'f', 'c' };
|
const byte_t pncmd_diagnose_communication_line_test[] = { Diagnose, 0x00, 0x06, 'l', 'i', 'b', 'n', 'f', 'c' };
|
||||||
const uint8_t pncmd_diagnose_rom_test[] = { Diagnose, 0x01 };
|
const byte_t pncmd_diagnose_rom_test[] = { Diagnose, 0x01 };
|
||||||
const uint8_t pncmd_diagnose_ram_test[] = { Diagnose, 0x02 };
|
const byte_t pncmd_diagnose_ram_test[] = { Diagnose, 0x02 };
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
printf("Usage: %s", argv[0]);
|
errx (1, "usage: %s", argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_context *context;
|
|
||||||
nfc_init(&context);
|
|
||||||
if (context == NULL) {
|
|
||||||
ERR("Unable to init libnfc (malloc)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
acLibnfcVersion = nfc_version();
|
acLibnfcVersion = nfc_version ();
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
nfc_connstring connstrings[MAX_DEVICE_COUNT];
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
size_t szFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);
|
fprintf (stderr, "malloc() failed\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
||||||
|
|
||||||
if (szFound == 0) {
|
if (szFound == 0) {
|
||||||
printf("No NFC device found.\n");
|
printf ("No NFC device found.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < szFound; i++) {
|
for (i = 0; i < szFound; i++) {
|
||||||
int res = 0;
|
pnd = nfc_connect (&(pnddDevices[i]));
|
||||||
pnd = nfc_open(context, connstrings[i]);
|
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
ERR("%s", "Unable to open NFC device.");
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
nfc_exit(context);
|
return EXIT_FAILURE;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("NFC device [%s] opened.\n", nfc_device_get_name(pnd));
|
printf ("NFC device [%s] connected.\n", pnd->acName);
|
||||||
|
|
||||||
res = pn53x_transceive(pnd, pncmd_diagnose_communication_line_test, sizeof(pncmd_diagnose_communication_line_test), abtRx, szRx, 0);
|
result = pn53x_transceive (pnd, pncmd_diagnose_communication_line_test, sizeof (pncmd_diagnose_communication_line_test), abtRx, &szRx);
|
||||||
if (res > 0) {
|
if (result) {
|
||||||
szRx = (size_t) res;
|
result = (memcmp (pncmd_diagnose_communication_line_test + 1, abtRx, sizeof (pncmd_diagnose_communication_line_test) - 1) == 0);
|
||||||
// Result of Diagnose ping for RC-S360 doesn't contain status byte so we've to handle both cases
|
|
||||||
result = (memcmp(pncmd_diagnose_communication_line_test + 1, abtRx, sizeof(pncmd_diagnose_communication_line_test) - 1) == 0) ||
|
|
||||||
(memcmp(pncmd_diagnose_communication_line_test + 2, abtRx, sizeof(pncmd_diagnose_communication_line_test) - 2) == 0);
|
|
||||||
printf(" Communication line test: %s\n", result ? "OK" : "Failed");
|
|
||||||
} else {
|
} else {
|
||||||
nfc_perror(pnd, "pn53x_transceive: cannot diagnose communication line");
|
nfc_perror (pnd, "pn53x_transceive");
|
||||||
}
|
}
|
||||||
|
printf (" Communication line test: %s\n", result ? "OK" : "Failed");
|
||||||
|
|
||||||
res = pn53x_transceive(pnd, pncmd_diagnose_rom_test, sizeof(pncmd_diagnose_rom_test), abtRx, szRx, 0);
|
result = pn53x_transceive (pnd, pncmd_diagnose_rom_test, sizeof (pncmd_diagnose_rom_test), abtRx, &szRx);
|
||||||
if (res > 0) {
|
if (result) {
|
||||||
szRx = (size_t) res;
|
|
||||||
result = ((szRx == 1) && (abtRx[0] == 0x00));
|
result = ((szRx == 1) && (abtRx[0] == 0x00));
|
||||||
printf(" ROM test: %s\n", result ? "OK" : "Failed");
|
|
||||||
} else {
|
} else {
|
||||||
nfc_perror(pnd, "pn53x_transceive: cannot diagnose ROM");
|
nfc_perror (pnd, "pn53x_transceive");
|
||||||
}
|
}
|
||||||
|
printf (" ROM test: %s\n", result ? "OK" : "Failed");
|
||||||
|
|
||||||
res = pn53x_transceive(pnd, pncmd_diagnose_ram_test, sizeof(pncmd_diagnose_ram_test), abtRx, szRx, 0);
|
result = pn53x_transceive (pnd, pncmd_diagnose_ram_test, sizeof (pncmd_diagnose_ram_test), abtRx, &szRx);
|
||||||
if (res > 0) {
|
if (result) {
|
||||||
szRx = (size_t) res;
|
|
||||||
result = ((szRx == 1) && (abtRx[0] == 0x00));
|
result = ((szRx == 1) && (abtRx[0] == 0x00));
|
||||||
printf(" RAM test: %s\n", result ? "OK" : "Failed");
|
|
||||||
} else {
|
} else {
|
||||||
nfc_perror(pnd, "pn53x_transceive: cannot diagnose RAM");
|
nfc_perror (pnd, "pn53x_transceive");
|
||||||
}
|
}
|
||||||
|
printf (" RAM test: %s\n", result ? "OK" : "Failed");
|
||||||
}
|
}
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user