Codebase list libfreefare / c163eba
Update upstream source from tag 'upstream/1.8.0' Update to upstream version '1.8.0' with Debian dir d55986ebfe909ecafd716162860c9bcaf7d72d17 Ludovic Rousseau 3 years ago
113 changed file(s) with 7344 addition(s) and 2483 deletion(s). Raw diff Collapse all Expand all
0 **/.deps/
1 **/.libs/
2 **/Makefile
3 **/Makefile.in
4 *.exe
5 *.la
6 *.lo
7 *.o
08 *~
19 Doxyfile
210 INSTALL
3 Makefile
4 Makefile.in
511 aclocal.m4
612 ar-lib
713 autom4te.cache/
814 build
9 cmake/Makefile
10 cmake/Makefile.in
11 cmake/modules/Makefile
12 cmake/modules/Makefile.in
15 compile
1316 config.guess
1417 config.h
1518 config.h.in
1720 config.status
1821 config.sub
1922 configure
20 contrib/Makefile
21 contrib/Makefile.in
22 contrib/devd/Makefile
23 contrib/devd/Makefile.in
24 contrib/udev/Makefile
25 contrib/udev/Makefile.in
26 contrib/win32/Makefile
27 contrib/win32/Makefile.in
28 contrib/win32/sys/Makefile
29 contrib/win32/sys/Makefile.in
3023 debian/
3124 depcomp
32 examples/*.o
33 examples/.deps/
34 examples/.libs/
35 examples/Makefile
36 examples/Makefile.in
37 examples/doc/.deps/
3825 examples/nfc-anticol
3926 examples/nfc-dep-initiator
4027 examples/nfc-dep-target
4734 examples/pn53x-diagnose
4835 examples/pn53x-sam
4936 examples/pn53x-tamashell
50 examples/pn53x-tamashell-scripts/Makefile
51 examples/pn53x-tamashell-scripts/Makefile.in
5237 examples/quick_start_example1
5338 examples/quick_start_example2
54 include/Makefile
55 include/Makefile.in
56 include/nfc/Makefile
57 include/nfc/Makefile.in
5839 install-sh
5940 libnfc.pc
60 libnfc/*.lo
61 libnfc/*.o
62 libnfc/.deps/
63 libnfc/.libs/
64 libnfc/Makefile
65 libnfc/Makefile.in
66 libnfc/buses/*.la
67 libnfc/buses/*.lo
68 libnfc/buses/*.o
69 libnfc/buses/.deps/
70 libnfc/buses/.libs/
71 libnfc/buses/Makefile
72 libnfc/buses/Makefile.in
73 libnfc/chips/*.la
74 libnfc/chips/*.lo
75 libnfc/chips/*.o
76 libnfc/chips/.deps/
77 libnfc/chips/.libs/
78 libnfc/chips/Makefile
79 libnfc/chips/Makefile.in
80 libnfc/drivers/*.la
81 libnfc/drivers/*.lo
82 libnfc/drivers/*.o
83 libnfc/drivers/.deps/
84 libnfc/drivers/.libs/
85 libnfc/drivers/Makefile
86 libnfc/drivers/Makefile.in
87 libnfc/libnfc.la
8841 libtool
8942 ltmain.sh
9043 m4/libtool.m4
9447 m4/lt~obsolete.m4
9548 missing
9649 stamp-h1
97 test/*.la
98 test/*.lo
99 test/*.o
100 test/.deps/
101 test/.libs/
102 test/Makefile
103 test/Makefile.in
104 utils/*.la
105 utils/*.lo
106 utils/*.o
107 utils/.deps/
108 utils/.libs/
109 utils/Makefile
110 utils/Makefile.in
50 test-driver
51 test/run-test.sh.log
52 test/run-test.sh.trs
53 test/test-suite.log
11154 utils/nfc-emulate-forum-tag4
55 utils/nfc-jewel
11256 utils/nfc-list
11357 utils/nfc-mfclassic
11458 utils/nfc-mfultralight
0 language: c
1
2 compiler:
3 - clang
4 - gcc
5
6 env:
7 - BLD=cmake
8 - BLD=autoconf
9
10 addons:
11 apt:
12 packages:
13 - libusb-dev
14 - doxygen
15 - cmake
16
17 script:
18 - if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi
19 - if [ $BLD == cmake ]; then mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install; fi
11 Adam Laurie <adam@algroup.co.uk>
22 Ahti Legonkov <ahti.legonkov@gmail.com>
33 Alex Lian <alian@alum.mit.edu>
4 Alexander Inyukhin <shurick@sectorb.msk.ru>
45 Anugrah Redja Kusuma <anugrah.redja@gmail.com>
56 Audrey Diacre <adiacre@il4p.fr>
7 Boris Moiseev <cyberbobs@gmail.com>
8 Christoph Gritschenberger <christoph.gritschenberger@gmail.com>
9 Dario Carluccio <dario.carluccio@gmail.com>
10 David Kreitschmann <david@kreitschmann.de>
611 Emanuele Bertoldi <emanuele.bertoldi@gmail.com>
12 Emmanuel Dreyfus <manu@netbsd.org>
713 Eugeny Boger <eugenyboger@gmail.com>
814 Francois Kooman <fkooman@tuxed.net>
15 Frank Morgner <frankmorgner@gmail.com>
16 Frédéric Bourgeois <bourgeoislab@gmail.com>
17 Hidde Wieringa <hidde@hiddewieringa.nl>
18 Jairo Andres Suarez <andres4005@gmail.com>
919 Jiapeng Li <gapleehit@gmail.com>
20 Jim Anastassiou <jim.anastassiou@gmail.com>
21 John Galt <centromere@users.noreply.github.com>
22 Julien Ehrhart <julien.ehrhart@live.com>
1023 Julien Schueller <julien.schueller@gmail.com>
1124 Laurent Latil <laurent@latil.nom.fr>
1225 Ludovic Rousseau <ludovic.rousseau@gmail.com>
1326 Marcello Morena <marcello.morena@gmail.com>
27 Marcos Vives Del Sol <socram8888@gmail.com>
28 Mati Vait <mativait@gmail.com>
29 Maxim Martyanov <llorephie@gmail.com>
1430 Mike Auty <mike.auty@gmail.com>
1531 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
32 Olliver Schinagl <oliver@schinagl.nl>
33 Paul Menzel <paul.menzel@giantmonkey.de>
1634 Peter Meerwald <pmeerw@pmeerw.net>
1735 Philippe Teuwen <yobibe@gmail.com>
1836 Pim 't Hart <pimmeyproductions@gmail.com>
37 Ray Lee <rayleesky@outlook.com>
1938 Roel Verdult <roel@libnfc.org>
2039 Romain Tartiere <romain.tartiere@gmail.com>
2140 Romuald Conty <romuald@libnfc.org>
41 Simon Yorkston <simon.yorkston@gmail.com>
42 bhack <s.fabri@email.it>
2243 lego <lego@debian-fresh.prx>
44 quantum-x <simon.yorkston@gmail.com>
45 timzi <developers@make-gadget.ru>
46 xantares <xantares09@hotmail.com>
47 xaqq <kapp.arno@gmail.com>
48 yerzhanm <yerzhan.mukhamejan@gmail.com>
0 PROJECT(libnfc C)
1 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
0 cmake_minimum_required (VERSION 2.6)
1
2 if (NOT DEFINED CMAKE_BUILD_TYPE)
3 set (CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
4 endif ()
5
6 project (libnfc C)
7
28 SET(VERSION_MAJOR "1")
3 SET(VERSION_MINOR "7")
4 SET(VERSION_PATCH "1")
9 SET(VERSION_MINOR "8")
10 SET(VERSION_PATCH "0")
511
612 SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
713
1117
1218 # config.h
1319 IF(WIN32)
14 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
20 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
1521 SET(LIBNFC_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/config" CACHE PATH "libnfc configuration directory")
1622 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32)
1723 ELSE(WIN32)
1824 SET(_XOPEN_SOURCE 600)
1925 SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
20 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
21 ENDIF(WIN32)
26 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
27 ENDIF(WIN32)
28 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
2229
2330 ADD_DEFINITIONS("-DHAVE_CONFIG_H")
2431
2532 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)
2633
2734 # make it easy to locate CMake modules for finding libraries
28 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
35 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/")
2936
3037 # Options
31 SET(LIBNFC_LOG ON CACHE BOOL "Enable log facility (errors, warning, info and debug messages)")
38 option (LIBNFC_LOG "Enable log facility (errors, warning, info and debug messages)" ON)
3239 IF(LIBNFC_LOG)
3340 ADD_DEFINITIONS(-DLOG)
3441 ENDIF(LIBNFC_LOG)
3542
36 SET(LIBNFC_ENVVARS ON CACHE BOOL "Enable envvars facility")
43 option (LIBNFC_ENVVARS "Enable envvars facility" ON)
3744 IF(LIBNFC_ENVVARS)
3845 ADD_DEFINITIONS(-DENVVARS)
3946 ENDIF(LIBNFC_ENVVARS)
4855 SET(WIN32_MODE "release")
4956 ENDIF(LIBNFC_DEBUG_MODE)
5057
51 SET(LIBNFC_CONFFILES_MODE ON CACHE BOOL "Enable configuration files")
58 option (LIBNFC_CONFFILES_MODE "Enable configuration files" ON)
5259 IF(LIBNFC_CONFFILES_MODE)
5360 ADD_DEFINITIONS(-DCONFFILES)
5461 ENDIF(LIBNFC_CONFFILES_MODE)
62
63 option (BUILD_EXAMPLES "build examples ON/OFF" ON)
64 option (BUILD_UTILS "build utils ON/OFF" ON)
65
66 option (BUILD_DEBPKG "build debian package ON/OFF" OFF)
67
5568
5669 # Doxygen
5770 SET(builddir "${CMAKE_BINARY_DIR}")
8699 ADD_DEFINITIONS(-Du_int8_t=uint8_t -Du_int16_t=uint16_t)
87100
88101 IF(MINGW)
89 # force MinGW-w64 in 32bit mode
90 SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
91 SET(CMAKE_MODULE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
92 SET(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
93 SET(CMAKE_EXE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}")
94 SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}")
102 IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
103 # force MinGW-w64 in 32bit mode
104 SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
105 SET(CMAKE_MODULE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
106 SET(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
107 SET(CMAKE_EXE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}")
108 SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}")
109 ELSE(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
110 IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
111 # force MinGW-w64 in 32bit mode
112 MESSAGE("Building 32-bit Windows DLL")
113 #SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}")
114 #SET(CMAKE_MODULE_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
115 #SET(CMAKE_SHARED_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}")
116 #SET(CMAKE_EXE_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}")
117 SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}")
118 ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
119 MESSAGE("Building 64-bit Windows DLL")
120 SET(CMAKE_RC_FLAGS "--target=pe-x86-64 --output-format=coff ${CMAKE_RC_FLAGS}")
121 ELSE(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
122 MESSAGE(FATAL_ERROR "Unknown Processor: ${CMAKE_SYSTEM_PROCESSOR}")
123 ENDIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
124 ENDIF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
125
126 FIND_PROGRAM(DLLTOOL dlltool CMAKE_FIND_ROOT_PATH_BOTH)
127 IF (NOT DLLTOOL)
128 MESSAGE(FATAL_ERROR "Could not find dlltool command")
129 ENDIF (NOT DLLTOOL)
95130 ENDIF(MINGW)
96131
97132 IF(NOT WIN32)
102137 IF(LIBNFC_DRIVER_PN53X_USB)
103138 SET(PKG_REQ ${PKG_REQ} "libusb")
104139 ENDIF(LIBNFC_DRIVER_PN53X_USB)
105 IF(LIBNFC_DRIVER_ACR122)
140 IF(LIBNFC_DRIVER_PCSC)
106141 SET(PKG_REQ ${PKG_REQ} "libpcsclite")
107142 ENDIF(LIBNFC_DRIVER_ACR122)
143 IF(LIBNFC_DRIVER_ACR122_PCSC)
144 SET(PKG_REQ ${PKG_REQ} "libpcsclite")
145 ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
108146 # CMake lists are separated by a semi colon, replace with colon
109147 STRING(REPLACE ";" "," PKG_CONFIG_REQUIRES "${PKG_REQ}")
110148 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libnfc.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc @ONLY)
111149 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
112150 ENDIF(NOT WIN32)
113151
114 # Require PCRE for Win32
115 IF (WIN32)
116 FIND_PACKAGE(PCRE REQUIRED)
117 IF(PCRE_INCLUDE_DIRS)
118 INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS})
119 LINK_DIRECTORIES(${PCRE_LIBRARY_DIRS})
120 ENDIF(PCRE_INCLUDE_DIRS)
121 ENDIF(WIN32)
122
123152 INCLUDE(LibnfcDrivers)
153
154 IF(UNIX AND NOT APPLE)
155 IF(I2C_REQUIRED)
156 # Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html
157 INCLUDE (CheckFunctionExists)
158 INCLUDE (CheckLibraryExists)
159 CHECK_FUNCTION_EXISTS (clock_gettime HAVE_CLOCK_GETTIME)
160 IF (NOT HAVE_CLOCK_GETTIME)
161 CHECK_LIBRARY_EXISTS (rt clock_gettime "" HAVE_CLOCK_GETTIME_IN_RT)
162 IF (HAVE_CLOCK_GETTIME_IN_RT)
163 SET(LIBRT_FOUND TRUE)
164 SET(LIBRT_LIBRARIES "rt")
165 ENDIF (HAVE_CLOCK_GETTIME_IN_RT)
166 ENDIF (NOT HAVE_CLOCK_GETTIME)
167 ENDIF(I2C_REQUIRED)
168 ENDIF(UNIX AND NOT APPLE)
124169
125170 IF(PCSC_INCLUDE_DIRS)
126171 INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS})
136181 # version.rc for Windows
137182 IF(WIN32)
138183 # Date for filling in rc file information
139 MACRO (GET_CURRENT_YEAR RESULT)
140 EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT})
141 STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}})
142 STRING(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3" ${RESULT} ${${RESULT}})
143 ENDMACRO (GET_CURRENT_YEAR)
184 IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
185 MACRO (GET_CURRENT_YEAR RESULT)
186 EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT})
187 STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}})
188 STRING(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3" ${RESULT} ${${RESULT}})
189 ENDMACRO (GET_CURRENT_YEAR)
190 ELSE(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
191 MACRO (GET_CURRENT_YEAR RESULT)
192 EXECUTE_PROCESS(COMMAND "date" "+%Y" OUTPUT_VARIABLE ${RESULT})
193 STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}})
194 ENDMACRO (GET_CURRENT_YEAR)
195 ENDIF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
144196 GET_CURRENT_YEAR(CURRENT_YEAR)
145197 MESSAGE("Year for copyright is " ${CURRENT_YEAR})
146198
199 SET(prefix ${CMAKE_INSTALL_PREFIX})
147200 SET(RC_COMMENT "${PACKAGE_NAME} library")
148201 SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}")
149202 SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll)
153206
154207 ADD_SUBDIRECTORY(libnfc)
155208 ADD_SUBDIRECTORY(include)
156 ADD_SUBDIRECTORY(utils)
157 ADD_SUBDIRECTORY(examples)
209
210 if (BUILD_UTILS)
211 add_subdirectory (utils)
212 endif ()
213
214 if (BUILD_EXAMPLES)
215 add_subdirectory (examples)
216 endif ()
217
218 if (NOT MSVC)
219 # config script install path
220 if ( NOT DEFINED LIBNFC_CMAKE_CONFIG_DIR )
221 set ( LIBNFC_CMAKE_CONFIG_DIR lib${LIB_SUFFIX}/cmake/libnfc )
222 endif ()
223
224 set ( LIBNFC_INCLUDE_DIR ${includedir} )
225 set ( LIBNFC_INCLUDE_DIRS ${LIBNFC_INCLUDE_DIR} )
226 list ( APPEND LIBNFC_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIRS} )
227 set ( LIBNFC_LIBRARY nfc )
228 set ( LIBNFC_LIBRARIES ${LIBNFC_LIBRARY} )
229 list ( APPEND LIBNFC_LIBRARIES ${LIBUSB_LIBRARIES} )
230 set ( LIBNFC_LIBRARY_DIRS ${libdir} )
231 set ( LIBNFC_ROOT_DIR ${prefix} )
232 set ( LIBNFC_VERSION_STRING ${VERSION} )
233 set ( LIBNFC_VERSION_MAJOR ${VERSION_MAJOR} )
234 set ( LIBNFC_VERSION_MINOR ${VERSION_MINOR} )
235 set ( LIBNFC_VERSION_PATCH ${VERSION_PATCH} )
236
237 set ( LIBNFC_USE_FILE ${CMAKE_INSTALL_PREFIX}/${LIBNFC_CMAKE_CONFIG_DIR}/UseLibNFC.cmake )
238
239
240
241 if(CMAKE_VERSION VERSION_LESS 2.8.8)
242 configure_file ( cmake/LibNFCConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake @ONLY )
243 configure_file ( cmake/LibNFCConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfigVersion.cmake @ONLY )
244 else ()
245 include(CMakePackageConfigHelpers)
246 configure_package_config_file (
247 cmake/LibNFCConfig.cmake.in
248 ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake
249 INSTALL_DESTINATION ${LIBNFC_CMAKE_CONFIG_DIR}
250 PATH_VARS
251 LIBNFC_USE_FILE
252 LIBNFC_ROOT_DIR
253 LIBNFC_INCLUDE_DIR
254 LIBNFC_INCLUDE_DIRS
255 LIBNFC_LIBRARY_DIRS
256 NO_CHECK_REQUIRED_COMPONENTS_MACRO
257 )
258 write_basic_package_version_file (
259 LibNFCConfigVersion.cmake
260 VERSION ${LIBNFC_VERSION_STRING}
261 COMPATIBILITY AnyNewerVersion
262 )
263 endif ()
264
265 install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake
266 ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfigVersion.cmake
267 cmake/UseLibNFC.cmake
268 DESTINATION ${LIBNFC_CMAKE_CONFIG_DIR}
269 )
270
271 endif ()
158272
159273 # Binary Package
160274 IF(WIN32)
161275 SET(CPACK_GENERATOR "ZIP")
162276 ELSE(WIN32)
163277 SET(CPACK_GENERATOR "TBZ2")
278 IF(BUILD_DEBPKG)
279 SET(CPACK_GENERATOR "DEB")
280 ENDIF(BUILD_DEBPKG)
164281 ENDIF(WIN32)
165282
166283 SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Near Field Communication (NFC) library")
167284 SET(CPACK_PACKAGE_VENDOR "Roel Verdult")
168 SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
285 SET(CPACK_PACKAGE_CONTACT "Roel Verdult <roel@libnfc.org>")
286
287 #Readme file
288 IF(WIN32)
289 SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README-Windows.md")
290 ELSE(WIN32)
291 SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
292 ENDIF(WIN32)
293
169294 SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
170295 SET(CPACK_PACKAGE_INSTALL_DIRECTORY "libnfc")
171296 SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
0 May 22, 2020 - 1.8.0
1 --------------------
2
3 Fixes:
4 - Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
5
6 Changes:
7 - Bump revision due to changes in API introduced in v1.7.2
8 - Bump library version to 6.0.0
9
10 May 21, 2020 - 1.7.2 (avoid using it, incompatible with 1.7.1)
11 --------------------
12
13 Fixes:
14 - Remove unreachable code
15 - nfc_emulate_uid: cleaner exit on interrupt
16 - Fix reporting of modulations and baud rates by nfc-scan-device -v
17 - Fix out-of-bounds access in nfc-mfultralight
18 - Several Cygwin compilation fixes
19 - Fix comparison when nfc_initiator_target_is_present() with a specified target
20 - Fix nfc_initiator_poll_target without tag on PN532
21 - Export iso14443b* symbols
22 - Fix udev rule which was executed too early
23 - Fix improper device name initialization
24 - Fix setenv()/unsetenv() for Windows
25 - Fix win32/nfc.def according to nfc.h
26 - Fix missing timeout in pn53x_initiator_select_passive_target()
27 - nfc-mfclassic: fix option to tolerate write errors
28 - nfc-poll: fix card removing check
29 - nfc-relay-picc: fix wrong open mode for file descriptor
30
31 Improvements:
32 - Allow ISO14443A to be used at higher baud rates
33 - nfc_initiator_select_passive_target() now checks against
34 reported modulations and baud rates for current device
35 - More serial devices on MAC OS X
36 - Add section to README to help to configure libnfc
37 - Various cmake improvements
38 - Drop PCRE dependency on Windows
39 - Remove deprecated readdir_r
40 - Markdown conversion of the text files
41 - Use hardcoded PN533 descriptors to be more robust on Windows
42 - Add support for SCL3712
43 - Add support for ACR1222U-C1
44 - Add support for NetBSD
45 - Add support for PN532 on RPi3 UART
46 - Add support for cross-compilation of 32b & 64b versions of the library for Windows
47 - Add pn533_usb to the kernel modules blacklist
48 - Add support for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested)
49 - Add support for contactless PC/SC readers (only as initiator)
50 - Add support for Feitian R502 and bR500 into pcsc driver
51 - Add support for HID iClass (Picopass) support (nfc-iclass tool in external nfc-tools repo)
52 - Allows for sending empty data in nfc_initiator_transceive_bits
53 - driver i2c: respect proper timing specifications
54 - driver i2c: add retry on error mechanism
55 - nfc-mfclassic: improvements fo magic cards
56 - nfc-mfclassic: add option to specify UID
57 - nfc-mfclassic/nfc-mfsetuid: add support for new gen (1b) of magic 4K cards
58 - nfc-mfclassic: Add RATS support indicator
59 - nfc-mfsetuid: allow to write complete Block0, instead of only UID
60 - nfc-mfultralight: add automatic modes and --check-magic
61 - nfc-mfultralight: add support for magic gen2 cards
62 - nfc-mfultralight: add option to specify UID
63 - nfc-mfultralight: add support for Ultralight NTAG213/215/216
64 - nfc-barcode: new command to read and decode NFC Barcodes (Tag-Talks-First)
65
66 Changes:
67 - nfc_device_get_supported_baud_rate() takes now a "mode" parameter
68 - New nfc_device_get_supported_baud_rate_target_mode()
69 - New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol
70 - New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass)
71 - pn53x_transceive() is now part of public API
72
73 Special thanks to:
74 - Jim Anastassiou, Frédéric Bourgeois, Dario Carluccio, Emmanuel Dreyfus,
75 Julien Ehrhart, S. Fabri, John Galt, Christoph Gritschenberger,
76 Alexander Inyukhin, Arnaud Kapp, David Kreitschmann, Adam Laurie, Ray Lee,
77 Maxim Martyanov, Paul Menzel, Boris Moiseev, Yerzhan Mukhamejan,
78 Olliver Shinagl, Jairo Andres Suarez, Mati Vait, Marcos Vives Del Sol,
79 Hidde Wieringa, Simon Yorkston, timzi, usk-johnny-s, xantares, Hanno
80 Heinrichs, jgeslin, Mikolaj Stawiski, rstular, Khem Raj, Frank Morgner, jpwidera,
81 Feitian Technologies
82
083 Feb 24, 2014 - 1.7.1
1 ------------------
84 --------------------
285
386 Fixes:
487 - Fix several issues reported by Coverity Scan
0 # Doxyfile 1.6.1
0 # Doxyfile 1.8.13
11
22 # This file describes the settings to be used by the documentation system
3 # doxygen (www.doxygen.org) for a project
4 #
5 # All text after a hash (#) is considered a comment and will be ignored
3 # doxygen (www.doxygen.org) for a project.
4 #
5 # All text after a double hash (##) is considered a comment and is placed in
6 # front of the TAG it is preceding.
7 #
8 # All text after a single hash (#) is considered a comment and will be ignored.
69 # The format is:
7 # TAG = value [value, ...]
8 # For lists items can also be appended using:
9 # TAG += value [value, ...]
10 # Values that contain spaces should be placed between quotes (" ")
10 # TAG = value [value, ...]
11 # For lists, items can also be appended using:
12 # TAG += value [value, ...]
13 # Values that contain spaces should be placed between quotes (\" \").
1114
1215 #---------------------------------------------------------------------------
1316 # Project related configuration options
1417 #---------------------------------------------------------------------------
1518
1619 # This tag specifies the encoding used for all characters in the config file
17 # that follow. The default is UTF-8 which is also the encoding used for all
18 # text before the first occurrence of this tag. Doxygen uses libiconv (or the
19 # iconv built into libc) for the transcoding. See
20 # http://www.gnu.org/software/libiconv for the list of possible encodings.
20 # that follow. The default is UTF-8 which is also the encoding used for all text
21 # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
22 # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
23 # for the list of possible encodings.
24 # The default value is: UTF-8.
2125
2226 DOXYFILE_ENCODING = UTF-8
2327
24 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded
25 # by quotes) that should identify the project.
28 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
29 # double-quotes, unless you are using Doxywizard) that should identify the
30 # project for which the documentation is generated. This name is used in the
31 # title of most generated pages and in a few other places.
32 # The default value is: My Project.
2633
2734 PROJECT_NAME = libnfc
2835
29 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
30 # This could be handy for archiving the generated documentation or
31 # if some version control system is used.
36 # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
37 # could be handy for archiving the generated documentation or if some version
38 # control system is used.
3239
3340 PROJECT_NUMBER = @VERSION@
3441
35 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
36 # base path where the generated documentation will be put.
37 # If a relative path is entered, it will be relative to the location
38 # where doxygen was started. If left blank the current directory will be used.
42 # Using the PROJECT_BRIEF tag one can provide an optional one line description
43 # for a project that appears at the top of each page and should give viewer a
44 # quick idea about the purpose of the project. Keep the description short.
45
46 PROJECT_BRIEF =
47
48 # With the PROJECT_LOGO tag one can specify a logo or an icon that is included
49 # in the documentation. The maximum height of the logo should not exceed 55
50 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
51 # the logo to the output directory.
52
53 PROJECT_LOGO =
54
55 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
56 # into which the generated documentation will be written. If a relative path is
57 # entered, it will be relative to the location where doxygen was started. If
58 # left blank the current directory will be used.
3959
4060 OUTPUT_DIRECTORY = @builddir@/doc
4161
42 # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
43 # 4096 sub-directories (in 2 levels) under the output directory of each output
44 # format and will distribute the generated files over these directories.
45 # Enabling this option can be useful when feeding doxygen a huge amount of
46 # source files, where putting all generated files in the same directory would
47 # otherwise cause performance problems for the file system.
62 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
63 # directories (in 2 levels) under the output directory of each output format and
64 # will distribute the generated files over these directories. Enabling this
65 # option can be useful when feeding doxygen a huge amount of source files, where
66 # putting all generated files in the same directory would otherwise causes
67 # performance problems for the file system.
68 # The default value is: NO.
4869
4970 CREATE_SUBDIRS = NO
71
72 # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
73 # characters to appear in the names of generated files. If set to NO, non-ASCII
74 # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
75 # U+3044.
76 # The default value is: NO.
77
78 ALLOW_UNICODE_NAMES = NO
5079
5180 # The OUTPUT_LANGUAGE tag is used to specify the language in which all
5281 # documentation generated by doxygen is written. Doxygen will use this
5382 # information to generate all constant output in the proper language.
54 # The default language is English, other supported languages are:
55 # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
56 # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
57 # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
58 # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
59 # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
60 # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
83 # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
84 # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
85 # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
86 # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
87 # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
88 # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
89 # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
90 # Ukrainian and Vietnamese.
91 # The default value is: English.
6192
6293 OUTPUT_LANGUAGE = English
6394
64 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
65 # include brief member descriptions after the members that are listed in
66 # the file and class documentation (similar to JavaDoc).
67 # Set to NO to disable this.
95 # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
96 # descriptions after the members that are listed in the file and class
97 # documentation (similar to Javadoc). Set to NO to disable this.
98 # The default value is: YES.
6899
69100 BRIEF_MEMBER_DESC = YES
70101
71 # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
72 # the brief description of a member or function before the detailed description.
73 # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
102 # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
103 # description of a member or function before the detailed description
104 #
105 # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
74106 # brief descriptions will be completely suppressed.
107 # The default value is: YES.
75108
76109 REPEAT_BRIEF = YES
77110
78 # This tag implements a quasi-intelligent brief description abbreviator
79 # that is used to form the text in various listings. Each string
80 # in this list, if found as the leading text of the brief description, will be
81 # stripped from the text and the result after processing the whole list, is
82 # used as the annotated text. Otherwise, the brief description is used as-is.
83 # If left blank, the following values are used ("$name" is automatically
84 # replaced with the name of the entity): "The $name class" "The $name widget"
85 # "The $name file" "is" "provides" "specifies" "contains"
86 # "represents" "a" "an" "the"
111 # This tag implements a quasi-intelligent brief description abbreviator that is
112 # used to form the text in various listings. Each string in this list, if found
113 # as the leading text of the brief description, will be stripped from the text
114 # and the result, after processing the whole list, is used as the annotated
115 # text. Otherwise, the brief description is used as-is. If left blank, the
116 # following values are used ($name is automatically replaced with the name of
117 # the entity):The $name class, The $name widget, The $name file, is, provides,
118 # specifies, contains, represents, a, an and the.
87119
88120 ABBREVIATE_BRIEF = "The $name class" \
89121 "The $name widget" \
98130 the
99131
100132 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
101 # Doxygen will generate a detailed section even if there is only a brief
133 # doxygen will generate a detailed section even if there is only a brief
102134 # description.
135 # The default value is: NO.
103136
104137 ALWAYS_DETAILED_SEC = NO
105138
107140 # inherited members of a class in the documentation of that class as if those
108141 # members were ordinary class members. Constructors, destructors and assignment
109142 # operators of the base classes will not be shown.
143 # The default value is: NO.
110144
111145 INLINE_INHERITED_MEMB = NO
112146
113 # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
114 # path before files name in the file list and in the header files. If set
115 # to NO the shortest path that makes the file name unique will be used.
147 # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
148 # before files name in the file list and in the header files. If set to NO the
149 # shortest path that makes the file name unique will be used
150 # The default value is: YES.
116151
117152 FULL_PATH_NAMES = NO
118153
119 # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
120 # can be used to strip a user-defined part of the path. Stripping is
121 # only done if one of the specified strings matches the left-hand part of
122 # the path. The tag can be used to show relative paths in the file list.
123 # If left blank the directory from which doxygen is run is used as the
124 # path to strip.
154 # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
155 # Stripping is only done if one of the specified strings matches the left-hand
156 # part of the path. The tag can be used to show relative paths in the file list.
157 # If left blank the directory from which doxygen is run is used as the path to
158 # strip.
159 #
160 # Note that you can specify absolute paths here, but also relative paths, which
161 # will be relative from the directory where doxygen is started.
162 # This tag requires that the tag FULL_PATH_NAMES is set to YES.
125163
126164 STRIP_FROM_PATH =
127165
128 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
129 # the path mentioned in the documentation of a class, which tells
130 # the reader which header file to include in order to use a class.
131 # If left blank only the name of the header file containing the class
132 # definition is used. Otherwise one should specify the include paths that
133 # are normally passed to the compiler using the -I flag.
166 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
167 # path mentioned in the documentation of a class, which tells the reader which
168 # header file to include in order to use a class. If left blank only the name of
169 # the header file containing the class definition is used. Otherwise one should
170 # specify the list of include paths that are normally passed to the compiler
171 # using the -I flag.
134172
135173 STRIP_FROM_INC_PATH =
136174
137 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
138 # (but less readable) file names. This can be useful is your file systems
139 # doesn't support long names like on DOS, Mac, or CD-ROM.
175 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
176 # less readable) file names. This can be useful is your file systems doesn't
177 # support long names like on DOS, Mac, or CD-ROM.
178 # The default value is: NO.
140179
141180 SHORT_NAMES = NO
142181
143 # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
144 # will interpret the first line (until the first dot) of a JavaDoc-style
145 # comment as the brief description. If set to NO, the JavaDoc
146 # comments will behave just like regular Qt-style comments
147 # (thus requiring an explicit @brief command for a brief description.)
182 # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
183 # first line (until the first dot) of a Javadoc-style comment as the brief
184 # description. If set to NO, the Javadoc-style will behave just like regular Qt-
185 # style comments (thus requiring an explicit @brief command for a brief
186 # description.)
187 # The default value is: NO.
148188
149189 JAVADOC_AUTOBRIEF = NO
150190
151 # If the QT_AUTOBRIEF tag is set to YES then Doxygen will
152 # interpret the first line (until the first dot) of a Qt-style
153 # comment as the brief description. If set to NO, the comments
154 # will behave just like regular Qt-style comments (thus requiring
155 # an explicit \brief command for a brief description.)
191 # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
192 # line (until the first dot) of a Qt-style comment as the brief description. If
193 # set to NO, the Qt-style will behave just like regular Qt-style comments (thus
194 # requiring an explicit \brief command for a brief description.)
195 # The default value is: NO.
156196
157197 QT_AUTOBRIEF = NO
158198
159 # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
160 # treat a multi-line C++ special comment block (i.e. a block of //! or ///
161 # comments) as a brief description. This used to be the default behaviour.
162 # The new default is to treat a multi-line C++ comment block as a detailed
163 # description. Set this tag to YES if you prefer the old behaviour instead.
199 # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
200 # multi-line C++ special comment block (i.e. a block of //! or /// comments) as
201 # a brief description. This used to be the default behavior. The new default is
202 # to treat a multi-line C++ comment block as a detailed description. Set this
203 # tag to YES if you prefer the old behavior instead.
204 #
205 # Note that setting this tag to YES also means that rational rose comments are
206 # not recognized any more.
207 # The default value is: NO.
164208
165209 MULTILINE_CPP_IS_BRIEF = NO
166210
167 # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
168 # member inherits the documentation from any documented member that it
169 # re-implements.
211 # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
212 # documentation from any documented member that it re-implements.
213 # The default value is: YES.
170214
171215 INHERIT_DOCS = YES
172216
173 # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
174 # a new page for each member. If set to NO, the documentation of a member will
175 # be part of the file/class/namespace that contains it.
217 # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
218 # page for each member. If set to NO, the documentation of a member will be part
219 # of the file/class/namespace that contains it.
220 # The default value is: NO.
176221
177222 SEPARATE_MEMBER_PAGES = NO
178223
179 # The TAB_SIZE tag can be used to set the number of spaces in a tab.
180 # Doxygen uses this value to replace tabs by spaces in code fragments.
224 # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
225 # uses this value to replace tabs by spaces in code fragments.
226 # Minimum value: 1, maximum value: 16, default value: 4.
181227
182228 TAB_SIZE = 2
183229
184 # This tag can be used to specify a number of aliases that acts
185 # as commands in the documentation. An alias has the form "name=value".
186 # For example adding "sideeffect=\par Side Effects:\n" will allow you to
187 # put the command \sideeffect (or @sideeffect) in the documentation, which
188 # will result in a user-defined paragraph with heading "Side Effects:".
189 # You can put \n's in the value part of an alias to insert newlines.
230 # This tag can be used to specify a number of aliases that act as commands in
231 # the documentation. An alias has the form:
232 # name=value
233 # For example adding
234 # "sideeffect=@par Side Effects:\n"
235 # will allow you to put the command \sideeffect (or @sideeffect) in the
236 # documentation, which will result in a user-defined paragraph with heading
237 # "Side Effects:". You can put \n's in the value part of an alias to insert
238 # newlines.
190239
191240 ALIASES =
192241
193 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
194 # sources only. Doxygen will then generate output that is more tailored for C.
195 # For instance, some of the names that are used will be different. The list
196 # of all members will be omitted, etc.
242 # This tag can be used to specify a number of word-keyword mappings (TCL only).
243 # A mapping has the form "name=value". For example adding "class=itcl::class"
244 # will allow you to use the command class in the itcl::class meaning.
245
246 TCL_SUBST =
247
248 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
249 # only. Doxygen will then generate output that is more tailored for C. For
250 # instance, some of the names that are used will be different. The list of all
251 # members will be omitted, etc.
252 # The default value is: NO.
197253
198254 OPTIMIZE_OUTPUT_FOR_C = YES
199255
200 # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
201 # sources only. Doxygen will then generate output that is more tailored for
202 # Java. For instance, namespaces will be presented as packages, qualified
203 # scopes will look different, etc.
256 # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
257 # Python sources only. Doxygen will then generate output that is more tailored
258 # for that language. For instance, namespaces will be presented as packages,
259 # qualified scopes will look different, etc.
260 # The default value is: NO.
204261
205262 OPTIMIZE_OUTPUT_JAVA = NO
206263
207264 # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
208 # sources only. Doxygen will then generate output that is more tailored for
209 # Fortran.
265 # sources. Doxygen will then generate output that is tailored for Fortran.
266 # The default value is: NO.
210267
211268 OPTIMIZE_FOR_FORTRAN = NO
212269
213270 # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
214 # sources. Doxygen will then generate output that is tailored for
215 # VHDL.
271 # sources. Doxygen will then generate output that is tailored for VHDL.
272 # The default value is: NO.
216273
217274 OPTIMIZE_OUTPUT_VHDL = NO
218275
219 # Doxygen selects the parser to use depending on the extension of the files it parses.
220 # With this tag you can assign which parser to use for a given extension.
221 # Doxygen has a built-in mapping, but you can override or extend it using this tag.
222 # The format is ext=language, where ext is a file extension, and language is one of
223 # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
224 # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
225 # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
226 # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
276 # Doxygen selects the parser to use depending on the extension of the files it
277 # parses. With this tag you can assign which parser to use for a given
278 # extension. Doxygen has a built-in mapping, but you can override or extend it
279 # using this tag. The format is ext=language, where ext is a file extension, and
280 # language is one of the parsers supported by doxygen: IDL, Java, Javascript,
281 # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
282 # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
283 # Fortran. In the later case the parser tries to guess whether the code is fixed
284 # or free formatted code, this is the default for Fortran type files), VHDL. For
285 # instance to make doxygen treat .inc files as Fortran files (default is PHP),
286 # and .f files as C (default is Fortran), use: inc=Fortran f=C.
287 #
288 # Note: For files without extension you can use no_extension as a placeholder.
289 #
290 # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
291 # the files are not read by doxygen.
227292
228293 EXTENSION_MAPPING =
229294
295 # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
296 # according to the Markdown format, which allows for more readable
297 # documentation. See http://daringfireball.net/projects/markdown/ for details.
298 # The output of markdown processing is further processed by doxygen, so you can
299 # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
300 # case of backward compatibilities issues.
301 # The default value is: YES.
302
303 MARKDOWN_SUPPORT = YES
304
305 # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
306 # to that level are automatically included in the table of contents, even if
307 # they do not have an id attribute.
308 # Note: This feature currently applies only to Markdown headings.
309 # Minimum value: 0, maximum value: 99, default value: 0.
310 # This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
311
312 TOC_INCLUDE_HEADINGS = 0
313
314 # When enabled doxygen tries to link words that correspond to documented
315 # classes, or namespaces to their corresponding documentation. Such a link can
316 # be prevented in individual cases by putting a % sign in front of the word or
317 # globally by setting AUTOLINK_SUPPORT to NO.
318 # The default value is: YES.
319
320 AUTOLINK_SUPPORT = YES
321
230322 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
231 # to include (a tag file for) the STL sources as input, then you should
232 # set this tag to YES in order to let doxygen match functions declarations and
233 # definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
234 # func(std::string) {}). This also make the inheritance and collaboration
323 # to include (a tag file for) the STL sources as input, then you should set this
324 # tag to YES in order to let doxygen match functions declarations and
325 # definitions whose arguments contain STL classes (e.g. func(std::string);
326 # versus func(std::string) {}). This also make the inheritance and collaboration
235327 # diagrams that involve STL classes more complete and accurate.
328 # The default value is: NO.
236329
237330 BUILTIN_STL_SUPPORT = NO
238331
239332 # If you use Microsoft's C++/CLI language, you should set this option to YES to
240333 # enable parsing support.
334 # The default value is: NO.
241335
242336 CPP_CLI_SUPPORT = NO
243337
244 # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
245 # Doxygen will parse them like normal C++ but will assume all classes use public
246 # instead of private inheritance when no explicit protection keyword is present.
338 # Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
339 # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
340 # will parse them like normal C++ but will assume all classes use public instead
341 # of private inheritance when no explicit protection keyword is present.
342 # The default value is: NO.
247343
248344 SIP_SUPPORT = NO
249345
250 # For Microsoft's IDL there are propget and propput attributes to indicate getter
251 # and setter methods for a property. Setting this option to YES (the default)
252 # will make doxygen to replace the get and set methods by a property in the
253 # documentation. This will only work if the methods are indeed getting or
254 # setting a simple type. If this is not the case, or you want to show the
255 # methods anyway, you should set this option to NO.
346 # For Microsoft's IDL there are propget and propput attributes to indicate
347 # getter and setter methods for a property. Setting this option to YES will make
348 # doxygen to replace the get and set methods by a property in the documentation.
349 # This will only work if the methods are indeed getting or setting a simple
350 # type. If this is not the case, or you want to show the methods anyway, you
351 # should set this option to NO.
352 # The default value is: YES.
256353
257354 IDL_PROPERTY_SUPPORT = YES
258355
259356 # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
260 # tag is set to YES, then doxygen will reuse the documentation of the first
357 # tag is set to YES then doxygen will reuse the documentation of the first
261358 # member in the group (if any) for the other members of the group. By default
262359 # all members of a group must be documented explicitly.
360 # The default value is: NO.
263361
264362 DISTRIBUTE_GROUP_DOC = NO
265363
266 # Set the SUBGROUPING tag to YES (the default) to allow class member groups of
267 # the same type (for instance a group of public functions) to be put as a
268 # subgroup of that type (e.g. under the Public Functions section). Set it to
269 # NO to prevent subgrouping. Alternatively, this can be done per class using
270 # the \nosubgrouping command.
364 # If one adds a struct or class to a group and this option is enabled, then also
365 # any nested class or struct is added to the same group. By default this option
366 # is disabled and one has to add nested compounds explicitly via \ingroup.
367 # The default value is: NO.
368
369 GROUP_NESTED_COMPOUNDS = NO
370
371 # Set the SUBGROUPING tag to YES to allow class member groups of the same type
372 # (for instance a group of public functions) to be put as a subgroup of that
373 # type (e.g. under the Public Functions section). Set it to NO to prevent
374 # subgrouping. Alternatively, this can be done per class using the
375 # \nosubgrouping command.
376 # The default value is: YES.
271377
272378 SUBGROUPING = YES
273379
274 # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
275 # is documented as struct, union, or enum with the name of the typedef. So
380 # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
381 # are shown inside the group in which they are included (e.g. using \ingroup)
382 # instead of on a separate page (for HTML and Man pages) or section (for LaTeX
383 # and RTF).
384 #
385 # Note that this feature does not work in combination with
386 # SEPARATE_MEMBER_PAGES.
387 # The default value is: NO.
388
389 INLINE_GROUPED_CLASSES = NO
390
391 # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
392 # with only public data fields or simple typedef fields will be shown inline in
393 # the documentation of the scope in which they are defined (i.e. file,
394 # namespace, or group documentation), provided this scope is documented. If set
395 # to NO, structs, classes, and unions are shown on a separate page (for HTML and
396 # Man pages) or section (for LaTeX and RTF).
397 # The default value is: NO.
398
399 INLINE_SIMPLE_STRUCTS = NO
400
401 # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
402 # enum is documented as struct, union, or enum with the name of the typedef. So
276403 # typedef struct TypeS {} TypeT, will appear in the documentation as a struct
277404 # with name TypeT. When disabled the typedef will appear as a member of a file,
278 # namespace, or class. And the struct will be named TypeS. This can typically
279 # be useful for C code in case the coding convention dictates that all compound
405 # namespace, or class. And the struct will be named TypeS. This can typically be
406 # useful for C code in case the coding convention dictates that all compound
280407 # types are typedef'ed and only the typedef is referenced, never the tag name.
408 # The default value is: NO.
281409
282410 TYPEDEF_HIDES_STRUCT = NO
283411
284 # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
285 # determine which symbols to keep in memory and which to flush to disk.
286 # When the cache is full, less often used symbols will be written to disk.
287 # For small to medium size projects (<1000 input files) the default value is
288 # probably good enough. For larger projects a too small cache size can cause
289 # doxygen to be busy swapping symbols to and from disk most of the time
290 # causing a significant performance penality.
291 # If the system has enough physical memory increasing the cache will improve the
292 # performance by keeping more symbols in memory. Note that the value works on
293 # a logarithmic scale so increasing the size by one will rougly double the
294 # memory usage. The cache size is given by this formula:
295 # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
296 # corresponding to a cache size of 2^16 = 65536 symbols
297
298 SYMBOL_CACHE_SIZE = 0
412 # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
413 # cache is used to resolve symbols given their name and scope. Since this can be
414 # an expensive process and often the same symbol appears multiple times in the
415 # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
416 # doxygen will become slower. If the cache is too large, memory is wasted. The
417 # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
418 # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
419 # symbols. At the end of a run doxygen will report the cache usage and suggest
420 # the optimal cache size from a speed point of view.
421 # Minimum value: 0, maximum value: 9, default value: 0.
422
423 LOOKUP_CACHE_SIZE = 0
299424
300425 #---------------------------------------------------------------------------
301426 # Build related configuration options
302427 #---------------------------------------------------------------------------
303428
304 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
305 # documentation are documented, even if no documentation was available.
306 # Private class members and static file members will be hidden unless
307 # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
429 # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
430 # documentation are documented, even if no documentation was available. Private
431 # class members and static file members will be hidden unless the
432 # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
433 # Note: This will also disable the warnings about undocumented members that are
434 # normally produced when WARNINGS is set to YES.
435 # The default value is: NO.
308436
309437 EXTRACT_ALL = NO
310438
311 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class
312 # will be included in the documentation.
439 # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
440 # be included in the documentation.
441 # The default value is: NO.
313442
314443 EXTRACT_PRIVATE = NO
315444
316 # If the EXTRACT_STATIC tag is set to YES all static members of a file
317 # will be included in the documentation.
445 # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
446 # scope will be included in the documentation.
447 # The default value is: NO.
448
449 EXTRACT_PACKAGE = NO
450
451 # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
452 # included in the documentation.
453 # The default value is: NO.
318454
319455 EXTRACT_STATIC = YES
320456
321 # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
322 # defined locally in source files will be included in the documentation.
323 # If set to NO only classes defined in header files are included.
457 # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
458 # locally in source files will be included in the documentation. If set to NO,
459 # only classes defined in header files are included. Does not have any effect
460 # for Java sources.
461 # The default value is: YES.
324462
325463 EXTRACT_LOCAL_CLASSES = YES
326464
327 # This flag is only useful for Objective-C code. When set to YES local
328 # methods, which are defined in the implementation section but not in
329 # the interface are included in the documentation.
330 # If set to NO (the default) only methods in the interface are included.
465 # This flag is only useful for Objective-C code. If set to YES, local methods,
466 # which are defined in the implementation section but not in the interface are
467 # included in the documentation. If set to NO, only methods in the interface are
468 # included.
469 # The default value is: NO.
331470
332471 EXTRACT_LOCAL_METHODS = NO
333472
334473 # If this flag is set to YES, the members of anonymous namespaces will be
335474 # extracted and appear in the documentation as a namespace called
336 # 'anonymous_namespace{file}', where file will be replaced with the base
337 # name of the file that contains the anonymous namespace. By default
338 # anonymous namespace are hidden.
475 # 'anonymous_namespace{file}', where file will be replaced with the base name of
476 # the file that contains the anonymous namespace. By default anonymous namespace
477 # are hidden.
478 # The default value is: NO.
339479
340480 EXTRACT_ANON_NSPACES = NO
341481
342 # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
343 # undocumented members of documented classes, files or namespaces.
344 # If set to NO (the default) these members will be included in the
345 # various overviews, but no documentation section is generated.
346 # This option has no effect if EXTRACT_ALL is enabled.
482 # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
483 # undocumented members inside documented classes or files. If set to NO these
484 # members will be included in the various overviews, but no documentation
485 # section is generated. This option has no effect if EXTRACT_ALL is enabled.
486 # The default value is: NO.
347487
348488 HIDE_UNDOC_MEMBERS = YES
349489
350 # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
351 # undocumented classes that are normally visible in the class hierarchy.
352 # If set to NO (the default) these classes will be included in the various
353 # overviews. This option has no effect if EXTRACT_ALL is enabled.
490 # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
491 # undocumented classes that are normally visible in the class hierarchy. If set
492 # to NO, these classes will be included in the various overviews. This option
493 # has no effect if EXTRACT_ALL is enabled.
494 # The default value is: NO.
354495
355496 HIDE_UNDOC_CLASSES = YES
356497
357 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
358 # friend (class|struct|union) declarations.
359 # If set to NO (the default) these declarations will be included in the
360 # documentation.
498 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
499 # (class|struct|union) declarations. If set to NO, these declarations will be
500 # included in the documentation.
501 # The default value is: NO.
361502
362503 HIDE_FRIEND_COMPOUNDS = YES
363504
364 # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
365 # documentation blocks found inside the body of a function.
366 # If set to NO (the default) these blocks will be appended to the
367 # function's detailed documentation block.
505 # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
506 # documentation blocks found inside the body of a function. If set to NO, these
507 # blocks will be appended to the function's detailed documentation block.
508 # The default value is: NO.
368509
369510 HIDE_IN_BODY_DOCS = NO
370511
371 # The INTERNAL_DOCS tag determines if documentation
372 # that is typed after a \internal command is included. If the tag is set
373 # to NO (the default) then the documentation will be excluded.
374 # Set it to YES to include the internal documentation.
512 # The INTERNAL_DOCS tag determines if documentation that is typed after a
513 # \internal command is included. If the tag is set to NO then the documentation
514 # will be excluded. Set it to YES to include the internal documentation.
515 # The default value is: NO.
375516
376517 INTERNAL_DOCS = NO
377518
378 # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
379 # file names in lower-case letters. If set to YES upper-case letters are also
519 # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
520 # names in lower-case letters. If set to YES, upper-case letters are also
380521 # allowed. This is useful if you have classes or files whose names only differ
381522 # in case and if your file system supports case sensitive file names. Windows
382523 # and Mac users are advised to set this option to NO.
524 # The default value is: system dependent.
383525
384526 CASE_SENSE_NAMES = YES
385527
386 # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
387 # will show members with their full class and namespace scopes in the
388 # documentation. If set to YES the scope will be hidden.
528 # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
529 # their full class and namespace scopes in the documentation. If set to YES, the
530 # scope will be hidden.
531 # The default value is: NO.
389532
390533 HIDE_SCOPE_NAMES = NO
391534
392 # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
393 # will put a list of the files that are included by a file in the documentation
394 # of that file.
535 # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
536 # append additional text to a page's title, such as Class Reference. If set to
537 # YES the compound reference will be hidden.
538 # The default value is: NO.
539
540 HIDE_COMPOUND_REFERENCE= NO
541
542 # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
543 # the files that are included by a file in the documentation of that file.
544 # The default value is: YES.
395545
396546 SHOW_INCLUDE_FILES = YES
397547
398 # If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
399 # is inserted in the documentation for inline members.
548 # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
549 # grouped member an include statement to the documentation, telling the reader
550 # which file to include in order to use the member.
551 # The default value is: NO.
552
553 SHOW_GROUPED_MEMB_INC = NO
554
555 # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
556 # files with double quotes in the documentation rather than with sharp brackets.
557 # The default value is: NO.
558
559 FORCE_LOCAL_INCLUDES = NO
560
561 # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
562 # documentation for inline members.
563 # The default value is: YES.
400564
401565 INLINE_INFO = YES
402566
403 # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
404 # will sort the (detailed) documentation of file and class members
405 # alphabetically by member name. If set to NO the members will appear in
406 # declaration order.
567 # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
568 # (detailed) documentation of file and class members alphabetically by member
569 # name. If set to NO, the members will appear in declaration order.
570 # The default value is: YES.
407571
408572 SORT_MEMBER_DOCS = YES
409573
410 # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
411 # brief documentation of file, namespace and class members alphabetically
412 # by member name. If set to NO (the default) the members will appear in
413 # declaration order.
574 # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
575 # descriptions of file, namespace and class members alphabetically by member
576 # name. If set to NO, the members will appear in declaration order. Note that
577 # this will also influence the order of the classes in the class list.
578 # The default value is: NO.
414579
415580 SORT_BRIEF_DOCS = NO
416581
417 # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
582 # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
583 # (brief and detailed) documentation of class members so that constructors and
584 # destructors are listed first. If set to NO the constructors will appear in the
585 # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
586 # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
587 # member documentation.
588 # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
589 # detailed member documentation.
590 # The default value is: NO.
418591
419592 SORT_MEMBERS_CTORS_1ST = NO
420593
421 # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
422 # hierarchy of group names into alphabetical order. If set to NO (the default)
423 # the group names will appear in their defined order.
594 # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
595 # of group names into alphabetical order. If set to NO the group names will
596 # appear in their defined order.
597 # The default value is: NO.
424598
425599 SORT_GROUP_NAMES = NO
426600
427 # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
428 # sorted by fully-qualified names, including namespaces. If set to
429 # NO (the default), the class list will be sorted only by class name,
430 # not including the namespace part.
601 # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
602 # fully-qualified names, including namespaces. If set to NO, the class list will
603 # be sorted only by class name, not including the namespace part.
431604 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
432 # Note: This option applies only to the class list, not to the
433 # alphabetical list.
605 # Note: This option applies only to the class list, not to the alphabetical
606 # list.
607 # The default value is: NO.
434608
435609 SORT_BY_SCOPE_NAME = NO
436610
437 # The GENERATE_TODOLIST tag can be used to enable (YES) or
438 # disable (NO) the todo list. This list is created by putting \todo
439 # commands in the documentation.
611 # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
612 # type resolution of all parameters of a function it will reject a match between
613 # the prototype and the implementation of a member function even if there is
614 # only one candidate or it is obvious which candidate to choose by doing a
615 # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
616 # accept a match between prototype and implementation in such cases.
617 # The default value is: NO.
618
619 STRICT_PROTO_MATCHING = NO
620
621 # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
622 # list. This list is created by putting \todo commands in the documentation.
623 # The default value is: YES.
440624
441625 GENERATE_TODOLIST = YES
442626
443 # The GENERATE_TESTLIST tag can be used to enable (YES) or
444 # disable (NO) the test list. This list is created by putting \test
445 # commands in the documentation.
627 # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
628 # list. This list is created by putting \test commands in the documentation.
629 # The default value is: YES.
446630
447631 GENERATE_TESTLIST = YES
448632
449 # The GENERATE_BUGLIST tag can be used to enable (YES) or
450 # disable (NO) the bug list. This list is created by putting \bug
451 # commands in the documentation.
633 # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
634 # list. This list is created by putting \bug commands in the documentation.
635 # The default value is: YES.
452636
453637 GENERATE_BUGLIST = YES
454638
455 # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
456 # disable (NO) the deprecated list. This list is created by putting
457 # \deprecated commands in the documentation.
639 # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
640 # the deprecated list. This list is created by putting \deprecated commands in
641 # the documentation.
642 # The default value is: YES.
458643
459644 GENERATE_DEPRECATEDLIST= YES
460645
461 # The ENABLED_SECTIONS tag can be used to enable conditional
462 # documentation sections, marked by \if sectionname ... \endif.
646 # The ENABLED_SECTIONS tag can be used to enable conditional documentation
647 # sections, marked by \if <section_label> ... \endif and \cond <section_label>
648 # ... \endcond blocks.
463649
464650 ENABLED_SECTIONS =
465651
466 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines
467 # the initial value of a variable or define consists of for it to appear in
468 # the documentation. If the initializer consists of more lines than specified
469 # here it will be hidden. Use a value of 0 to hide initializers completely.
470 # The appearance of the initializer of individual variables and defines in the
471 # documentation can be controlled using \showinitializer or \hideinitializer
472 # command in the documentation regardless of this setting.
652 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
653 # initial value of a variable or macro / define can have for it to appear in the
654 # documentation. If the initializer consists of more lines than specified here
655 # it will be hidden. Use a value of 0 to hide initializers completely. The
656 # appearance of the value of individual variables and macros / defines can be
657 # controlled using \showinitializer or \hideinitializer command in the
658 # documentation regardless of this setting.
659 # Minimum value: 0, maximum value: 10000, default value: 30.
473660
474661 MAX_INITIALIZER_LINES = 30
475662
476 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated
477 # at the bottom of the documentation of classes and structs. If set to YES the
663 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
664 # the bottom of the documentation of classes and structs. If set to YES, the
478665 # list will mention the files that were used to generate the documentation.
666 # The default value is: YES.
479667
480668 SHOW_USED_FILES = YES
481669
482 # If the sources in your project are distributed over multiple directories
483 # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
484 # in the documentation. The default is NO.
485
486 SHOW_DIRECTORIES = YES
487
488 # Set the SHOW_FILES tag to NO to disable the generation of the Files page.
489 # This will remove the Files entry from the Quick Index and from the
490 # Folder Tree View (if specified). The default is YES.
670 # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
671 # will remove the Files entry from the Quick Index and from the Folder Tree View
672 # (if specified).
673 # The default value is: YES.
491674
492675 SHOW_FILES = YES
493676
494 # Set the SHOW_NAMESPACES tag to NO to disable the generation of the
495 # Namespaces page.
496 # This will remove the Namespaces entry from the Quick Index
497 # and from the Folder Tree View (if specified). The default is YES.
677 # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
678 # page. This will remove the Namespaces entry from the Quick Index and from the
679 # Folder Tree View (if specified).
680 # The default value is: YES.
498681
499682 SHOW_NAMESPACES = YES
500683
501684 # The FILE_VERSION_FILTER tag can be used to specify a program or script that
502685 # doxygen should invoke to get the current version for each file (typically from
503686 # the version control system). Doxygen will invoke the program by executing (via
504 # popen()) the command <command> <input-file>, where <command> is the value of
505 # the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
506 # provided by doxygen. Whatever the program writes to standard output
507 # is used as the file version. See the manual for examples.
687 # popen()) the command command input-file, where command is the value of the
688 # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
689 # by doxygen. Whatever the program writes to standard output is used as the file
690 # version. For an example see the documentation.
508691
509692 FILE_VERSION_FILTER =
510693
511 # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
512 # doxygen. The layout file controls the global structure of the generated output files
513 # in an output format independent way. The create the layout file that represents
514 # doxygen's defaults, run doxygen with the -l option. You can optionally specify a
515 # file name after the option, if omitted DoxygenLayout.xml will be used as the name
516 # of the layout file.
694 # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
695 # by doxygen. The layout file controls the global structure of the generated
696 # output files in an output format independent way. To create the layout file
697 # that represents doxygen's defaults, run doxygen with the -l option. You can
698 # optionally specify a file name after the option, if omitted DoxygenLayout.xml
699 # will be used as the name of the layout file.
700 #
701 # Note that if you run doxygen from a directory containing a file called
702 # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
703 # tag is left empty.
517704
518705 LAYOUT_FILE =
519706
520 #---------------------------------------------------------------------------
521 # configuration options related to warning and progress messages
522 #---------------------------------------------------------------------------
523
524 # The QUIET tag can be used to turn on/off the messages that are generated
525 # by doxygen. Possible values are YES and NO. If left blank NO is used.
707 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
708 # the reference definitions. This must be a list of .bib files. The .bib
709 # extension is automatically appended if omitted. This requires the bibtex tool
710 # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
711 # For LaTeX the style of the bibliography can be controlled using
712 # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
713 # search path. See also \cite for info how to create references.
714
715 CITE_BIB_FILES =
716
717 #---------------------------------------------------------------------------
718 # Configuration options related to warning and progress messages
719 #---------------------------------------------------------------------------
720
721 # The QUIET tag can be used to turn on/off the messages that are generated to
722 # standard output by doxygen. If QUIET is set to YES this implies that the
723 # messages are off.
724 # The default value is: NO.
526725
527726 QUIET = NO
528727
529728 # The WARNINGS tag can be used to turn on/off the warning messages that are
530 # generated by doxygen. Possible values are YES and NO. If left blank
531 # NO is used.
729 # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
730 # this implies that the warnings are on.
731 #
732 # Tip: Turn warnings on while writing the documentation.
733 # The default value is: YES.
532734
533735 WARNINGS = YES
534736
535 # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
536 # for undocumented members. If EXTRACT_ALL is set to YES then this flag will
537 # automatically be disabled.
737 # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
738 # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
739 # will automatically be disabled.
740 # The default value is: YES.
538741
539742 WARN_IF_UNDOCUMENTED = YES
540743
541 # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
542 # potential errors in the documentation, such as not documenting some
543 # parameters in a documented function, or documenting parameters that
544 # don't exist or using markup commands wrongly.
744 # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
745 # potential errors in the documentation, such as not documenting some parameters
746 # in a documented function, or documenting parameters that don't exist or using
747 # markup commands wrongly.
748 # The default value is: YES.
545749
546750 WARN_IF_DOC_ERROR = YES
547751
548 # This WARN_NO_PARAMDOC option can be abled to get warnings for
549 # functions that are documented, but have no documentation for their parameters
550 # or return value. If set to NO (the default) doxygen will only warn about
551 # wrong or incomplete parameter documentation, but not about the absence of
552 # documentation.
752 # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
753 # are documented, but have no documentation for their parameters or return
754 # value. If set to NO, doxygen will only warn about wrong or incomplete
755 # parameter documentation, but not about the absence of documentation.
756 # The default value is: NO.
553757
554758 WARN_NO_PARAMDOC = NO
555759
556 # The WARN_FORMAT tag determines the format of the warning messages that
557 # doxygen can produce. The string should contain the $file, $line, and $text
558 # tags, which will be replaced by the file and line number from which the
559 # warning originated and the warning text. Optionally the format may contain
560 # $version, which will be replaced by the version of the file (if it could
561 # be obtained via FILE_VERSION_FILTER)
760 # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
761 # a warning is encountered.
762 # The default value is: NO.
763
764 WARN_AS_ERROR = NO
765
766 # The WARN_FORMAT tag determines the format of the warning messages that doxygen
767 # can produce. The string should contain the $file, $line, and $text tags, which
768 # will be replaced by the file and line number from which the warning originated
769 # and the warning text. Optionally the format may contain $version, which will
770 # be replaced by the version of the file (if it could be obtained via
771 # FILE_VERSION_FILTER)
772 # The default value is: $file:$line: $text.
562773
563774 WARN_FORMAT = "$file:$line: $text"
564775
565 # The WARN_LOGFILE tag can be used to specify a file to which warning
566 # and error messages should be written. If left blank the output is written
567 # to stderr.
776 # The WARN_LOGFILE tag can be used to specify a file to which warning and error
777 # messages should be written. If left blank the output is written to standard
778 # error (stderr).
568779
569780 WARN_LOGFILE = Doxygen.log
570781
571782 #---------------------------------------------------------------------------
572 # configuration options related to the input files
573 #---------------------------------------------------------------------------
574
575 # The INPUT tag can be used to specify the files and/or directories that contain
576 # documented source files. You may enter file names like "myfile.cpp" or
577 # directories like "/usr/src/myproject". Separate the files or directories
578 # with spaces.
579
580 INPUT = @top_srcdir@/libnfc @top_srcdir@/examples @top_srcdir@/include/nfc @top_srcdir@/utils
783 # Configuration options related to the input files
784 #---------------------------------------------------------------------------
785
786 # The INPUT tag is used to specify the files and/or directories that contain
787 # documented source files. You may enter file names like myfile.cpp or
788 # directories like /usr/src/myproject. Separate the files or directories with
789 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
790 # Note: If this tag is empty the current directory is searched.
791
792 INPUT = @top_srcdir@/libnfc \
793 @top_srcdir@/examples \
794 @top_srcdir@/include/nfc \
795 @top_srcdir@/utils
581796
582797 # This tag can be used to specify the character encoding of the source files
583 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
584 # also the default input encoding. Doxygen uses libiconv (or the iconv built
585 # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
586 # the list of possible encodings.
798 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
799 # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
800 # documentation (see: http://www.gnu.org/software/libiconv) for the list of
801 # possible encodings.
802 # The default value is: UTF-8.
587803
588804 INPUT_ENCODING = UTF-8
589805
590806 # If the value of the INPUT tag contains directories, you can use the
591 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
592 # and *.h) to filter out the source-files in the directories. If left
593 # blank the following patterns are tested:
594 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
595 # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
807 # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
808 # *.h) to filter out the source-files in the directories.
809 #
810 # Note that for custom extensions or not directly supported extensions you also
811 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
812 # read by doxygen.
813 #
814 # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
815 # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
816 # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
817 # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
818 # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
596819
597820 FILE_PATTERNS = *.c \
598821 *.h \
599822 *.dox
600823
601 # The RECURSIVE tag can be used to turn specify whether or not subdirectories
602 # should be searched for input files as well. Possible values are YES and NO.
603 # If left blank NO is used.
824 # The RECURSIVE tag can be used to specify whether or not subdirectories should
825 # be searched for input files as well.
826 # The default value is: NO.
604827
605828 RECURSIVE = NO
606829
607 # The EXCLUDE tag can be used to specify files and/or directories that should
830 # The EXCLUDE tag can be used to specify files and/or directories that should be
608831 # excluded from the INPUT source files. This way you can easily exclude a
609832 # subdirectory from a directory tree whose root is specified with the INPUT tag.
833 #
834 # Note that relative paths are relative to the directory from which doxygen is
835 # run.
610836
611837 EXCLUDE = @top_srcdir@/libnfc/drivers.h \
612838 @top_srcdir@/libnfc/iso14443-subr.c \
614840 @top_srcdir@/libnfc/log-printf.c \
615841 @top_srcdir@/libnfc/log.h \
616842 @top_srcdir@/libnfc/mirror-subrc.c \
617 @top_srcdir@/libnfc/mirror-subrc.h \
618
619 # The EXCLUDE_SYMLINKS tag can be used select whether or not files or
620 # directories that are symbolic links (a Unix filesystem feature) are excluded
843 @top_srcdir@/libnfc/mirror-subrc.h
844
845 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
846 # directories that are symbolic links (a Unix file system feature) are excluded
621847 # from the input.
848 # The default value is: NO.
622849
623850 EXCLUDE_SYMLINKS = NO
624851
625852 # If the value of the INPUT tag contains directories, you can use the
626853 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
627 # certain files from those directories. Note that the wildcards are matched
628 # against the file with absolute path, so to exclude all test directories
629 # for example use the pattern */test/*
854 # certain files from those directories.
855 #
856 # Note that the wildcards are matched against the file with absolute path, so to
857 # exclude all test directories for example use the pattern */test/*
630858
631859 EXCLUDE_PATTERNS = .git/*
632860
635863 # output. The symbol name can be a fully qualified name, a word, or if the
636864 # wildcard * is used, a substring. Examples: ANamespace, AClass,
637865 # AClass::ANamespace, ANamespace::*Test
866 #
867 # Note that the wildcards are matched against the file with absolute path, so to
868 # exclude all test directories use the pattern */test/*
638869
639870 EXCLUDE_SYMBOLS =
640871
641 # The EXAMPLE_PATH tag can be used to specify one or more files or
642 # directories that contain example code fragments that are included (see
643 # the \include command).
872 # The EXAMPLE_PATH tag can be used to specify one or more files or directories
873 # that contain example code fragments that are included (see the \include
874 # command).
644875
645876 EXAMPLE_PATH = @top_srcdir@/ \
646877 @top_srcdir@/src/examples/doc
647878
648879 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
649 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
650 # and *.h) to filter out the source-files in the directories. If left
651 # blank all files are included.
880 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
881 # *.h) to filter out the source-files in the directories. If left blank all
882 # files are included.
652883
653884 EXAMPLE_PATTERNS = ChangeLog \
654885 *.c
655886
656887 # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
657 # searched for input files to be used with the \include or \dontinclude
658 # commands irrespective of the value of the RECURSIVE tag.
659 # Possible values are YES and NO. If left blank NO is used.
888 # searched for input files to be used with the \include or \dontinclude commands
889 # irrespective of the value of the RECURSIVE tag.
890 # The default value is: NO.
660891
661892 EXAMPLE_RECURSIVE = NO
662893
663 # The IMAGE_PATH tag can be used to specify one or more files or
664 # directories that contain image that are included in the documentation (see
665 # the \image command).
894 # The IMAGE_PATH tag can be used to specify one or more files or directories
895 # that contain images that are to be included in the documentation (see the
896 # \image command).
666897
667898 IMAGE_PATH =
668899
669900 # The INPUT_FILTER tag can be used to specify a program that doxygen should
670901 # invoke to filter for each input file. Doxygen will invoke the filter program
671 # by executing (via popen()) the command <filter> <input-file>, where <filter>
672 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
673 # input file. Doxygen will then use the output that the filter program writes
674 # to standard output.
675 # If FILTER_PATTERNS is specified, this tag will be
676 # ignored.
902 # by executing (via popen()) the command:
903 #
904 # <filter> <input-file>
905 #
906 # where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
907 # name of an input file. Doxygen will then use the output that the filter
908 # program writes to standard output. If FILTER_PATTERNS is specified, this tag
909 # will be ignored.
910 #
911 # Note that the filter must not add or remove lines; it is applied before the
912 # code is scanned, but not when the output code is generated. If lines are added
913 # or removed, the anchors will not be placed correctly.
914 #
915 # Note that for custom extensions or not directly supported extensions you also
916 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
917 # properly processed by doxygen.
677918
678919 INPUT_FILTER =
679920
680921 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
681 # basis.
682 # Doxygen will compare the file name with each pattern and apply the
683 # filter if there is a match.
684 # The filters are a list of the form:
685 # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
686 # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
687 # is applied to all files.
922 # basis. Doxygen will compare the file name with each pattern and apply the
923 # filter if there is a match. The filters are a list of the form: pattern=filter
924 # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
925 # filters are used. If the FILTER_PATTERNS tag is empty or if none of the
926 # patterns match the file name, INPUT_FILTER is applied.
927 #
928 # Note that for custom extensions or not directly supported extensions you also
929 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
930 # properly processed by doxygen.
688931
689932 FILTER_PATTERNS =
690933
691934 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
692 # INPUT_FILTER) will be used to filter the input files when producing source
693 # files to browse (i.e. when SOURCE_BROWSER is set to YES).
935 # INPUT_FILTER) will also be used to filter the input files that are used for
936 # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
937 # The default value is: NO.
694938
695939 FILTER_SOURCE_FILES = NO
696940
697 #---------------------------------------------------------------------------
698 # configuration options related to source browsing
699 #---------------------------------------------------------------------------
700
701 # If the SOURCE_BROWSER tag is set to YES then a list of source files will
702 # be generated. Documented entities will be cross-referenced with these sources.
703 # Note: To get rid of all source code in the generated output, make sure also
704 # VERBATIM_HEADERS is set to NO.
941 # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
942 # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
943 # it is also possible to disable source filtering for a specific pattern using
944 # *.ext= (so without naming a filter).
945 # This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
946
947 FILTER_SOURCE_PATTERNS =
948
949 # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
950 # is part of the input, its contents will be placed on the main page
951 # (index.html). This can be useful if you have a project on for instance GitHub
952 # and want to reuse the introduction page also for the doxygen output.
953
954 USE_MDFILE_AS_MAINPAGE =
955
956 #---------------------------------------------------------------------------
957 # Configuration options related to source browsing
958 #---------------------------------------------------------------------------
959
960 # If the SOURCE_BROWSER tag is set to YES then a list of source files will be
961 # generated. Documented entities will be cross-referenced with these sources.
962 #
963 # Note: To get rid of all source code in the generated output, make sure that
964 # also VERBATIM_HEADERS is set to NO.
965 # The default value is: NO.
705966
706967 SOURCE_BROWSER = YES
707968
708 # Setting the INLINE_SOURCES tag to YES will include the body
709 # of functions and classes directly in the documentation.
969 # Setting the INLINE_SOURCES tag to YES will include the body of functions,
970 # classes and enums directly into the documentation.
971 # The default value is: NO.
710972
711973 INLINE_SOURCES = NO
712974
713 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
714 # doxygen to hide any special comment blocks from generated source code
715 # fragments. Normal C and C++ comments will always remain visible.
975 # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
976 # special comment blocks from generated source code fragments. Normal C, C++ and
977 # Fortran comments will always remain visible.
978 # The default value is: YES.
716979
717980 STRIP_CODE_COMMENTS = YES
718981
719 # If the REFERENCED_BY_RELATION tag is set to YES
720 # then for each documented function all documented
721 # functions referencing it will be listed.
982 # If the REFERENCED_BY_RELATION tag is set to YES then for each documented
983 # function all documented functions referencing it will be listed.
984 # The default value is: NO.
722985
723986 REFERENCED_BY_RELATION = NO
724987
725 # If the REFERENCES_RELATION tag is set to YES
726 # then for each documented function all documented entities
727 # called/used by that function will be listed.
988 # If the REFERENCES_RELATION tag is set to YES then for each documented function
989 # all documented entities called/used by that function will be listed.
990 # The default value is: NO.
728991
729992 REFERENCES_RELATION = NO
730993
731 # If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
732 # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
733 # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
734 # link to the source code.
735 # Otherwise they will link to the documentation.
994 # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
995 # to YES then the hyperlinks from functions in REFERENCES_RELATION and
996 # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
997 # link to the documentation.
998 # The default value is: YES.
736999
7371000 REFERENCES_LINK_SOURCE = YES
7381001
739 # If the USE_HTAGS tag is set to YES then the references to source code
740 # will point to the HTML generated by the htags(1) tool instead of doxygen
741 # built-in source browser. The htags tool is part of GNU's global source
742 # tagging system (see http://www.gnu.org/software/global/global.html). You
743 # will need version 4.8.6 or higher.
1002 # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
1003 # source code will show a tooltip with additional information such as prototype,
1004 # brief description and links to the definition and documentation. Since this
1005 # will make the HTML file larger and loading of large files a bit slower, you
1006 # can opt to disable this feature.
1007 # The default value is: YES.
1008 # This tag requires that the tag SOURCE_BROWSER is set to YES.
1009
1010 SOURCE_TOOLTIPS = YES
1011
1012 # If the USE_HTAGS tag is set to YES then the references to source code will
1013 # point to the HTML generated by the htags(1) tool instead of doxygen built-in
1014 # source browser. The htags tool is part of GNU's global source tagging system
1015 # (see http://www.gnu.org/software/global/global.html). You will need version
1016 # 4.8.6 or higher.
1017 #
1018 # To use it do the following:
1019 # - Install the latest version of global
1020 # - Enable SOURCE_BROWSER and USE_HTAGS in the config file
1021 # - Make sure the INPUT points to the root of the source tree
1022 # - Run doxygen as normal
1023 #
1024 # Doxygen will invoke htags (and that will in turn invoke gtags), so these
1025 # tools must be available from the command line (i.e. in the search path).
1026 #
1027 # The result: instead of the source browser generated by doxygen, the links to
1028 # source code will now point to the output of htags.
1029 # The default value is: NO.
1030 # This tag requires that the tag SOURCE_BROWSER is set to YES.
7441031
7451032 USE_HTAGS = NO
7461033
747 # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
748 # will generate a verbatim copy of the header file for each class for
749 # which an include is specified. Set to NO to disable this.
1034 # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
1035 # verbatim copy of the header file for each class for which an include is
1036 # specified. Set to NO to disable this.
1037 # See also: Section \class.
1038 # The default value is: YES.
7501039
7511040 VERBATIM_HEADERS = YES
7521041
753 #---------------------------------------------------------------------------
754 # configuration options related to the alphabetical class index
755 #---------------------------------------------------------------------------
756
757 # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
758 # of all compounds will be generated. Enable this if the project
759 # contains a lot of classes, structs, unions or interfaces.
1042 # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
1043 # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
1044 # cost of reduced performance. This can be particularly helpful with template
1045 # rich C++ code for which doxygen's built-in parser lacks the necessary type
1046 # information.
1047 # Note: The availability of this option depends on whether or not doxygen was
1048 # generated with the -Duse-libclang=ON option for CMake.
1049 # The default value is: NO.
1050
1051 CLANG_ASSISTED_PARSING = NO
1052
1053 # If clang assisted parsing is enabled you can provide the compiler with command
1054 # line options that you would normally use when invoking the compiler. Note that
1055 # the include paths will already be set by doxygen for the files and directories
1056 # specified with INPUT and INCLUDE_PATH.
1057 # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
1058
1059 CLANG_OPTIONS =
1060
1061 #---------------------------------------------------------------------------
1062 # Configuration options related to the alphabetical class index
1063 #---------------------------------------------------------------------------
1064
1065 # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
1066 # compounds will be generated. Enable this if the project contains a lot of
1067 # classes, structs, unions or interfaces.
1068 # The default value is: YES.
7601069
7611070 ALPHABETICAL_INDEX = NO
7621071
763 # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
764 # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
765 # in which this list will be split (can be a number in the range [1..20])
1072 # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
1073 # which the alphabetical index list will be split.
1074 # Minimum value: 1, maximum value: 20, default value: 5.
1075 # This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
7661076
7671077 COLS_IN_ALPHA_INDEX = 5
7681078
769 # In case all classes in a project start with a common prefix, all
770 # classes will be put under the same header in the alphabetical index.
771 # The IGNORE_PREFIX tag can be used to specify one or more prefixes that
772 # should be ignored while generating the index headers.
1079 # In case all classes in a project start with a common prefix, all classes will
1080 # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
1081 # can be used to specify a prefix (or a list of prefixes) that should be ignored
1082 # while generating the index headers.
1083 # This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
7731084
7741085 IGNORE_PREFIX =
7751086
7761087 #---------------------------------------------------------------------------
777 # configuration options related to the HTML output
778 #---------------------------------------------------------------------------
779
780 # If the GENERATE_HTML tag is set to YES (the default) Doxygen will
781 # generate HTML output.
1088 # Configuration options related to the HTML output
1089 #---------------------------------------------------------------------------
1090
1091 # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
1092 # The default value is: YES.
7821093
7831094 GENERATE_HTML = YES
7841095
785 # The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
786 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
787 # put in front of it. If left blank `html' will be used as the default path.
1096 # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
1097 # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1098 # it.
1099 # The default directory is: html.
1100 # This tag requires that the tag GENERATE_HTML is set to YES.
7881101
7891102 HTML_OUTPUT = html
7901103
791 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for
792 # each generated HTML page (for example: .htm,.php,.asp). If it is left blank
793 # doxygen will generate files with .html extension.
1104 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
1105 # generated HTML page (for example: .htm, .php, .asp).
1106 # The default value is: .html.
1107 # This tag requires that the tag GENERATE_HTML is set to YES.
7941108
7951109 HTML_FILE_EXTENSION = .html
7961110
797 # The HTML_HEADER tag can be used to specify a personal HTML header for
798 # each generated HTML page. If it is left blank doxygen will generate a
1111 # The HTML_HEADER tag can be used to specify a user-defined HTML header file for
1112 # each generated HTML page. If the tag is left blank doxygen will generate a
7991113 # standard header.
1114 #
1115 # To get valid HTML the header file that includes any scripts and style sheets
1116 # that doxygen needs, which is dependent on the configuration options used (e.g.
1117 # the setting GENERATE_TREEVIEW). It is highly recommended to start with a
1118 # default header using
1119 # doxygen -w html new_header.html new_footer.html new_stylesheet.css
1120 # YourConfigFile
1121 # and then modify the file new_header.html. See also section "Doxygen usage"
1122 # for information on how to generate the default header that doxygen normally
1123 # uses.
1124 # Note: The header is subject to change so you typically have to regenerate the
1125 # default header when upgrading to a newer version of doxygen. For a description
1126 # of the possible markers and block names see the documentation.
1127 # This tag requires that the tag GENERATE_HTML is set to YES.
8001128
8011129 HTML_HEADER =
8021130
803 # The HTML_FOOTER tag can be used to specify a personal HTML footer for
804 # each generated HTML page. If it is left blank doxygen will generate a
805 # standard footer.
1131 # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
1132 # generated HTML page. If the tag is left blank doxygen will generate a standard
1133 # footer. See HTML_HEADER for more information on how to generate a default
1134 # footer and what special commands can be used inside the footer. See also
1135 # section "Doxygen usage" for information on how to generate the default footer
1136 # that doxygen normally uses.
1137 # This tag requires that the tag GENERATE_HTML is set to YES.
8061138
8071139 HTML_FOOTER =
8081140
809 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading
810 # style sheet that is used by each HTML page. It can be used to
811 # fine-tune the look of the HTML output. If the tag is left blank doxygen
812 # will generate a default style sheet. Note that doxygen will try to copy
813 # the style sheet file to the HTML output directory, so don't put your own
814 # stylesheet in the HTML output directory as well, or it will be erased!
1141 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
1142 # sheet that is used by each HTML page. It can be used to fine-tune the look of
1143 # the HTML output. If left blank doxygen will generate a default style sheet.
1144 # See also section "Doxygen usage" for information on how to generate the style
1145 # sheet that doxygen normally uses.
1146 # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
1147 # it is more robust and this tag (HTML_STYLESHEET) will in the future become
1148 # obsolete.
1149 # This tag requires that the tag GENERATE_HTML is set to YES.
8151150
8161151 HTML_STYLESHEET =
8171152
818 # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
819 # files or namespaces will be aligned in HTML using tables. If set to
820 # NO a bullet list will be used.
821
822 HTML_ALIGN_MEMBERS = YES
1153 # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1154 # cascading style sheets that are included after the standard style sheets
1155 # created by doxygen. Using this option one can overrule certain style aspects.
1156 # This is preferred over using HTML_STYLESHEET since it does not replace the
1157 # standard style sheet and is therefore more robust against future updates.
1158 # Doxygen will copy the style sheet files to the output directory.
1159 # Note: The order of the extra style sheet files is of importance (e.g. the last
1160 # style sheet in the list overrules the setting of the previous ones in the
1161 # list). For an example see the documentation.
1162 # This tag requires that the tag GENERATE_HTML is set to YES.
1163
1164 HTML_EXTRA_STYLESHEET =
1165
1166 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1167 # other source files which should be copied to the HTML output directory. Note
1168 # that these files will be copied to the base HTML output directory. Use the
1169 # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
1170 # files. In the HTML_STYLESHEET file, use the file name only. Also note that the
1171 # files will be copied as-is; there are no commands or markers available.
1172 # This tag requires that the tag GENERATE_HTML is set to YES.
1173
1174 HTML_EXTRA_FILES =
1175
1176 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1177 # will adjust the colors in the style sheet and background images according to
1178 # this color. Hue is specified as an angle on a colorwheel, see
1179 # http://en.wikipedia.org/wiki/Hue for more information. For instance the value
1180 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
1181 # purple, and 360 is red again.
1182 # Minimum value: 0, maximum value: 359, default value: 220.
1183 # This tag requires that the tag GENERATE_HTML is set to YES.
1184
1185 HTML_COLORSTYLE_HUE = 220
1186
1187 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
1188 # in the HTML output. For a value of 0 the output will use grayscales only. A
1189 # value of 255 will produce the most vivid colors.
1190 # Minimum value: 0, maximum value: 255, default value: 100.
1191 # This tag requires that the tag GENERATE_HTML is set to YES.
1192
1193 HTML_COLORSTYLE_SAT = 100
1194
1195 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
1196 # luminance component of the colors in the HTML output. Values below 100
1197 # gradually make the output lighter, whereas values above 100 make the output
1198 # darker. The value divided by 100 is the actual gamma applied, so 80 represents
1199 # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
1200 # change the gamma.
1201 # Minimum value: 40, maximum value: 240, default value: 80.
1202 # This tag requires that the tag GENERATE_HTML is set to YES.
1203
1204 HTML_COLORSTYLE_GAMMA = 80
1205
1206 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1207 # page will contain the date and time when the page was generated. Setting this
1208 # to YES can help to show when doxygen was last run and thus if the
1209 # documentation is up to date.
1210 # The default value is: NO.
1211 # This tag requires that the tag GENERATE_HTML is set to YES.
1212
1213 HTML_TIMESTAMP = NO
8231214
8241215 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
8251216 # documentation will contain sections that can be hidden and shown after the
826 # page has loaded. For this to work a browser that supports
827 # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
828 # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
1217 # page has loaded.
1218 # The default value is: NO.
1219 # This tag requires that the tag GENERATE_HTML is set to YES.
8291220
8301221 HTML_DYNAMIC_SECTIONS = NO
8311222
832 # If the GENERATE_DOCSET tag is set to YES, additional index files
833 # will be generated that can be used as input for Apple's Xcode 3
834 # integrated development environment, introduced with OSX 10.5 (Leopard).
835 # To create a documentation set, doxygen will generate a Makefile in the
836 # HTML output directory. Running make will produce the docset in that
837 # directory and running "make install" will install the docset in
838 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
839 # it at startup.
840 # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
1223 # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
1224 # shown in the various tree structured indices initially; the user can expand
1225 # and collapse entries dynamically later on. Doxygen will expand the tree to
1226 # such a level that at most the specified number of entries are visible (unless
1227 # a fully collapsed tree already exceeds this amount). So setting the number of
1228 # entries 1 will produce a full collapsed tree by default. 0 is a special value
1229 # representing an infinite number of entries and will result in a full expanded
1230 # tree by default.
1231 # Minimum value: 0, maximum value: 9999, default value: 100.
1232 # This tag requires that the tag GENERATE_HTML is set to YES.
1233
1234 HTML_INDEX_NUM_ENTRIES = 100
1235
1236 # If the GENERATE_DOCSET tag is set to YES, additional index files will be
1237 # generated that can be used as input for Apple's Xcode 3 integrated development
1238 # environment (see: http://developer.apple.com/tools/xcode/), introduced with
1239 # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
1240 # Makefile in the HTML output directory. Running make will produce the docset in
1241 # that directory and running make install will install the docset in
1242 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
1243 # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
1244 # for more information.
1245 # The default value is: NO.
1246 # This tag requires that the tag GENERATE_HTML is set to YES.
8411247
8421248 GENERATE_DOCSET = NO
8431249
844 # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
845 # feed. A documentation feed provides an umbrella under which multiple
846 # documentation sets from a single provider (such as a company or product suite)
847 # can be grouped.
1250 # This tag determines the name of the docset feed. A documentation feed provides
1251 # an umbrella under which multiple documentation sets from a single provider
1252 # (such as a company or product suite) can be grouped.
1253 # The default value is: Doxygen generated docs.
1254 # This tag requires that the tag GENERATE_DOCSET is set to YES.
8481255
8491256 DOCSET_FEEDNAME = "Doxygen generated docs"
8501257
851 # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
852 # should uniquely identify the documentation set bundle. This should be a
853 # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
854 # will append .docset to the name.
1258 # This tag specifies a string that should uniquely identify the documentation
1259 # set bundle. This should be a reverse domain-name style string, e.g.
1260 # com.mycompany.MyDocSet. Doxygen will append .docset to the name.
1261 # The default value is: org.doxygen.Project.
1262 # This tag requires that the tag GENERATE_DOCSET is set to YES.
8551263
8561264 DOCSET_BUNDLE_ID = org.doxygen.Project
8571265
858 # If the GENERATE_HTMLHELP tag is set to YES, additional index files
859 # will be generated that can be used as input for tools like the
860 # Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
861 # of the generated HTML documentation.
1266 # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
1267 # the documentation publisher. This should be a reverse domain-name style
1268 # string, e.g. com.mycompany.MyDocSet.documentation.
1269 # The default value is: org.doxygen.Publisher.
1270 # This tag requires that the tag GENERATE_DOCSET is set to YES.
1271
1272 DOCSET_PUBLISHER_ID = org.doxygen.Publisher
1273
1274 # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
1275 # The default value is: Publisher.
1276 # This tag requires that the tag GENERATE_DOCSET is set to YES.
1277
1278 DOCSET_PUBLISHER_NAME = Publisher
1279
1280 # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
1281 # additional HTML index files: index.hhp, index.hhc, and index.hhk. The
1282 # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
1283 # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
1284 # Windows.
1285 #
1286 # The HTML Help Workshop contains a compiler that can convert all HTML output
1287 # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
1288 # files are now used as the Windows 98 help format, and will replace the old
1289 # Windows help format (.hlp) on all Windows platforms in the future. Compressed
1290 # HTML files also contain an index, a table of contents, and you can search for
1291 # words in the documentation. The HTML workshop also contains a viewer for
1292 # compressed HTML files.
1293 # The default value is: NO.
1294 # This tag requires that the tag GENERATE_HTML is set to YES.
8621295
8631296 GENERATE_HTMLHELP = NO
8641297
865 # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
866 # be used to specify the file name of the resulting .chm file. You
867 # can add a path in front of the file if the result should not be
1298 # The CHM_FILE tag can be used to specify the file name of the resulting .chm
1299 # file. You can add a path in front of the file if the result should not be
8681300 # written to the html output directory.
1301 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
8691302
8701303 CHM_FILE =
8711304
872 # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
873 # be used to specify the location (absolute path including file name) of
874 # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
875 # the HTML help compiler on the generated index.hhp.
1305 # The HHC_LOCATION tag can be used to specify the location (absolute path
1306 # including file name) of the HTML help compiler (hhc.exe). If non-empty,
1307 # doxygen will try to run the HTML help compiler on the generated index.hhp.
1308 # The file has to be specified with full path.
1309 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
8761310
8771311 HHC_LOCATION =
8781312
879 # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
880 # controls if a separate .chi index file is generated (YES) or that
881 # it should be included in the master .chm file (NO).
1313 # The GENERATE_CHI flag controls if a separate .chi index file is generated
1314 # (YES) or that it should be included in the master .chm file (NO).
1315 # The default value is: NO.
1316 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
8821317
8831318 GENERATE_CHI = NO
8841319
885 # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
886 # is used to encode HtmlHelp index (hhk), content (hhc) and project file
887 # content.
1320 # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
1321 # and project file content.
1322 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
8881323
8891324 CHM_INDEX_ENCODING =
8901325
891 # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
892 # controls whether a binary table of contents is generated (YES) or a
893 # normal table of contents (NO) in the .chm file.
1326 # The BINARY_TOC flag controls whether a binary table of contents is generated
1327 # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
1328 # enables the Previous and Next buttons.
1329 # The default value is: NO.
1330 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
8941331
8951332 BINARY_TOC = NO
8961333
897 # The TOC_EXPAND flag can be set to YES to add extra items for group members
898 # to the contents of the HTML help documentation and to the tree view.
1334 # The TOC_EXPAND flag can be set to YES to add extra items for group members to
1335 # the table of contents of the HTML help documentation and to the tree view.
1336 # The default value is: NO.
1337 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
8991338
9001339 TOC_EXPAND = NO
9011340
902 # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
903 # are set, an additional index file will be generated that can be used as input for
904 # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
905 # HTML documentation.
1341 # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
1342 # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
1343 # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
1344 # (.qch) of the generated HTML documentation.
1345 # The default value is: NO.
1346 # This tag requires that the tag GENERATE_HTML is set to YES.
9061347
9071348 GENERATE_QHP = NO
9081349
909 # If the QHG_LOCATION tag is specified, the QCH_FILE tag can
910 # be used to specify the file name of the resulting .qch file.
911 # The path specified is relative to the HTML output folder.
1350 # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
1351 # the file name of the resulting .qch file. The path specified is relative to
1352 # the HTML output folder.
1353 # This tag requires that the tag GENERATE_QHP is set to YES.
9121354
9131355 QCH_FILE =
9141356
915 # The QHP_NAMESPACE tag specifies the namespace to use when generating
916 # Qt Help Project output. For more information please see
917 # http://doc.trolltech.com/qthelpproject.html#namespace
1357 # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
1358 # Project output. For more information please see Qt Help Project / Namespace
1359 # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
1360 # The default value is: org.doxygen.Project.
1361 # This tag requires that the tag GENERATE_QHP is set to YES.
9181362
9191363 QHP_NAMESPACE =
9201364
921 # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
922 # Qt Help Project output. For more information please see
923 # http://doc.trolltech.com/qthelpproject.html#virtual-folders
1365 # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
1366 # Help Project output. For more information please see Qt Help Project / Virtual
1367 # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
1368 # folders).
1369 # The default value is: doc.
1370 # This tag requires that the tag GENERATE_QHP is set to YES.
9241371
9251372 QHP_VIRTUAL_FOLDER = doc
9261373
927 # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
928 # For more information please see
929 # http://doc.trolltech.com/qthelpproject.html#custom-filters
1374 # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
1375 # filter to add. For more information please see Qt Help Project / Custom
1376 # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1377 # filters).
1378 # This tag requires that the tag GENERATE_QHP is set to YES.
9301379
9311380 QHP_CUST_FILTER_NAME =
9321381
933 # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
934 # <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
1382 # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
1383 # custom filter to add. For more information please see Qt Help Project / Custom
1384 # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1385 # filters).
1386 # This tag requires that the tag GENERATE_QHP is set to YES.
9351387
9361388 QHP_CUST_FILTER_ATTRS =
9371389
938 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
939 # filter section matches.
940 # <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
1390 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
1391 # project's filter section matches. Qt Help Project / Filter Attributes (see:
1392 # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
1393 # This tag requires that the tag GENERATE_QHP is set to YES.
9411394
9421395 QHP_SECT_FILTER_ATTRS =
9431396
944 # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
945 # be used to specify the location of Qt's qhelpgenerator.
946 # If non-empty doxygen will try to run qhelpgenerator on the generated
947 # .qhp file.
1397 # The QHG_LOCATION tag can be used to specify the location of Qt's
1398 # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
1399 # generated .qhp file.
1400 # This tag requires that the tag GENERATE_QHP is set to YES.
9481401
9491402 QHG_LOCATION =
9501403
951 # The DISABLE_INDEX tag can be used to turn on/off the condensed index at
952 # top of each HTML page. The value NO (the default) enables the index and
953 # the value YES disables it.
1404 # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
1405 # generated, together with the HTML files, they form an Eclipse help plugin. To
1406 # install this plugin and make it available under the help contents menu in
1407 # Eclipse, the contents of the directory containing the HTML and XML files needs
1408 # to be copied into the plugins directory of eclipse. The name of the directory
1409 # within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
1410 # After copying Eclipse needs to be restarted before the help appears.
1411 # The default value is: NO.
1412 # This tag requires that the tag GENERATE_HTML is set to YES.
1413
1414 GENERATE_ECLIPSEHELP = NO
1415
1416 # A unique identifier for the Eclipse help plugin. When installing the plugin
1417 # the directory name containing the HTML and XML files should also have this
1418 # name. Each documentation set should have its own identifier.
1419 # The default value is: org.doxygen.Project.
1420 # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
1421
1422 ECLIPSE_DOC_ID = org.doxygen.Project
1423
1424 # If you want full control over the layout of the generated HTML pages it might
1425 # be necessary to disable the index and replace it with your own. The
1426 # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
1427 # of each HTML page. A value of NO enables the index and the value YES disables
1428 # it. Since the tabs in the index contain the same information as the navigation
1429 # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
1430 # The default value is: NO.
1431 # This tag requires that the tag GENERATE_HTML is set to YES.
9541432
9551433 DISABLE_INDEX = NO
9561434
957 # This tag can be used to set the number of enum values (range [1..20])
958 # that doxygen will group on one line in the generated HTML documentation.
1435 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1436 # structure should be generated to display hierarchical information. If the tag
1437 # value is set to YES, a side panel will be generated containing a tree-like
1438 # index structure (just like the one that is generated for HTML Help). For this
1439 # to work a browser that supports JavaScript, DHTML, CSS and frames is required
1440 # (i.e. any modern browser). Windows users are probably better off using the
1441 # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
1442 # further fine-tune the look of the index. As an example, the default style
1443 # sheet generated by doxygen has an example that shows how to put an image at
1444 # the root of the tree instead of the PROJECT_NAME. Since the tree basically has
1445 # the same information as the tab index, you could consider setting
1446 # DISABLE_INDEX to YES when enabling this option.
1447 # The default value is: NO.
1448 # This tag requires that the tag GENERATE_HTML is set to YES.
1449
1450 GENERATE_TREEVIEW = NONE
1451
1452 # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
1453 # doxygen will group on one line in the generated HTML documentation.
1454 #
1455 # Note that a value of 0 will completely suppress the enum values from appearing
1456 # in the overview section.
1457 # Minimum value: 0, maximum value: 20, default value: 4.
1458 # This tag requires that the tag GENERATE_HTML is set to YES.
9591459
9601460 ENUM_VALUES_PER_LINE = 4
9611461
962 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
963 # structure should be generated to display hierarchical information.
964 # If the tag value is set to YES, a side panel will be generated
965 # containing a tree-like index structure (just like the one that
966 # is generated for HTML Help). For this to work a browser that supports
967 # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
968 # Windows users are probably better off using the HTML help feature.
969
970 GENERATE_TREEVIEW = NONE
971
972 # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
973 # and Class Hierarchy pages using a tree view instead of an ordered list.
974
975 USE_INLINE_TREES = NO
976
977 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
978 # used to set the initial width (in pixels) of the frame in which the tree
979 # is shown.
1462 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
1463 # to set the initial width (in pixels) of the frame in which the tree is shown.
1464 # Minimum value: 0, maximum value: 1500, default value: 250.
1465 # This tag requires that the tag GENERATE_HTML is set to YES.
9801466
9811467 TREEVIEW_WIDTH = 250
9821468
983 # Use this tag to change the font size of Latex formulas included
984 # as images in the HTML documentation. The default is 10. Note that
985 # when you change the font size after a successful doxygen run you need
986 # to manually remove any form_*.png images from the HTML output directory
987 # to force them to be regenerated.
1469 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
1470 # external symbols imported via tag files in a separate window.
1471 # The default value is: NO.
1472 # This tag requires that the tag GENERATE_HTML is set to YES.
1473
1474 EXT_LINKS_IN_WINDOW = NO
1475
1476 # Use this tag to change the font size of LaTeX formulas included as images in
1477 # the HTML documentation. When you change the font size after a successful
1478 # doxygen run you need to manually remove any form_*.png images from the HTML
1479 # output directory to force them to be regenerated.
1480 # Minimum value: 8, maximum value: 50, default value: 10.
1481 # This tag requires that the tag GENERATE_HTML is set to YES.
9881482
9891483 FORMULA_FONTSIZE = 10
9901484
991 # When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
992 # and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP)
993 # there is already a search function so this one should typically
994 # be disabled.
1485 # Use the FORMULA_TRANPARENT tag to determine whether or not the images
1486 # generated for formulas are transparent PNGs. Transparent PNGs are not
1487 # supported properly for IE 6.0, but are supported on all modern browsers.
1488 #
1489 # Note that when changing this option you need to delete any form_*.png files in
1490 # the HTML output directory before the changes have effect.
1491 # The default value is: YES.
1492 # This tag requires that the tag GENERATE_HTML is set to YES.
1493
1494 FORMULA_TRANSPARENT = YES
1495
1496 # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1497 # http://www.mathjax.org) which uses client side Javascript for the rendering
1498 # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
1499 # installed or if you want to formulas look prettier in the HTML output. When
1500 # enabled you may also need to install MathJax separately and configure the path
1501 # to it using the MATHJAX_RELPATH option.
1502 # The default value is: NO.
1503 # This tag requires that the tag GENERATE_HTML is set to YES.
1504
1505 USE_MATHJAX = NO
1506
1507 # When MathJax is enabled you can set the default output format to be used for
1508 # the MathJax output. See the MathJax site (see:
1509 # http://docs.mathjax.org/en/latest/output.html) for more details.
1510 # Possible values are: HTML-CSS (which is slower, but has the best
1511 # compatibility), NativeMML (i.e. MathML) and SVG.
1512 # The default value is: HTML-CSS.
1513 # This tag requires that the tag USE_MATHJAX is set to YES.
1514
1515 MATHJAX_FORMAT = HTML-CSS
1516
1517 # When MathJax is enabled you need to specify the location relative to the HTML
1518 # output directory using the MATHJAX_RELPATH option. The destination directory
1519 # should contain the MathJax.js script. For instance, if the mathjax directory
1520 # is located at the same level as the HTML output directory, then
1521 # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
1522 # Content Delivery Network so you can quickly see the result without installing
1523 # MathJax. However, it is strongly recommended to install a local copy of
1524 # MathJax from http://www.mathjax.org before deployment.
1525 # The default value is: http://cdn.mathjax.org/mathjax/latest.
1526 # This tag requires that the tag USE_MATHJAX is set to YES.
1527
1528 MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
1529
1530 # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1531 # extension names that should be enabled during MathJax rendering. For example
1532 # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
1533 # This tag requires that the tag USE_MATHJAX is set to YES.
1534
1535 MATHJAX_EXTENSIONS =
1536
1537 # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
1538 # of code that will be used on startup of the MathJax code. See the MathJax site
1539 # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
1540 # example see the documentation.
1541 # This tag requires that the tag USE_MATHJAX is set to YES.
1542
1543 MATHJAX_CODEFILE =
1544
1545 # When the SEARCHENGINE tag is enabled doxygen will generate a search box for
1546 # the HTML output. The underlying search engine uses javascript and DHTML and
1547 # should work on any modern browser. Note that when using HTML help
1548 # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
1549 # there is already a search function so this one should typically be disabled.
1550 # For large projects the javascript based search engine can be slow, then
1551 # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
1552 # search using the keyboard; to jump to the search box use <access key> + S
1553 # (what the <access key> is depends on the OS and browser, but it is typically
1554 # <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
1555 # key> to jump into the search results window, the results can be navigated
1556 # using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
1557 # the search. The filter options can be selected when the cursor is inside the
1558 # search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
1559 # to select a filter and <Enter> or <escape> to activate or cancel the filter
1560 # option.
1561 # The default value is: YES.
1562 # This tag requires that the tag GENERATE_HTML is set to YES.
9951563
9961564 SEARCHENGINE = NO
9971565
998 #---------------------------------------------------------------------------
999 # configuration options related to the LaTeX output
1000 #---------------------------------------------------------------------------
1001
1002 # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
1003 # generate Latex output.
1566 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
1567 # implemented using a web server instead of a web client using Javascript. There
1568 # are two flavors of web server based searching depending on the EXTERNAL_SEARCH
1569 # setting. When disabled, doxygen will generate a PHP script for searching and
1570 # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
1571 # and searching needs to be provided by external tools. See the section
1572 # "External Indexing and Searching" for details.
1573 # The default value is: NO.
1574 # This tag requires that the tag SEARCHENGINE is set to YES.
1575
1576 SERVER_BASED_SEARCH = NO
1577
1578 # When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
1579 # script for searching. Instead the search results are written to an XML file
1580 # which needs to be processed by an external indexer. Doxygen will invoke an
1581 # external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1582 # search results.
1583 #
1584 # Doxygen ships with an example indexer (doxyindexer) and search engine
1585 # (doxysearch.cgi) which are based on the open source search engine library
1586 # Xapian (see: http://xapian.org/).
1587 #
1588 # See the section "External Indexing and Searching" for details.
1589 # The default value is: NO.
1590 # This tag requires that the tag SEARCHENGINE is set to YES.
1591
1592 EXTERNAL_SEARCH = NO
1593
1594 # The SEARCHENGINE_URL should point to a search engine hosted by a web server
1595 # which will return the search results when EXTERNAL_SEARCH is enabled.
1596 #
1597 # Doxygen ships with an example indexer (doxyindexer) and search engine
1598 # (doxysearch.cgi) which are based on the open source search engine library
1599 # Xapian (see: http://xapian.org/). See the section "External Indexing and
1600 # Searching" for details.
1601 # This tag requires that the tag SEARCHENGINE is set to YES.
1602
1603 SEARCHENGINE_URL =
1604
1605 # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
1606 # search data is written to a file for indexing by an external tool. With the
1607 # SEARCHDATA_FILE tag the name of this file can be specified.
1608 # The default file is: searchdata.xml.
1609 # This tag requires that the tag SEARCHENGINE is set to YES.
1610
1611 SEARCHDATA_FILE = searchdata.xml
1612
1613 # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
1614 # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
1615 # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
1616 # projects and redirect the results back to the right project.
1617 # This tag requires that the tag SEARCHENGINE is set to YES.
1618
1619 EXTERNAL_SEARCH_ID =
1620
1621 # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
1622 # projects other than the one defined by this configuration file, but that are
1623 # all added to the same external search index. Each project needs to have a
1624 # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
1625 # to a relative location where the documentation can be found. The format is:
1626 # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
1627 # This tag requires that the tag SEARCHENGINE is set to YES.
1628
1629 EXTRA_SEARCH_MAPPINGS =
1630
1631 #---------------------------------------------------------------------------
1632 # Configuration options related to the LaTeX output
1633 #---------------------------------------------------------------------------
1634
1635 # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
1636 # The default value is: YES.
10041637
10051638 GENERATE_LATEX = NO
10061639
1007 # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
1008 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
1009 # put in front of it. If left blank `latex' will be used as the default path.
1640 # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
1641 # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1642 # it.
1643 # The default directory is: latex.
1644 # This tag requires that the tag GENERATE_LATEX is set to YES.
10101645
10111646 LATEX_OUTPUT = latex
10121647
10131648 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1014 # invoked. If left blank `latex' will be used as the default command name.
1649 # invoked.
1650 #
1651 # Note that when enabling USE_PDFLATEX this option is only used for generating
1652 # bitmaps for formulas in the HTML output, but not in the Makefile that is
1653 # written to the output directory.
1654 # The default file is: latex.
1655 # This tag requires that the tag GENERATE_LATEX is set to YES.
10151656
10161657 LATEX_CMD_NAME = latex
10171658
1018 # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
1019 # generate index for LaTeX. If left blank `makeindex' will be used as the
1020 # default command name.
1659 # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
1660 # index for LaTeX.
1661 # The default file is: makeindex.
1662 # This tag requires that the tag GENERATE_LATEX is set to YES.
10211663
10221664 MAKEINDEX_CMD_NAME = makeindex
10231665
1024 # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
1025 # LaTeX documents. This may be useful for small projects and may help to
1026 # save some trees in general.
1666 # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
1667 # documents. This may be useful for small projects and may help to save some
1668 # trees in general.
1669 # The default value is: NO.
1670 # This tag requires that the tag GENERATE_LATEX is set to YES.
10271671
10281672 COMPACT_LATEX = NO
10291673
1030 # The PAPER_TYPE tag can be used to set the paper type that is used
1031 # by the printer. Possible values are: a4, a4wide, letter, legal and
1032 # executive. If left blank a4wide will be used.
1674 # The PAPER_TYPE tag can be used to set the paper type that is used by the
1675 # printer.
1676 # Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
1677 # 14 inches) and executive (7.25 x 10.5 inches).
1678 # The default value is: a4.
1679 # This tag requires that the tag GENERATE_LATEX is set to YES.
10331680
10341681 PAPER_TYPE = a4wide
10351682
1036 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
1037 # packages that should be included in the LaTeX output.
1683 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1684 # that should be included in the LaTeX output. The package can be specified just
1685 # by its name or with the correct syntax as to be used with the LaTeX
1686 # \usepackage command. To get the times font for instance you can specify :
1687 # EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
1688 # To use the option intlimits with the amsmath package you can specify:
1689 # EXTRA_PACKAGES=[intlimits]{amsmath}
1690 # If left blank no extra packages will be included.
1691 # This tag requires that the tag GENERATE_LATEX is set to YES.
10381692
10391693 EXTRA_PACKAGES =
10401694
1041 # The LATEX_HEADER tag can be used to specify a personal LaTeX header for
1042 # the generated latex document. The header should contain everything until
1043 # the first chapter. If it is left blank doxygen will generate a
1044 # standard header. Notice: only use this tag if you know what you are doing!
1695 # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
1696 # generated LaTeX document. The header should contain everything until the first
1697 # chapter. If it is left blank doxygen will generate a standard header. See
1698 # section "Doxygen usage" for information on how to let doxygen write the
1699 # default header to a separate file.
1700 #
1701 # Note: Only use a user-defined header if you know what you are doing! The
1702 # following commands have a special meaning inside the header: $title,
1703 # $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1704 # $projectbrief, $projectlogo. Doxygen will replace $title with the empty
1705 # string, for the replacement values of the other commands the user is referred
1706 # to HTML_HEADER.
1707 # This tag requires that the tag GENERATE_LATEX is set to YES.
10451708
10461709 LATEX_HEADER =
10471710
1048 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
1049 # is prepared for conversion to pdf (using ps2pdf). The pdf file will
1050 # contain links (just like the HTML output) instead of page references
1051 # This makes the output suitable for online browsing using a pdf viewer.
1711 # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
1712 # generated LaTeX document. The footer should contain everything after the last
1713 # chapter. If it is left blank doxygen will generate a standard footer. See
1714 # LATEX_HEADER for more information on how to generate a default footer and what
1715 # special commands can be used inside the footer.
1716 #
1717 # Note: Only use a user-defined footer if you know what you are doing!
1718 # This tag requires that the tag GENERATE_LATEX is set to YES.
1719
1720 LATEX_FOOTER =
1721
1722 # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1723 # LaTeX style sheets that are included after the standard style sheets created
1724 # by doxygen. Using this option one can overrule certain style aspects. Doxygen
1725 # will copy the style sheet files to the output directory.
1726 # Note: The order of the extra style sheet files is of importance (e.g. the last
1727 # style sheet in the list overrules the setting of the previous ones in the
1728 # list).
1729 # This tag requires that the tag GENERATE_LATEX is set to YES.
1730
1731 LATEX_EXTRA_STYLESHEET =
1732
1733 # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1734 # other source files which should be copied to the LATEX_OUTPUT output
1735 # directory. Note that the files will be copied as-is; there are no commands or
1736 # markers available.
1737 # This tag requires that the tag GENERATE_LATEX is set to YES.
1738
1739 LATEX_EXTRA_FILES =
1740
1741 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
1742 # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
1743 # contain links (just like the HTML output) instead of page references. This
1744 # makes the output suitable for online browsing using a PDF viewer.
1745 # The default value is: YES.
1746 # This tag requires that the tag GENERATE_LATEX is set to YES.
10521747
10531748 PDF_HYPERLINKS = YES
10541749
1055 # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
1056 # plain latex in the generated Makefile. Set this option to YES to get a
1750 # If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
1751 # the PDF file directly from the LaTeX files. Set this option to YES, to get a
10571752 # higher quality PDF documentation.
1753 # The default value is: YES.
1754 # This tag requires that the tag GENERATE_LATEX is set to YES.
10581755
10591756 USE_PDFLATEX = YES
10601757
1061 # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
1062 # command to the generated LaTeX files. This will instruct LaTeX to keep
1063 # running if errors occur, instead of asking the user for help.
1064 # This option is also used when generating formulas in HTML.
1758 # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
1759 # command to the generated LaTeX files. This will instruct LaTeX to keep running
1760 # if errors occur, instead of asking the user for help. This option is also used
1761 # when generating formulas in HTML.
1762 # The default value is: NO.
1763 # This tag requires that the tag GENERATE_LATEX is set to YES.
10651764
10661765 LATEX_BATCHMODE = NO
10671766
1068 # If LATEX_HIDE_INDICES is set to YES then doxygen will not
1069 # include the index chapters (such as File Index, Compound Index, etc.)
1070 # in the output.
1767 # If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
1768 # index chapters (such as File Index, Compound Index, etc.) in the output.
1769 # The default value is: NO.
1770 # This tag requires that the tag GENERATE_LATEX is set to YES.
10711771
10721772 LATEX_HIDE_INDICES = NO
10731773
1074 # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
1774 # If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
1775 # code with syntax highlighting in the LaTeX output.
1776 #
1777 # Note that which sources are shown also depends on other settings such as
1778 # SOURCE_BROWSER.
1779 # The default value is: NO.
1780 # This tag requires that the tag GENERATE_LATEX is set to YES.
10751781
10761782 LATEX_SOURCE_CODE = NO
10771783
1078 #---------------------------------------------------------------------------
1079 # configuration options related to the RTF output
1080 #---------------------------------------------------------------------------
1081
1082 # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
1083 # The RTF output is optimized for Word 97 and may not look very pretty with
1084 # other RTF readers or editors.
1784 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
1785 # bibliography, e.g. plainnat, or ieeetr. See
1786 # http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
1787 # The default value is: plain.
1788 # This tag requires that the tag GENERATE_LATEX is set to YES.
1789
1790 LATEX_BIB_STYLE = plain
1791
1792 # If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
1793 # page will contain the date and time when the page was generated. Setting this
1794 # to NO can help when comparing the output of multiple runs.
1795 # The default value is: NO.
1796 # This tag requires that the tag GENERATE_LATEX is set to YES.
1797
1798 LATEX_TIMESTAMP = NO
1799
1800 #---------------------------------------------------------------------------
1801 # Configuration options related to the RTF output
1802 #---------------------------------------------------------------------------
1803
1804 # If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
1805 # RTF output is optimized for Word 97 and may not look too pretty with other RTF
1806 # readers/editors.
1807 # The default value is: NO.
10851808
10861809 GENERATE_RTF = NO
10871810
1088 # The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
1089 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
1090 # put in front of it. If left blank `rtf' will be used as the default path.
1811 # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
1812 # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1813 # it.
1814 # The default directory is: rtf.
1815 # This tag requires that the tag GENERATE_RTF is set to YES.
10911816
10921817 RTF_OUTPUT = rtf
10931818
1094 # If the COMPACT_RTF tag is set to YES Doxygen generates more compact
1095 # RTF documents. This may be useful for small projects and may help to
1096 # save some trees in general.
1819 # If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
1820 # documents. This may be useful for small projects and may help to save some
1821 # trees in general.
1822 # The default value is: NO.
1823 # This tag requires that the tag GENERATE_RTF is set to YES.
10971824
10981825 COMPACT_RTF = NO
10991826
1100 # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
1101 # will contain hyperlink fields. The RTF file will
1102 # contain links (just like the HTML output) instead of page references.
1103 # This makes the output suitable for online browsing using WORD or other
1104 # programs which support those fields.
1105 # Note: wordpad (write) and others do not support links.
1827 # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
1828 # contain hyperlink fields. The RTF file will contain links (just like the HTML
1829 # output) instead of page references. This makes the output suitable for online
1830 # browsing using Word or some other Word compatible readers that support those
1831 # fields.
1832 #
1833 # Note: WordPad (write) and others do not support links.
1834 # The default value is: NO.
1835 # This tag requires that the tag GENERATE_RTF is set to YES.
11061836
11071837 RTF_HYPERLINKS = NO
11081838
1109 # Load stylesheet definitions from file. Syntax is similar to doxygen's
1110 # config file, i.e. a series of assignments. You only have to provide
1111 # replacements, missing definitions are set to their default value.
1839 # Load stylesheet definitions from file. Syntax is similar to doxygen's config
1840 # file, i.e. a series of assignments. You only have to provide replacements,
1841 # missing definitions are set to their default value.
1842 #
1843 # See also section "Doxygen usage" for information on how to generate the
1844 # default style sheet that doxygen normally uses.
1845 # This tag requires that the tag GENERATE_RTF is set to YES.
11121846
11131847 RTF_STYLESHEET_FILE =
11141848
1115 # Set optional variables used in the generation of an rtf document.
1116 # Syntax is similar to doxygen's config file.
1849 # Set optional variables used in the generation of an RTF document. Syntax is
1850 # similar to doxygen's config file. A template extensions file can be generated
1851 # using doxygen -e rtf extensionFile.
1852 # This tag requires that the tag GENERATE_RTF is set to YES.
11171853
11181854 RTF_EXTENSIONS_FILE =
11191855
1120 #---------------------------------------------------------------------------
1121 # configuration options related to the man page output
1122 #---------------------------------------------------------------------------
1123
1124 # If the GENERATE_MAN tag is set to YES (the default) Doxygen will
1125 # generate man pages
1856 # If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
1857 # with syntax highlighting in the RTF output.
1858 #
1859 # Note that which sources are shown also depends on other settings such as
1860 # SOURCE_BROWSER.
1861 # The default value is: NO.
1862 # This tag requires that the tag GENERATE_RTF is set to YES.
1863
1864 RTF_SOURCE_CODE = NO
1865
1866 #---------------------------------------------------------------------------
1867 # Configuration options related to the man page output
1868 #---------------------------------------------------------------------------
1869
1870 # If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
1871 # classes and files.
1872 # The default value is: NO.
11261873
11271874 GENERATE_MAN = NO
11281875
1129 # The MAN_OUTPUT tag is used to specify where the man pages will be put.
1130 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
1131 # put in front of it. If left blank `man' will be used as the default path.
1876 # The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
1877 # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1878 # it. A directory man3 will be created inside the directory specified by
1879 # MAN_OUTPUT.
1880 # The default directory is: man.
1881 # This tag requires that the tag GENERATE_MAN is set to YES.
11321882
11331883 MAN_OUTPUT = man
11341884
1135 # The MAN_EXTENSION tag determines the extension that is added to
1136 # the generated man pages (default is the subroutine's section .3)
1885 # The MAN_EXTENSION tag determines the extension that is added to the generated
1886 # man pages. In case the manual section does not start with a number, the number
1887 # 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
1888 # optional.
1889 # The default value is: .3.
1890 # This tag requires that the tag GENERATE_MAN is set to YES.
11371891
11381892 MAN_EXTENSION = .3
11391893
1140 # If the MAN_LINKS tag is set to YES and Doxygen generates man output,
1141 # then it will generate one additional man file for each entity
1142 # documented in the real man page(s). These additional files
1143 # only source the real man page, but without them the man command
1144 # would be unable to find the correct page. The default is NO.
1894 # The MAN_SUBDIR tag determines the name of the directory created within
1895 # MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
1896 # MAN_EXTENSION with the initial . removed.
1897 # This tag requires that the tag GENERATE_MAN is set to YES.
1898
1899 MAN_SUBDIR =
1900
1901 # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
1902 # will generate one additional man file for each entity documented in the real
1903 # man page(s). These additional files only source the real man page, but without
1904 # them the man command would be unable to find the correct page.
1905 # The default value is: NO.
1906 # This tag requires that the tag GENERATE_MAN is set to YES.
11451907
11461908 MAN_LINKS = NO
11471909
11481910 #---------------------------------------------------------------------------
1149 # configuration options related to the XML output
1150 #---------------------------------------------------------------------------
1151
1152 # If the GENERATE_XML tag is set to YES Doxygen will
1153 # generate an XML file that captures the structure of
1154 # the code including all documentation.
1911 # Configuration options related to the XML output
1912 #---------------------------------------------------------------------------
1913
1914 # If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
1915 # captures the structure of the code including all documentation.
1916 # The default value is: NO.
11551917
11561918 GENERATE_XML = NO
11571919
1158 # The XML_OUTPUT tag is used to specify where the XML pages will be put.
1159 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
1160 # put in front of it. If left blank `xml' will be used as the default path.
1920 # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
1921 # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1922 # it.
1923 # The default directory is: xml.
1924 # This tag requires that the tag GENERATE_XML is set to YES.
11611925
11621926 XML_OUTPUT = xml
11631927
1164 # The XML_SCHEMA tag can be used to specify an XML schema,
1165 # which can be used by a validating XML parser to check the
1166 # syntax of the XML files.
1167
1168 XML_SCHEMA =
1169
1170 # The XML_DTD tag can be used to specify an XML DTD,
1171 # which can be used by a validating XML parser to check the
1172 # syntax of the XML files.
1173
1174 XML_DTD =
1175
1176 # If the XML_PROGRAMLISTING tag is set to YES Doxygen will
1177 # dump the program listings (including syntax highlighting
1178 # and cross-referencing information) to the XML output. Note that
1179 # enabling this will significantly increase the size of the XML output.
1928 # If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
1929 # listings (including syntax highlighting and cross-referencing information) to
1930 # the XML output. Note that enabling this will significantly increase the size
1931 # of the XML output.
1932 # The default value is: YES.
1933 # This tag requires that the tag GENERATE_XML is set to YES.
11801934
11811935 XML_PROGRAMLISTING = YES
11821936
11831937 #---------------------------------------------------------------------------
1184 # configuration options for the AutoGen Definitions output
1185 #---------------------------------------------------------------------------
1186
1187 # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
1188 # generate an AutoGen Definitions (see autogen.sf.net) file
1189 # that captures the structure of the code including all
1190 # documentation. Note that this feature is still experimental
1191 # and incomplete at the moment.
1938 # Configuration options related to the DOCBOOK output
1939 #---------------------------------------------------------------------------
1940
1941 # If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
1942 # that can be used to generate PDF.
1943 # The default value is: NO.
1944
1945 GENERATE_DOCBOOK = NO
1946
1947 # The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
1948 # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
1949 # front of it.
1950 # The default directory is: docbook.
1951 # This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1952
1953 DOCBOOK_OUTPUT = docbook
1954
1955 # If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
1956 # program listings (including syntax highlighting and cross-referencing
1957 # information) to the DOCBOOK output. Note that enabling this will significantly
1958 # increase the size of the DOCBOOK output.
1959 # The default value is: NO.
1960 # This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1961
1962 DOCBOOK_PROGRAMLISTING = NO
1963
1964 #---------------------------------------------------------------------------
1965 # Configuration options for the AutoGen Definitions output
1966 #---------------------------------------------------------------------------
1967
1968 # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
1969 # AutoGen Definitions (see http://autogen.sf.net) file that captures the
1970 # structure of the code including all documentation. Note that this feature is
1971 # still experimental and incomplete at the moment.
1972 # The default value is: NO.
11921973
11931974 GENERATE_AUTOGEN_DEF = NO
11941975
11951976 #---------------------------------------------------------------------------
1196 # configuration options related to the Perl module output
1197 #---------------------------------------------------------------------------
1198
1199 # If the GENERATE_PERLMOD tag is set to YES Doxygen will
1200 # generate a Perl module file that captures the structure of
1201 # the code including all documentation. Note that this
1202 # feature is still experimental and incomplete at the
1203 # moment.
1977 # Configuration options related to the Perl module output
1978 #---------------------------------------------------------------------------
1979
1980 # If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
1981 # file that captures the structure of the code including all documentation.
1982 #
1983 # Note that this feature is still experimental and incomplete at the moment.
1984 # The default value is: NO.
12041985
12051986 GENERATE_PERLMOD = NO
12061987
1207 # If the PERLMOD_LATEX tag is set to YES Doxygen will generate
1208 # the necessary Makefile rules, Perl scripts and LaTeX code to be able
1209 # to generate PDF and DVI output from the Perl module output.
1988 # If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
1989 # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
1990 # output from the Perl module output.
1991 # The default value is: NO.
1992 # This tag requires that the tag GENERATE_PERLMOD is set to YES.
12101993
12111994 PERLMOD_LATEX = NO
12121995
1213 # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
1214 # nicely formatted so it can be parsed by a human reader.
1215 # This is useful
1216 # if you want to understand what is going on.
1217 # On the other hand, if this
1218 # tag is set to NO the size of the Perl module output will be much smaller
1219 # and Perl will parse it just the same.
1996 # If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
1997 # formatted so it can be parsed by a human reader. This is useful if you want to
1998 # understand what is going on. On the other hand, if this tag is set to NO, the
1999 # size of the Perl module output will be much smaller and Perl will parse it
2000 # just the same.
2001 # The default value is: YES.
2002 # This tag requires that the tag GENERATE_PERLMOD is set to YES.
12202003
12212004 PERLMOD_PRETTY = YES
12222005
1223 # The names of the make variables in the generated doxyrules.make file
1224 # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
1225 # This is useful so different doxyrules.make files included by the same
1226 # Makefile don't overwrite each other's variables.
2006 # The names of the make variables in the generated doxyrules.make file are
2007 # prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
2008 # so different doxyrules.make files included by the same Makefile don't
2009 # overwrite each other's variables.
2010 # This tag requires that the tag GENERATE_PERLMOD is set to YES.
12272011
12282012 PERLMOD_MAKEVAR_PREFIX =
12292013
12312015 # Configuration options related to the preprocessor
12322016 #---------------------------------------------------------------------------
12332017
1234 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
1235 # evaluate all C-preprocessor directives found in the sources and include
1236 # files.
2018 # If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
2019 # C-preprocessor directives found in the sources and include files.
2020 # The default value is: YES.
12372021
12382022 ENABLE_PREPROCESSING = YES
12392023
1240 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
1241 # names in the source code. If set to NO (the default) only conditional
1242 # compilation will be performed. Macro expansion can be done in a controlled
1243 # way by setting EXPAND_ONLY_PREDEF to YES.
2024 # If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
2025 # in the source code. If set to NO, only conditional compilation will be
2026 # performed. Macro expansion can be done in a controlled way by setting
2027 # EXPAND_ONLY_PREDEF to YES.
2028 # The default value is: NO.
2029 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12442030
12452031 MACRO_EXPANSION = NO
12462032
1247 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
1248 # then the macro expansion is limited to the macros specified with the
1249 # PREDEFINED and EXPAND_AS_DEFINED tags.
2033 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
2034 # the macro expansion is limited to the macros specified with the PREDEFINED and
2035 # EXPAND_AS_DEFINED tags.
2036 # The default value is: NO.
2037 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12502038
12512039 EXPAND_ONLY_PREDEF = NO
12522040
1253 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
1254 # in the INCLUDE_PATH (see below) will be search if a #include is found.
2041 # If the SEARCH_INCLUDES tag is set to YES, the include files in the
2042 # INCLUDE_PATH will be searched if a #include is found.
2043 # The default value is: YES.
2044 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12552045
12562046 SEARCH_INCLUDES = YES
12572047
12582048 # The INCLUDE_PATH tag can be used to specify one or more directories that
1259 # contain include files that are not input files but should be processed by
1260 # the preprocessor.
2049 # contain include files that are not input files but should be processed by the
2050 # preprocessor.
2051 # This tag requires that the tag SEARCH_INCLUDES is set to YES.
12612052
12622053 INCLUDE_PATH =
12632054
12642055 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
12652056 # patterns (like *.h and *.hpp) to filter out the header-files in the
1266 # directories. If left blank, the patterns specified with FILE_PATTERNS will
1267 # be used.
2057 # directories. If left blank, the patterns specified with FILE_PATTERNS will be
2058 # used.
2059 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12682060
12692061 INCLUDE_FILE_PATTERNS =
12702062
1271 # The PREDEFINED tag can be used to specify one or more macro names that
1272 # are defined before the preprocessor is started (similar to the -D option of
1273 # gcc). The argument of the tag is a list of macros of the form: name
1274 # or name=definition (no spaces). If the definition and the = are
1275 # omitted =1 is assumed. To prevent a macro definition from being
1276 # undefined via #undef or recursively expanded use the := operator
1277 # instead of the = operator.
2063 # The PREDEFINED tag can be used to specify one or more macro names that are
2064 # defined before the preprocessor is started (similar to the -D option of e.g.
2065 # gcc). The argument of the tag is a list of macros of the form: name or
2066 # name=definition (no spaces). If the definition and the "=" are omitted, "=1"
2067 # is assumed. To prevent a macro definition from being undefined via #undef or
2068 # recursively expanded use the := operator instead of the = operator.
2069 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12782070
12792071 PREDEFINED =
12802072
1281 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
1282 # this tag can be used to specify a list of macro names that should be expanded.
1283 # The macro definition that is found in the sources will be used.
1284 # Use the PREDEFINED tag if you want to use a different macro definition.
2073 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
2074 # tag can be used to specify a list of macro names that should be expanded. The
2075 # macro definition that is found in the sources will be used. Use the PREDEFINED
2076 # tag if you want to use a different macro definition that overrules the
2077 # definition found in the source code.
2078 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12852079
12862080 EXPAND_AS_DEFINED =
12872081
1288 # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
1289 # doxygen's preprocessor will remove all function-like macros that are alone
1290 # on a line, have an all uppercase name, and do not end with a semicolon. Such
1291 # function macros are typically used for boiler-plate code, and will confuse
1292 # the parser if not removed.
2082 # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
2083 # remove all references to function-like macros that are alone on a line, have
2084 # an all uppercase name, and do not end with a semicolon. Such function macros
2085 # are typically used for boiler-plate code, and will confuse the parser if not
2086 # removed.
2087 # The default value is: YES.
2088 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
12932089
12942090 SKIP_FUNCTION_MACROS = YES
12952091
12962092 #---------------------------------------------------------------------------
1297 # Configuration::additions related to external references
1298 #---------------------------------------------------------------------------
1299
1300 # The TAGFILES option can be used to specify one or more tagfiles.
1301 # Optionally an initial location of the external documentation
1302 # can be added for each tagfile. The format of a tag file without
1303 # this location is as follows:
1304 #
2093 # Configuration options related to external references
2094 #---------------------------------------------------------------------------
2095
2096 # The TAGFILES tag can be used to specify one or more tag files. For each tag
2097 # file the location of the external documentation should be added. The format of
2098 # a tag file without this location is as follows:
13052099 # TAGFILES = file1 file2 ...
13062100 # Adding location for the tag files is done as follows:
1307 #
13082101 # TAGFILES = file1=loc1 "file2 = loc2" ...
1309 # where "loc1" and "loc2" can be relative or absolute paths or
1310 # URLs. If a location is present for each tag, the installdox tool
1311 # does not have to be run to correct the links.
1312 # Note that each tag file must have a unique name
1313 # (where the name does NOT include the path)
1314 # If a tag file is not located in the directory in which doxygen
1315 # is run, you must also specify the path to the tagfile here.
2102 # where loc1 and loc2 can be relative or absolute paths or URLs. See the
2103 # section "Linking to external documentation" for more information about the use
2104 # of tag files.
2105 # Note: Each tag file must have a unique name (where the name does NOT include
2106 # the path). If a tag file is not located in the directory in which doxygen is
2107 # run, you must also specify the path to the tagfile here.
13162108
13172109 TAGFILES =
13182110
1319 # When a file name is specified after GENERATE_TAGFILE, doxygen will create
1320 # a tag file that is based on the input files it reads.
2111 # When a file name is specified after GENERATE_TAGFILE, doxygen will create a
2112 # tag file that is based on the input files it reads. See section "Linking to
2113 # external documentation" for more information about the usage of tag files.
13212114
13222115 GENERATE_TAGFILE = libnfc.tag
13232116
1324 # If the ALLEXTERNALS tag is set to YES all external classes will be listed
1325 # in the class index. If set to NO only the inherited external classes
1326 # will be listed.
2117 # If the ALLEXTERNALS tag is set to YES, all external class will be listed in
2118 # the class index. If set to NO, only the inherited external classes will be
2119 # listed.
2120 # The default value is: NO.
13272121
13282122 ALLEXTERNALS = NO
13292123
1330 # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
1331 # in the modules index. If set to NO, only the current project's groups will
2124 # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
2125 # in the modules index. If set to NO, only the current project's groups will be
2126 # listed.
2127 # The default value is: YES.
2128
2129 EXTERNAL_GROUPS = YES
2130
2131 # If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
2132 # the related pages index. If set to NO, only the current project's pages will
13322133 # be listed.
1333
1334 EXTERNAL_GROUPS = YES
2134 # The default value is: YES.
2135
2136 EXTERNAL_PAGES = YES
13352137
13362138 # The PERL_PATH should be the absolute path and name of the perl script
1337 # interpreter (i.e. the result of `which perl').
2139 # interpreter (i.e. the result of 'which perl').
2140 # The default file (with absolute path) is: /usr/bin/perl.
13382141
13392142 PERL_PATH = /usr/bin/perl
13402143
13422145 # Configuration options related to the dot tool
13432146 #---------------------------------------------------------------------------
13442147
1345 # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
1346 # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
1347 # or super classes. Setting the tag to NO turns the diagrams off. Note that
1348 # this option is superseded by the HAVE_DOT option below. This is only a
1349 # fallback. It is recommended to install and use dot, since it yields more
2148 # If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
2149 # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
2150 # NO turns the diagrams off. Note that this option also works with HAVE_DOT
2151 # disabled, but it is recommended to install and use dot, since it yields more
13502152 # powerful graphs.
2153 # The default value is: YES.
13512154
13522155 CLASS_DIAGRAMS = YES
13532156
13542157 # You can define message sequence charts within doxygen comments using the \msc
1355 # command. Doxygen will then run the mscgen tool (see
1356 # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
2158 # command. Doxygen will then run the mscgen tool (see:
2159 # http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
13572160 # documentation. The MSCGEN_PATH tag allows you to specify the directory where
13582161 # the mscgen tool resides. If left empty the tool is assumed to be found in the
13592162 # default search path.
13602163
13612164 MSCGEN_PATH =
13622165
1363 # If set to YES, the inheritance and collaboration graphs will hide
1364 # inheritance and usage relations if the target is undocumented
1365 # or is not a class.
2166 # You can include diagrams made with dia in doxygen documentation. Doxygen will
2167 # then run dia to produce the diagram and insert it in the documentation. The
2168 # DIA_PATH tag allows you to specify the directory where the dia binary resides.
2169 # If left empty dia is assumed to be found in the default search path.
2170
2171 DIA_PATH =
2172
2173 # If set to YES the inheritance and collaboration graphs will hide inheritance
2174 # and usage relations if the target is undocumented or is not a class.
2175 # The default value is: YES.
13662176
13672177 HIDE_UNDOC_RELATIONS = YES
13682178
13692179 # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
1370 # available from the path. This tool is part of Graphviz, a graph visualization
1371 # toolkit from AT&T and Lucent Bell Labs. The other options in this section
1372 # have no effect if this option is set to NO (the default)
2180 # available from the path. This tool is part of Graphviz (see:
2181 # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
2182 # Bell Labs. The other options in this section have no effect if this option is
2183 # set to NO
2184 # The default value is: YES.
13732185
13742186 HAVE_DOT = NO
13752187
1376 # By default doxygen will write a font called FreeSans.ttf to the output
1377 # directory and reference it in all dot files that doxygen generates. This
1378 # font does not include all possible unicode characters however, so when you need
1379 # these (or just want a differently looking font) you can specify the font name
1380 # using DOT_FONTNAME. You need need to make sure dot is able to find the font,
1381 # which can be done by putting it in a standard location or by setting the
1382 # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
1383 # containing the font.
1384
1385 DOT_FONTNAME = FreeSans
1386
1387 # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
1388 # The default size is 10pt.
2188 # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
2189 # to run in parallel. When set to 0 doxygen will base this on the number of
2190 # processors available in the system. You can set it explicitly to a value
2191 # larger than 0 to get control over the balance between CPU load and processing
2192 # speed.
2193 # Minimum value: 0, maximum value: 32, default value: 0.
2194 # This tag requires that the tag HAVE_DOT is set to YES.
2195
2196 DOT_NUM_THREADS = 0
2197
2198 # When you want a differently looking font in the dot files that doxygen
2199 # generates you can specify the font name using DOT_FONTNAME. You need to make
2200 # sure dot is able to find the font, which can be done by putting it in a
2201 # standard location or by setting the DOTFONTPATH environment variable or by
2202 # setting DOT_FONTPATH to the directory containing the font.
2203 # The default value is: Helvetica.
2204 # This tag requires that the tag HAVE_DOT is set to YES.
2205
2206 DOT_FONTNAME =
2207
2208 # The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
2209 # dot graphs.
2210 # Minimum value: 4, maximum value: 24, default value: 10.
2211 # This tag requires that the tag HAVE_DOT is set to YES.
13892212
13902213 DOT_FONTSIZE = 10
13912214
1392 # By default doxygen will tell dot to use the output directory to look for the
1393 # FreeSans.ttf font (which doxygen will put there itself). If you specify a
1394 # different font using DOT_FONTNAME you can set the path where dot
1395 # can find it using this tag.
2215 # By default doxygen will tell dot to use the default font as specified with
2216 # DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
2217 # the path where dot can find it using this tag.
2218 # This tag requires that the tag HAVE_DOT is set to YES.
13962219
13972220 DOT_FONTPATH =
13982221
1399 # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
1400 # will generate a graph for each documented class showing the direct and
1401 # indirect inheritance relations. Setting this tag to YES will force the
1402 # the CLASS_DIAGRAMS tag to NO.
2222 # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
2223 # each documented class showing the direct and indirect inheritance relations.
2224 # Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
2225 # The default value is: YES.
2226 # This tag requires that the tag HAVE_DOT is set to YES.
14032227
14042228 CLASS_GRAPH = YES
14052229
1406 # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
1407 # will generate a graph for each documented class showing the direct and
1408 # indirect implementation dependencies (inheritance, containment, and
1409 # class references variables) of the class with other documented classes.
2230 # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
2231 # graph for each documented class showing the direct and indirect implementation
2232 # dependencies (inheritance, containment, and class references variables) of the
2233 # class with other documented classes.
2234 # The default value is: YES.
2235 # This tag requires that the tag HAVE_DOT is set to YES.
14102236
14112237 COLLABORATION_GRAPH = YES
14122238
1413 # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
1414 # will generate a graph for groups, showing the direct groups dependencies
2239 # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
2240 # groups, showing the direct groups dependencies.
2241 # The default value is: YES.
2242 # This tag requires that the tag HAVE_DOT is set to YES.
14152243
14162244 GROUP_GRAPHS = YES
14172245
1418 # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
2246 # If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
14192247 # collaboration diagrams in a style similar to the OMG's Unified Modeling
14202248 # Language.
2249 # The default value is: NO.
2250 # This tag requires that the tag HAVE_DOT is set to YES.
14212251
14222252 UML_LOOK = NO
14232253
1424 # If set to YES, the inheritance and collaboration graphs will show the
1425 # relations between templates and their instances.
2254 # If the UML_LOOK tag is enabled, the fields and methods are shown inside the
2255 # class node. If there are many fields or methods and many nodes the graph may
2256 # become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
2257 # number of items for each type to make the size more manageable. Set this to 0
2258 # for no limit. Note that the threshold may be exceeded by 50% before the limit
2259 # is enforced. So when you set the threshold to 10, up to 15 fields may appear,
2260 # but if the number exceeds 15, the total amount of fields shown is limited to
2261 # 10.
2262 # Minimum value: 0, maximum value: 100, default value: 10.
2263 # This tag requires that the tag HAVE_DOT is set to YES.
2264
2265 UML_LIMIT_NUM_FIELDS = 10
2266
2267 # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
2268 # collaboration graphs will show the relations between templates and their
2269 # instances.
2270 # The default value is: NO.
2271 # This tag requires that the tag HAVE_DOT is set to YES.
14262272
14272273 TEMPLATE_RELATIONS = NO
14282274
1429 # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
1430 # tags are set to YES then doxygen will generate a graph for each documented
1431 # file showing the direct and indirect include dependencies of the file with
1432 # other documented files.
2275 # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
2276 # YES then doxygen will generate a graph for each documented file showing the
2277 # direct and indirect include dependencies of the file with other documented
2278 # files.
2279 # The default value is: YES.
2280 # This tag requires that the tag HAVE_DOT is set to YES.
14332281
14342282 INCLUDE_GRAPH = YES
14352283
1436 # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
1437 # HAVE_DOT tags are set to YES then doxygen will generate a graph for each
1438 # documented header file showing the documented files that directly or
1439 # indirectly include this file.
2284 # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
2285 # set to YES then doxygen will generate a graph for each documented file showing
2286 # the direct and indirect include dependencies of the file with other documented
2287 # files.
2288 # The default value is: YES.
2289 # This tag requires that the tag HAVE_DOT is set to YES.
14402290
14412291 INCLUDED_BY_GRAPH = YES
14422292
1443 # If the CALL_GRAPH and HAVE_DOT options are set to YES then
1444 # doxygen will generate a call dependency graph for every global function
1445 # or class method. Note that enabling this option will significantly increase
1446 # the time of a run. So in most cases it will be better to enable call graphs
1447 # for selected functions only using the \callgraph command.
2293 # If the CALL_GRAPH tag is set to YES then doxygen will generate a call
2294 # dependency graph for every global function or class method.
2295 #
2296 # Note that enabling this option will significantly increase the time of a run.
2297 # So in most cases it will be better to enable call graphs for selected
2298 # functions only using the \callgraph command. Disabling a call graph can be
2299 # accomplished by means of the command \hidecallgraph.
2300 # The default value is: NO.
2301 # This tag requires that the tag HAVE_DOT is set to YES.
14482302
14492303 CALL_GRAPH = NO
14502304
1451 # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
1452 # doxygen will generate a caller dependency graph for every global function
1453 # or class method. Note that enabling this option will significantly increase
1454 # the time of a run. So in most cases it will be better to enable caller
1455 # graphs for selected functions only using the \callergraph command.
2305 # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
2306 # dependency graph for every global function or class method.
2307 #
2308 # Note that enabling this option will significantly increase the time of a run.
2309 # So in most cases it will be better to enable caller graphs for selected
2310 # functions only using the \callergraph command. Disabling a caller graph can be
2311 # accomplished by means of the command \hidecallergraph.
2312 # The default value is: NO.
2313 # This tag requires that the tag HAVE_DOT is set to YES.
14562314
14572315 CALLER_GRAPH = NO
14582316
1459 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
1460 # will graphical hierarchy of all classes instead of a textual one.
2317 # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
2318 # hierarchy of all classes instead of a textual one.
2319 # The default value is: YES.
2320 # This tag requires that the tag HAVE_DOT is set to YES.
14612321
14622322 GRAPHICAL_HIERARCHY = YES
14632323
1464 # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
1465 # then doxygen will show the dependencies a directory has on other directories
1466 # in a graphical way. The dependency relations are determined by the #include
1467 # relations between the files in the directories.
2324 # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
2325 # dependencies a directory has on other directories in a graphical way. The
2326 # dependency relations are determined by the #include relations between the
2327 # files in the directories.
2328 # The default value is: YES.
2329 # This tag requires that the tag HAVE_DOT is set to YES.
14682330
14692331 DIRECTORY_GRAPH = YES
14702332
14712333 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
1472 # generated by dot. Possible values are png, jpg, or gif
1473 # If left blank png will be used.
2334 # generated by dot. For an explanation of the image formats see the section
2335 # output formats in the documentation of the dot tool (Graphviz (see:
2336 # http://www.graphviz.org/)).
2337 # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2338 # to make the SVG files visible in IE 9+ (other browsers do not have this
2339 # requirement).
2340 # Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
2341 # png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
2342 # gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
2343 # png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
2344 # png:gdiplus:gdiplus.
2345 # The default value is: png.
2346 # This tag requires that the tag HAVE_DOT is set to YES.
14742347
14752348 DOT_IMAGE_FORMAT = png
14762349
1477 # The tag DOT_PATH can be used to specify the path where the dot tool can be
2350 # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
2351 # enable generation of interactive SVG images that allow zooming and panning.
2352 #
2353 # Note that this requires a modern browser other than Internet Explorer. Tested
2354 # and working are Firefox, Chrome, Safari, and Opera.
2355 # Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
2356 # the SVG files visible. Older versions of IE do not have SVG support.
2357 # The default value is: NO.
2358 # This tag requires that the tag HAVE_DOT is set to YES.
2359
2360 INTERACTIVE_SVG = NO
2361
2362 # The DOT_PATH tag can be used to specify the path where the dot tool can be
14782363 # found. If left blank, it is assumed the dot tool can be found in the path.
2364 # This tag requires that the tag HAVE_DOT is set to YES.
14792365
14802366 DOT_PATH =
14812367
14822368 # The DOTFILE_DIRS tag can be used to specify one or more directories that
1483 # contain dot files that are included in the documentation (see the
1484 # \dotfile command).
2369 # contain dot files that are included in the documentation (see the \dotfile
2370 # command).
2371 # This tag requires that the tag HAVE_DOT is set to YES.
14852372
14862373 DOTFILE_DIRS =
14872374
1488 # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
1489 # nodes that will be shown in the graph. If the number of nodes in a graph
1490 # becomes larger than this value, doxygen will truncate the graph, which is
1491 # visualized by representing a node as a red box. Note that doxygen if the
1492 # number of direct children of the root node in a graph is already larger than
1493 # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
1494 # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2375 # The MSCFILE_DIRS tag can be used to specify one or more directories that
2376 # contain msc files that are included in the documentation (see the \mscfile
2377 # command).
2378
2379 MSCFILE_DIRS =
2380
2381 # The DIAFILE_DIRS tag can be used to specify one or more directories that
2382 # contain dia files that are included in the documentation (see the \diafile
2383 # command).
2384
2385 DIAFILE_DIRS =
2386
2387 # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
2388 # path where java can find the plantuml.jar file. If left blank, it is assumed
2389 # PlantUML is not used or called during a preprocessing step. Doxygen will
2390 # generate a warning when it encounters a \startuml command in this case and
2391 # will not generate output for the diagram.
2392
2393 PLANTUML_JAR_PATH =
2394
2395 # When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
2396 # configuration file for plantuml.
2397
2398 PLANTUML_CFG_FILE =
2399
2400 # When using plantuml, the specified paths are searched for files specified by
2401 # the !include statement in a plantuml block.
2402
2403 PLANTUML_INCLUDE_PATH =
2404
2405 # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2406 # that will be shown in the graph. If the number of nodes in a graph becomes
2407 # larger than this value, doxygen will truncate the graph, which is visualized
2408 # by representing a node as a red box. Note that doxygen if the number of direct
2409 # children of the root node in a graph is already larger than
2410 # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
2411 # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2412 # Minimum value: 0, maximum value: 10000, default value: 50.
2413 # This tag requires that the tag HAVE_DOT is set to YES.
14952414
14962415 DOT_GRAPH_MAX_NODES = 50
14972416
1498 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
1499 # graphs generated by dot. A depth value of 3 means that only nodes reachable
1500 # from the root by following a path via at most 3 edges will be shown. Nodes
1501 # that lay further from the root node will be omitted. Note that setting this
1502 # option to 1 or 2 may greatly reduce the computation time needed for large
1503 # code bases. Also note that the size of a graph can be further restricted by
2417 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
2418 # generated by dot. A depth value of 3 means that only nodes reachable from the
2419 # root by following a path via at most 3 edges will be shown. Nodes that lay
2420 # further from the root node will be omitted. Note that setting this option to 1
2421 # or 2 may greatly reduce the computation time needed for large code bases. Also
2422 # note that the size of a graph can be further restricted by
15042423 # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
2424 # Minimum value: 0, maximum value: 1000, default value: 0.
2425 # This tag requires that the tag HAVE_DOT is set to YES.
15052426
15062427 MAX_DOT_GRAPH_DEPTH = 1000
15072428
15082429 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
1509 # background. This is disabled by default, because dot on Windows does not
1510 # seem to support this out of the box. Warning: Depending on the platform used,
1511 # enabling this option may lead to badly anti-aliased labels on the edges of
1512 # a graph (i.e. they become hard to read).
2430 # background. This is disabled by default, because dot on Windows does not seem
2431 # to support this out of the box.
2432 #
2433 # Warning: Depending on the platform used, enabling this option may lead to
2434 # badly anti-aliased labels on the edges of a graph (i.e. they become hard to
2435 # read).
2436 # The default value is: NO.
2437 # This tag requires that the tag HAVE_DOT is set to YES.
15132438
15142439 DOT_TRANSPARENT = YES
15152440
1516 # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
2441 # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
15172442 # files in one run (i.e. multiple -o and -T options on the command line). This
1518 # makes dot run faster, but since only newer versions of dot (>1.8.10)
1519 # support this, this feature is disabled by default.
2443 # makes dot run faster, but since only newer versions of dot (>1.8.10) support
2444 # this, this feature is disabled by default.
2445 # The default value is: NO.
2446 # This tag requires that the tag HAVE_DOT is set to YES.
15202447
15212448 DOT_MULTI_TARGETS = NO
15222449
1523 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
1524 # generate a legend page explaining the meaning of the various boxes and
1525 # arrows in the dot generated graphs.
2450 # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
2451 # explaining the meaning of the various boxes and arrows in the dot generated
2452 # graphs.
2453 # The default value is: YES.
2454 # This tag requires that the tag HAVE_DOT is set to YES.
15262455
15272456 GENERATE_LEGEND = YES
15282457
1529 # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
1530 # remove the intermediate dot files that are used to generate
1531 # the various graphs.
2458 # If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
2459 # files that are used to generate the various graphs.
2460 # The default value is: YES.
2461 # This tag requires that the tag HAVE_DOT is set to YES.
15322462
15332463 DOT_CLEANUP = YES
+0
-54
HACKING less more
0 Hello hackers!
1
2 General remarks about contributing
3 ----------------------------------
4
5 Contributions to the libnfc are welcome!
6 Here are some directions to get you started:
7
8 1. Follow style conventions
9 The source code of the library trend to follow some conventions so that it
10 is consistent in style and thus easier to read.
11 Look around and respect the same style.
12 Don't use tabs. Increment unit is two spaces.
13 Don't leave dandling spaces or tabs at EOL.
14 Helper script to get some uniformity in the style:
15 $ make style
16
17 If you use vim see the "Vim: How to prevent trailing whitespaces"
18 http://www.carbon-project.org/Vim__How_to_prevent_trailing_whitespaces.html
19
20 2. Chase warnings: no warning should be introduced by your changes
21 Depending what you touch, you can check with:
22 2.1 When using autotools
23 $ autoreconf -Wall -vis
24 2.2 When compiling
25 2.2.1 Using extra flags:
26 $ export CFLAGS="-Wall -g -O2 -Wextra -pipe -funsigned-char -fstrict-aliasing \
27 -Wchar-subscripts -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wunused \
28 -Wuninitialized -Wpointer-arith -Wredundant-decls -Winline -Wformat \
29 -Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs \
30 -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \
31 -Wbad-function-cast -Wnested-externs -Wmissing-declarations"
32 $ ./configure
33 $ make clean
34 $ make
35 2.2.2 Using clang:
36 $ scan-build ./configure
37 $ make clean
38 $ scan-build make
39 2.2.3 Using cppcheck (v1.58 or higher):
40 $ make cppcheck
41 2.3 When Debianizing
42 $ lintian --info --display-info --display-experimental *deb
43 or (shorter version)
44 $ lintian -iIE *deb
45
46 3. Preserve cross-platform compatility
47 The source code should remain compilable across various platforms,
48 including some you probably cannot test alone so keep it in mind.
49 Supported platforms:
50 - Linux
51 - FreeBSD
52 - Mac OS X
53 - Windows with Mingw
0 Hello hackers!
1
2 General remarks about contributing
3 ----------------------------------
4
5 Contributions to the libnfc are welcome!
6 Here are some directions to get you started:
7
8 1. Follow style conventions
9 The source code of the library trend to follow some conventions so that it
10 is consistent in style and thus easier to read.
11 Look around and respect the same style.
12 Don't use tabs. Increment unit is two spaces.
13 Don't leave dandling spaces or tabs at EOL.
14 Helper script to get some uniformity in the style:
15 $ make style
16
17 If you use vim see the [Vim: How to prevent trailing whitespaces](http://www.carbon-project.org/Vim__How_to_prevent_trailing_whitespaces.html).
18
19 2. Chase warnings: no warning should be introduced by your changes
20 Depending what you touch, you can check with:
21
22 2.1 When using autotools
23
24 $ autoreconf -Wall -vis
25
26 2.2 When compiling
27
28 2.2.1 Using extra flags:
29
30 $ export CFLAGS="-Wall -g -O2 -Wextra -pipe -funsigned-char -fstrict-aliasing \
31 -Wchar-subscripts -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wunused \
32 -Wuninitialized -Wpointer-arith -Wredundant-decls -Winline -Wformat \
33 -Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs \
34 -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \
35 -Wbad-function-cast -Wnested-externs -Wmissing-declarations"
36 $ ./configure
37 $ make clean
38 $ make
39
40 2.2.2 Using clang:
41
42 You can use same CFLAGS but also `-Wunreachable-code`
43
44 $ scan-build ./configure
45 $ make clean
46 $ scan-build make
47
48 2.2.3 Using `cppcheck` (v1.58 or higher):
49
50 $ make cppcheck
51
52 2.3 When Debianizing
53
54 $ lintian --info --display-info --display-experimental *deb
55 or (shorter version)
56 $ lintian -iIE *deb
57
58 3. Preserve cross-platform compatibility
59
60 The source code should remain compilable across various platforms,
61 including some you probably cannot test alone so keep it in mind.
62 Supported platforms:
63
64 - Linux
65 - FreeBSD
66 - Mac OS X
67 - Windows with MinGW
99 EXTRA_DIST = \
1010 CMakeLists.txt \
1111 Doxyfile \
12 README-Windows.txt \
13 libnfc.conf.sample
12 HACKING.md \
13 NEWS.md \
14 README.md \
15 README-Windows.md \
16 libnfc.conf.sample \
17 mingw-cross-compile.sh
1418
1519 CLEANFILES = Doxygen.log coverage.info libnfc.pc
1620
3337 find . -name "*.[ch]" -exec astyle --formatted --mode=c --suffix=none \
3438 --indent=spaces=2 --indent-switches --indent-preprocessor \
3539 --keep-one-line-blocks --max-instatement-indent=60 \
36 --brackets=linux --pad-oper --unpad-paren --pad-header \
40 --style=linux --pad-oper --unpad-paren --pad-header \
3741 --align-pointer=name {} \;
3842
3943 cppcheck:
+0
-373
NEWS less more
0 New in 1.7.1:
1
2 API Changes:
3
4 * nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL
5 * nfc_initiator_target_is_present() allow NULL pointer to tag
6
7 New in 1.7.0:
8
9 Drivers:
10
11 * New PN532 over I2C driver, see contrib/libnfc/pn532_i2c_on_rpi.conf.sample
12
13 API Changes:
14
15 * New function iso14443b_crc_append()
16
17 New in 1.7.0-rc7:
18
19 Drivers:
20
21 * New PN532 over SPI driver, see contrib/libnfc/pn532_spi_on_rpi.conf.sample
22
23 API Changes:
24
25 * Functions
26 - nfc_initiator_target_is_present() & str_nfc_target():
27 now take a pointer to nfc_target as argument
28 - nfc_init(): upon malloc error, doesn't force exit() anymore
29 so now you should test if context != NULL after nfc_init() call
30
31 New in 1.7.0-rc5:
32
33 API Changes:
34
35 * Functions
36 - New nfc_register_driver() function allowing to hook custom drivers.
37
38 New in 1.7.0-rc3:
39
40 API Changes:
41
42 * Functions
43 - Add timeout param to nfc_emulate_target()
44
45 New in 1.7.0-rc2:
46
47 Configuration:
48 libnfc can now use a configuration file for special setups, or features
49 activation. This file (/etc/nfc/libnfc.conf under GNU/Linux systems)
50 supports already some keywords:
51 - "allow_autoscan" to enable/disable device auto-detection feature;
52 - "allow_intrusive_scan" to enable/disable intrusive auto-detection
53 (ie. serial port probing);
54 - "log_level" to select library verbosity;
55 - "device.name" and "device.connstring" to define a user device,
56 this is the recommended method if user has a not easily detectable
57 device (ie. a serial one).
58 It is also possible to define devices using dedicated configuration files and
59 put them into device search directory (/etc/nfc/devices.d under GNU/Linux).
60 Example for the OpenPCD2: create /etc/nfc/devices.d/openpcd2.conf with:
61 name = "OpenPCD2"
62 connstring = "pn532_uart:/dev/ttyACM0"
63 optional = true
64 The keyword "optional" does not mandate the device to be present always
65 (it detects if the reader is indeed present before using it)
66
67 API Changes:
68
69 * Types
70 - New NFC_ESOFT error to handle software errors (allocations, pipe
71 creation, etc.)
72
73 * Functions
74 - Remove nfc_get_default_device() function: the default device is now the
75 first in nfc_list_devices() or could be open using NULL connstring with
76 nfc_open() function.
77 - New enum-to-string converter functions str_nfc_modulation_type() and
78 str_nfc_baud_rate()
79 - New str_nfc_target() to convert nfc_target struct into allocated string
80 - New nfc_device_get_information_about() function to retreive some device's
81 information
82 - No more in/out function parameter: nfc_initiator_transceive_*() now
83 take a constant size for Rx buffer
84 - New nfc_initiator_target_is_present() to test is the previously selected
85 target is available in the field
86 - nfc_initiator_transceive_bytes() returns NFC_EMFCAUTHFAIL when AUTH
87 command failed on a Mifare Classic
88 - New nfc_initiator_init_secure_element() to initiate a connection with
89 secure element (Only supported with a PN532 with SAM equipped)
90
91 New in 1.6.0-rc1:
92
93 API Changes:
94
95 * Types
96 - '_t' suffix removed from all types (e.g. nfc_device_t is now nfc_device)
97 - All errors removed in flavour of NFC_EIO, NFC_EINVARG, NFC_EDEVNOTSUPP,
98 NFC_ENOTSUCHDEV, NFC_EOVFLOW, NFC_ETIMEOUT, NFC_EOPABORTED, NFC_ENOTIMPL,
99 NFC_ETGRELEASED, NFC_ERFTRANS, NFC_ECHIP and NFC_SUCCESS
100 - nfc_device_desc_t replaced by nfc_connstring: libnfc now uses connection
101 strings to describe a device
102 - byte_t typedef removed, libnfc now uses uint8_t from C99
103 - nfc_device is now an opaque type
104 - nfc_properties replaces nfc_options
105
106 * Functions
107 - New nfc_get_default_device() function that allows to grab the connstring
108 stored in LIBNFC_DEFAULT_DEVICE environnement variable or returns the
109 first available device if not set
110 - New nfc_device_get_connstring() accessor function to know the device
111 connstring
112 - New nfc_device_set_property_bool() function that replace nfc_configure()
113 - New nfc_device_set_property_int() function to set integer property
114 - nfc_device_name() renamed to nfc_device_get_name() for the sake of
115 consistency
116 - New nfc_device_get_last_error() function, an accessor to last error occured
117 - Whole libnfc's functions now return 0 (NFC_SUCCESS) or positive value if
118 appropriated on success and libnfc's error code on failure
119 - nfc_connect(), nfc_disconnect() renamed to nfc_open(), nfc_close()
120 respectively
121 - Add 2 new functions: initialization and deinitialization functions:
122 nfc_init() and nfc_exit()
123 - New nfc_device_get_supported_modulation() and
124 nfc_device_get_supported_baud_rate() functions
125
126 * Dependencies
127 - log4c is not anymore used for debugging facility. It was a bad choice,
128 sorry for inconvenience.
129
130 New in 1.5.1:
131
132 API Changes
133
134 * Types
135 - Communication-level errors DEIO and DETIMEOUT are now know as ECOMIO,
136 ECOMTIMEOUT respectively
137 - Common device-level errors DEINVAL and DEABORT are now know as EINVALARG,
138 EOPABORT respectively
139 - New errors: EFRAACKMISMATCH, EFRAISERRFRAME, EDEVNOTSUP and ENOTIMPL
140
141 * Functions
142 - nfc_abort_command() returns a boolean
143 - timeout (struct timeval) pointer added to
144 nfc_initiator_transceive_bytes(), nfc_target_send_bytes() and
145 nfc_target_receive_bytes()
146 - timed functions nfc_initiator_transceive_bytes_timed() and
147 nfc_initiator_transceive_bits_timed() now takes uint32_t as cycles
148 pointer
149 - nfc_initiator_poll_targets() renamed to nfc_initiator_poll_target() and
150 only return one target
151
152 New in 1.5.0:
153
154 Installed files
155 - nfc-message.h have been removed, internal macros are not part of API.
156 - New nfc-emulation.h file offers a middle level API to handle emulation (see
157 nfc-emulate-forum-tag4 example)
158
159 API Changes
160
161 * Types
162 - New error: DEABORT raised when operation is aborted by user (using
163 nfc_abort_command())
164 - nfc_chip_t type removed from public API (have been renamed to pn53x_type
165 in chips/pn53x)
166 - nfc_device_spec_t removed, each driver can use his own way to keep a
167 connection pointer
168
169 * Structures
170 - nfc_device_t now have a nfc_driver_t struct pointer (named .driver) and
171 void pointer (.driver_data) to handle device specific wrapping
172 - nfc_device_t now have a void pointer (.chip_data) to keep some chip
173 specific data
174 - nfc_device_t now have an file descriptor array to manage to abort request
175 - nfc_device_t does have .nc member (nfc_chip_t) anymore (different chips
176 handling in now in chip level)
177 - nfc_device_t does have .nds member (nfc_device_spec_t) anymore, each
178 driver handle its communication using driver_data pointer
179 - nfc_device_t does have .bActive member (bool) anymore, this variable was
180 almost not used and was not efficient
181 - nfc_device_t does have chip's register caches anymore, this is handle in
182 chip level (using chip_data pointer)
183 - driver_callbacks structure have been removed from public API
184 - New nfc_emulator structure used by the new emulation API (see
185 nfc_emulate_target())
186 - New nfc_emulation_state_machine structure used by the new emulation API,
187 it handles an I/O function and data pointer to create a software based
188 state-machine.
189
190 * Functions
191 - New nfc_abort_command() function to abort current running command.
192 - New nfc_initiator_transceive_bits_timed() and
193 nfc_initiator_transceive_bytes_timed() to transceive bits/bytes and
194 measure the time to have a reply
195 - New nfc_emulate_target() function to start a target emulation using an
196 nfc_emulator structure (it contains a custom state-machine
197 (nfc_emulation_state_machine struct) and a custom target (nfc_target_t)
198 (see nfc-emulate-forum-tag4 to have a look on how-to use it)
199
200
201
202 New in 1.4.1:
203
204 API Changes
205
206 * Types
207 - New error: ETGUIDNOTSUP raised when UID is not 4 bytes long or does not
208 start with 0x08 (Security restriction present in the NXP PN53x chips)
209
210
211
212 New in 1.4.0:
213
214 API Changes
215
216 * Types
217 - New nfc_device_option value (enum): NDO_FORCE_ISO14443_A to force the
218 chip to switch in ISO14443-A
219 - New nfc_dep_mode_t (enum) for DEP mode:
220 NDM_UNDEFINED, NDM_PASSIVE, NDM_ACTIVE
221 - New nfc_modulation_type_t (enum) that lists modulation types:
222 NMT_ISO14443A, NMT_ISO14443B, NMT_FELICA, NMT_JEWEL, NMT_DEP
223 - New nfc_baud_rate_t (enum): list of baud rates:
224 NBR_UNDEFINED, NBR_106, NBR_212, NBR_424, NBR_847
225 - nfc_target_type_t have been removed from API (use nfc_modulation_t
226 instead)
227
228 * Structures
229 - nfc_device_t now have a boolean bAutoIso14443_4 to keep the locally the
230 state of NDO_AUTO_ISO14443_4 (should not be directly set, use
231 nfc_configure() with NDO_AUTO_ISO14443_4)
232 - nfc_device_t now have an uint8_t ui8Parameters to cache PN53x parameters
233 - nfc_device_t now have a byte_t btSupportByte to cache supported
234 modulations
235 - nfc_dep_info_t have completely changed, please see API documentation
236 - nfc_iso14443b_info_t have completely changed, please see API
237 documentation
238 - nfc_modulation_t have completely changed: it now contains a
239 nfc_modulation_type_t and nfc_baud_rate_t couple. Initialization example:
240 nfc_modulation_t nm = {
241 .nmt = NMT_ISO14443A,
242 .nbr = NBR_106,
243 };
244 - nfc_target_t now contains new nfc_modulation_t instead of
245 nfc_target_type_t. Initialization example:
246 nfc_target_t nt = {
247 .nm.nmt = NMT_ISO14443A,
248 .nm.nbr = NBR_UNDEFINED,
249 .nti.nai.abtAtqa = { 0x03, 0x44 },
250 .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
251 .nti.nai.btSak = 0x20,
252 .nti.nai.szUidLen = 4,
253 .nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
254 .nti.nai.szAtsLen = 5,
255 };
256
257 * Functions
258 - nfc_initiator_select_passive_target() now use new nfc_modulation_t and
259 nfc_target_t instead of nfc_target_info_t
260 - nfc_initiator_list_passive_targets() now use new nfc_modulation_t and
261 nfc_target_t instead of nfc_target_info_t
262 - nfc_initiator_poll_targets() use new nfc_modulation_t instead of
263 nfc_target_type_t
264 - nfc_initiator_select_dep_target() completely changed, use now
265 nfc_dep_mode_t, nfc_baudrate_t, nfc_dep_info_t and nfc_target_t, please
266 see API documentation
267 - nfc_target_init() have an additional argument: nfc_target_t to describe
268 the wanted target
269 - append_iso14443a_crc() was renamed to iso14443a_crc_append()
270 - New iso14443a_locate_historical_bytes() to locate historical bytes in ATS
271
272
273
274 New in 1.3.9 (since 1.3.4):
275
276 Installed files
277
278 - mifaretag.h and mifareultag.h are removed, Mifare features are not a part
279 of libnfc API anymore (these features are always available in examples/)
280
281 API Changes
282
283 * Types
284 - New nfc_device_option_t value (enum): NDO_AUTO_14443_4, an option to
285 enable/disable auto-switching to ISO/IEC 14443-4 if device is compliliant
286 - New nfc_device_option_t value (enum): NDO_EASY_FRAMING, an option to
287 enable/disable automatic frames encapsulation and chaining
288 - New nfc_target_type_t (enum), with values like NTT_MIFARE,
289 NTT_ISO14443B_106, NTT_DEP_ACTIVE_424, etc.
290 - Mifare related types have been removed from API: mifare_cmd,
291 mifare_param_auth, mifare_param_data, mifare_param_value, mifare_param
292
293 * Structures
294 - nfc_device_t now have boolean bEasyFraming to enable/disable "easy
295 framing" feature (should not be directly set, use nfc_configure() with
296 NDO_EASY_FRAMING)
297 - nfc_device_t now have integer iLastError to handle last error
298 - New chip_callbacks to handle error lookup per chip
299 - driver_callbacks now have a pointer to chip_callbacks
300 - New nfc_target_t that contains nfc_target_info_t and nfc_target_type_t
301
302 * Functions
303 - nfc_initiator_select_tag() became nfc_initiator_select_passive_target()
304 - New nfc_initiator_list_passive_targets() returns a list of detected
305 target on desired modulation
306 - (experimental) New nfc_initiator_poll_targets() returns targets that are
307 detected during hardware polling (available only with PN532)
308 - nfc_initiator_transceive_dep_bytes(), nfc_target_receive_dep_bytes() and
309 nfc_target_send_dep_bytes() have been removed from API, use
310 NDO_EASY_FRAMING option to switch from raw mode to "easy framing"
311 - nfc_initiator_mifare_cmd() have been removed: no more Mifare related
312 stuff in libnfc's API
313 - New nfc_strerror(), nfc_strerror_r() and nfc_perror() to report errors
314 - New append_iso14443a_crc() to append iso14443a_crc() to a string
315
316
317 New in 1.3.4 (since 1.2.1):
318
319 Installed files
320
321 - Headers are now installed in include/nfc instead of include/libnfc
322 - libnfc.h have been renamed to nfc.h
323 - defines.h and types.h have been merge into nfc-types.h
324 - bitutils.h is not installed anymore, some functions are now in
325 examples/nfc-utils.c
326 - devices.h, dev_acr122.h, dev_arygon.h, dev_pn531.h, dev_pn533.h and rs232.h
327 are not installed anymore
328 - New header mifareultag.h, like mifaretag.h for Mifare UltraLight
329 - New header nfc-messages.h with messages macros (DBG, ERR, INFO)
330
331 API Changes
332
333 * Types
334 - uint32_t which was used as size now are size_t
335 - chip_type became nfc_chip_t (enum)
336 - init_modulation became nfc_modulation_t (enum), and now have
337 NM_ACTIVE_DEP and NM_PASSIVE_DEP modulation values added
338
339 * Structures
340 - dev_info became nfc_device_t
341 - dev_config_option became nfc_device_option_t
342 - New nfc_device_desc_t to describe the way to access to a NFC device.
343 Initialisation example:
344 nfc_device_desc_t ndd = {
345 ndd.pcDriver = "ARYGON";
346 ndd.pcPort = "/dev/ttyUSB0";
347 ndd.uiSpeed = 115200;
348 };
349 - dev_callbacks became driver_callbacks and now have two function pointers
350 more: pick_device() and list_devices()
351 - New nfc_dep_info_t to handle DEP targets info
352 - tag_info_iso14443a became nfc_iso14443a_info_t
353 - tag_info_iso14443b became nfc_iso14443b_info_t
354 - tag_info_felica became nfc_felica_info_t
355 - tag_info_jewel became nfc_jewel_info_t
356 - tag_info became nfc_target_info_t, and now have extended union to
357 nfc_dep_info_t
358
359 * Functions
360 - nfc_connect() now takes 1 nfc_devive_desc_t argument (can be NULL)
361 - New nfc_list_devices(), it find available NFC devices using all know
362 drivers
363 - (experimental) New nfc_initiator_select_dep(), it looks for DEP targets
364 - (experimental) New nfc_initiator_transceive_dep_bytes(), like
365 nfc_initiator_transceive_bytes() for DEP targets
366 - (experimental) New nfc_target_receive_dep_bytes() and
367 nfc_target_send_dep_bytes(), to receive/send bytes to DEP target
368 (configured as initiator) while local NFC device is configured as target
369 - New nfc_device_name() returns the device's name
370 - New iso14443a_crc() computes CRC as described in ISO/IEC 14443
371 - New nfc_version() returns the actual version of libnfc (with SVN
372 revision, if available)
0 New in 1.8.0:
1
2 API Changes:
3 - Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
4 - Bump library version to 6.0.0
5
6 New in 1.7.2:
7
8 Drivers:
9
10 * New driver for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested)
11 * New driver for contactless PC/SC readers (only as initiator)
12
13 API Changes:
14
15 * nfc_device_get_supported_baud_rate() now takes also "mode" as argument
16 * New nfc_device_get_supported_baud_rate_target_mode()
17 * New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol
18 * New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass)
19 * pn53x_transceive() is now part of public API
20
21 New in 1.7.1:
22
23 API Changes:
24
25 * nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL
26 * nfc_initiator_target_is_present() allow NULL pointer to tag
27
28 New in 1.7.0:
29
30 Drivers:
31
32 * New PN532 over I2C driver, see contrib/libnfc/pn532_i2c_on_rpi.conf.sample
33
34 API Changes:
35
36 * New function iso14443b_crc_append()
37
38 New in 1.7.0-rc7:
39
40 Drivers:
41
42 * New PN532 over SPI driver, see contrib/libnfc/pn532_spi_on_rpi.conf.sample
43
44 API Changes:
45
46 * Functions
47 - nfc_initiator_target_is_present() & str_nfc_target():
48 now take a pointer to nfc_target as argument
49 - nfc_init(): upon malloc error, doesn't force exit() anymore
50 so now you should test if context != NULL after nfc_init() call
51
52 New in 1.7.0-rc5:
53
54 API Changes:
55
56 * Functions
57 - New nfc_register_driver() function allowing to hook custom drivers.
58
59 New in 1.7.0-rc3:
60
61 API Changes:
62
63 * Functions
64 - Add timeout param to nfc_emulate_target()
65
66 New in 1.7.0-rc2:
67
68 Configuration:
69 libnfc can now use a configuration file for special setups, or features
70 activation. This file (/etc/nfc/libnfc.conf under GNU/Linux systems)
71 supports already some keywords:
72 - "allow_autoscan" to enable/disable device auto-detection feature;
73 - "allow_intrusive_scan" to enable/disable intrusive auto-detection
74 (ie. serial port probing);
75 - "log_level" to select library verbosity;
76 - "device.name" and "device.connstring" to define a user device,
77 this is the recommended method if user has a not easily detectable
78 device (ie. a serial one).
79 It is also possible to define devices using dedicated configuration files and
80 put them into device search directory (/etc/nfc/devices.d under GNU/Linux).
81 Example for the OpenPCD2: create /etc/nfc/devices.d/openpcd2.conf with:
82 name = "OpenPCD2"
83 connstring = "pn532_uart:/dev/ttyACM0"
84 optional = true
85 The keyword "optional" does not mandate the device to be present always
86 (it detects if the reader is indeed present before using it)
87
88 API Changes:
89
90 * Types
91 - New NFC_ESOFT error to handle software errors (allocations, pipe
92 creation, etc.)
93
94 * Functions
95 - Remove nfc_get_default_device() function: the default device is now the
96 first in nfc_list_devices() or could be open using NULL connstring with
97 nfc_open() function.
98 - New enum-to-string converter functions str_nfc_modulation_type() and
99 str_nfc_baud_rate()
100 - New str_nfc_target() to convert nfc_target struct into allocated string
101 - New nfc_device_get_information_about() function to retreive some device's
102 information
103 - No more in/out function parameter: nfc_initiator_transceive_*() now
104 take a constant size for Rx buffer
105 - New nfc_initiator_target_is_present() to test is the previously selected
106 target is available in the field
107 - nfc_initiator_transceive_bytes() returns NFC_EMFCAUTHFAIL when AUTH
108 command failed on a Mifare Classic
109 - New nfc_initiator_init_secure_element() to initiate a connection with
110 secure element (Only supported with a PN532 with SAM equipped)
111
112 New in 1.6.0-rc1:
113
114 API Changes:
115
116 * Types
117 - '_t' suffix removed from all types (e.g. nfc_device_t is now nfc_device)
118 - All errors removed in flavour of NFC_EIO, NFC_EINVARG, NFC_EDEVNOTSUPP,
119 NFC_ENOTSUCHDEV, NFC_EOVFLOW, NFC_ETIMEOUT, NFC_EOPABORTED, NFC_ENOTIMPL,
120 NFC_ETGRELEASED, NFC_ERFTRANS, NFC_ECHIP and NFC_SUCCESS
121 - nfc_device_desc_t replaced by nfc_connstring: libnfc now uses connection
122 strings to describe a device
123 - byte_t typedef removed, libnfc now uses uint8_t from C99
124 - nfc_device is now an opaque type
125 - nfc_properties replaces nfc_options
126
127 * Functions
128 - New nfc_get_default_device() function that allows to grab the connstring
129 stored in LIBNFC_DEFAULT_DEVICE environnement variable or returns the
130 first available device if not set
131 - New nfc_device_get_connstring() accessor function to know the device
132 connstring
133 - New nfc_device_set_property_bool() function that replace nfc_configure()
134 - New nfc_device_set_property_int() function to set integer property
135 - nfc_device_name() renamed to nfc_device_get_name() for the sake of
136 consistency
137 - New nfc_device_get_last_error() function, an accessor to last error occured
138 - Whole libnfc's functions now return 0 (NFC_SUCCESS) or positive value if
139 appropriated on success and libnfc's error code on failure
140 - nfc_connect(), nfc_disconnect() renamed to nfc_open(), nfc_close()
141 respectively
142 - Add 2 new functions: initialization and deinitialization functions:
143 nfc_init() and nfc_exit()
144 - New nfc_device_get_supported_modulation() and
145 nfc_device_get_supported_baud_rate() functions
146
147 * Dependencies
148 - log4c is not anymore used for debugging facility. It was a bad choice,
149 sorry for inconvenience.
150
151 New in 1.5.1:
152
153 API Changes
154
155 * Types
156 - Communication-level errors DEIO and DETIMEOUT are now know as ECOMIO,
157 ECOMTIMEOUT respectively
158 - Common device-level errors DEINVAL and DEABORT are now know as EINVALARG,
159 EOPABORT respectively
160 - New errors: EFRAACKMISMATCH, EFRAISERRFRAME, EDEVNOTSUP and ENOTIMPL
161
162 * Functions
163 - nfc_abort_command() returns a boolean
164 - timeout (struct timeval) pointer added to
165 nfc_initiator_transceive_bytes(), nfc_target_send_bytes() and
166 nfc_target_receive_bytes()
167 - timed functions nfc_initiator_transceive_bytes_timed() and
168 nfc_initiator_transceive_bits_timed() now takes uint32_t as cycles
169 pointer
170 - nfc_initiator_poll_targets() renamed to nfc_initiator_poll_target() and
171 only return one target
172
173 New in 1.5.0:
174
175 Installed files
176 - nfc-message.h have been removed, internal macros are not part of API.
177 - New nfc-emulation.h file offers a middle level API to handle emulation (see
178 nfc-emulate-forum-tag4 example)
179
180 API Changes
181
182 * Types
183 - New error: DEABORT raised when operation is aborted by user (using
184 nfc_abort_command())
185 - nfc_chip_t type removed from public API (have been renamed to pn53x_type
186 in chips/pn53x)
187 - nfc_device_spec_t removed, each driver can use his own way to keep a
188 connection pointer
189
190 * Structures
191 - nfc_device_t now have a nfc_driver_t struct pointer (named .driver) and
192 void pointer (.driver_data) to handle device specific wrapping
193 - nfc_device_t now have a void pointer (.chip_data) to keep some chip
194 specific data
195 - nfc_device_t now have an file descriptor array to manage to abort request
196 - nfc_device_t does have .nc member (nfc_chip_t) anymore (different chips
197 handling in now in chip level)
198 - nfc_device_t does have .nds member (nfc_device_spec_t) anymore, each
199 driver handle its communication using driver_data pointer
200 - nfc_device_t does have .bActive member (bool) anymore, this variable was
201 almost not used and was not efficient
202 - nfc_device_t does have chip's register caches anymore, this is handle in
203 chip level (using chip_data pointer)
204 - driver_callbacks structure have been removed from public API
205 - New nfc_emulator structure used by the new emulation API (see
206 nfc_emulate_target())
207 - New nfc_emulation_state_machine structure used by the new emulation API,
208 it handles an I/O function and data pointer to create a software based
209 state-machine.
210
211 * Functions
212 - New nfc_abort_command() function to abort current running command.
213 - New nfc_initiator_transceive_bits_timed() and
214 nfc_initiator_transceive_bytes_timed() to transceive bits/bytes and
215 measure the time to have a reply
216 - New nfc_emulate_target() function to start a target emulation using an
217 nfc_emulator structure (it contains a custom state-machine
218 (nfc_emulation_state_machine struct) and a custom target (nfc_target_t)
219 (see nfc-emulate-forum-tag4 to have a look on how-to use it)
220
221
222
223 New in 1.4.1:
224
225 API Changes
226
227 * Types
228 - New error: ETGUIDNOTSUP raised when UID is not 4 bytes long or does not
229 start with 0x08 (Security restriction present in the NXP PN53x chips)
230
231
232
233 New in 1.4.0:
234
235 API Changes
236
237 * Types
238 - New nfc_device_option value (enum): NDO_FORCE_ISO14443_A to force the
239 chip to switch in ISO14443-A
240 - New nfc_dep_mode_t (enum) for DEP mode:
241 NDM_UNDEFINED, NDM_PASSIVE, NDM_ACTIVE
242 - New nfc_modulation_type_t (enum) that lists modulation types:
243 NMT_ISO14443A, NMT_ISO14443B, NMT_FELICA, NMT_JEWEL, NMT_DEP
244 - New nfc_baud_rate_t (enum): list of baud rates:
245 NBR_UNDEFINED, NBR_106, NBR_212, NBR_424, NBR_847
246 - nfc_target_type_t have been removed from API (use nfc_modulation_t
247 instead)
248
249 * Structures
250 - nfc_device_t now have a boolean bAutoIso14443_4 to keep the locally the
251 state of NDO_AUTO_ISO14443_4 (should not be directly set, use
252 nfc_configure() with NDO_AUTO_ISO14443_4)
253 - nfc_device_t now have an uint8_t ui8Parameters to cache PN53x parameters
254 - nfc_device_t now have a byte_t btSupportByte to cache supported
255 modulations
256 - nfc_dep_info_t have completely changed, please see API documentation
257 - nfc_iso14443b_info_t have completely changed, please see API
258 documentation
259 - nfc_modulation_t have completely changed: it now contains a
260 nfc_modulation_type_t and nfc_baud_rate_t couple. Initialization example:
261 nfc_modulation_t nm = {
262 .nmt = NMT_ISO14443A,
263 .nbr = NBR_106,
264 };
265 - nfc_target_t now contains new nfc_modulation_t instead of
266 nfc_target_type_t. Initialization example:
267 nfc_target_t nt = {
268 .nm.nmt = NMT_ISO14443A,
269 .nm.nbr = NBR_UNDEFINED,
270 .nti.nai.abtAtqa = { 0x03, 0x44 },
271 .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
272 .nti.nai.btSak = 0x20,
273 .nti.nai.szUidLen = 4,
274 .nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
275 .nti.nai.szAtsLen = 5,
276 };
277
278 * Functions
279 - nfc_initiator_select_passive_target() now use new nfc_modulation_t and
280 nfc_target_t instead of nfc_target_info_t
281 - nfc_initiator_list_passive_targets() now use new nfc_modulation_t and
282 nfc_target_t instead of nfc_target_info_t
283 - nfc_initiator_poll_targets() use new nfc_modulation_t instead of
284 nfc_target_type_t
285 - nfc_initiator_select_dep_target() completely changed, use now
286 nfc_dep_mode_t, nfc_baudrate_t, nfc_dep_info_t and nfc_target_t, please
287 see API documentation
288 - nfc_target_init() have an additional argument: nfc_target_t to describe
289 the wanted target
290 - append_iso14443a_crc() was renamed to iso14443a_crc_append()
291 - New iso14443a_locate_historical_bytes() to locate historical bytes in ATS
292
293
294
295 New in 1.3.9 (since 1.3.4):
296
297 Installed files
298
299 - mifaretag.h and mifareultag.h are removed, Mifare features are not a part
300 of libnfc API anymore (these features are always available in examples/)
301
302 API Changes
303
304 * Types
305 - New nfc_device_option_t value (enum): NDO_AUTO_14443_4, an option to
306 enable/disable auto-switching to ISO/IEC 14443-4 if device is compliliant
307 - New nfc_device_option_t value (enum): NDO_EASY_FRAMING, an option to
308 enable/disable automatic frames encapsulation and chaining
309 - New nfc_target_type_t (enum), with values like NTT_MIFARE,
310 NTT_ISO14443B_106, NTT_DEP_ACTIVE_424, etc.
311 - Mifare related types have been removed from API: mifare_cmd,
312 mifare_param_auth, mifare_param_data, mifare_param_value, mifare_param
313
314 * Structures
315 - nfc_device_t now have boolean bEasyFraming to enable/disable "easy
316 framing" feature (should not be directly set, use nfc_configure() with
317 NDO_EASY_FRAMING)
318 - nfc_device_t now have integer iLastError to handle last error
319 - New chip_callbacks to handle error lookup per chip
320 - driver_callbacks now have a pointer to chip_callbacks
321 - New nfc_target_t that contains nfc_target_info_t and nfc_target_type_t
322
323 * Functions
324 - nfc_initiator_select_tag() became nfc_initiator_select_passive_target()
325 - New nfc_initiator_list_passive_targets() returns a list of detected
326 target on desired modulation
327 - (experimental) New nfc_initiator_poll_targets() returns targets that are
328 detected during hardware polling (available only with PN532)
329 - nfc_initiator_transceive_dep_bytes(), nfc_target_receive_dep_bytes() and
330 nfc_target_send_dep_bytes() have been removed from API, use
331 NDO_EASY_FRAMING option to switch from raw mode to "easy framing"
332 - nfc_initiator_mifare_cmd() have been removed: no more Mifare related
333 stuff in libnfc's API
334 - New nfc_strerror(), nfc_strerror_r() and nfc_perror() to report errors
335 - New append_iso14443a_crc() to append iso14443a_crc() to a string
336
337
338 New in 1.3.4 (since 1.2.1):
339
340 Installed files
341
342 - Headers are now installed in include/nfc instead of include/libnfc
343 - libnfc.h have been renamed to nfc.h
344 - defines.h and types.h have been merge into nfc-types.h
345 - bitutils.h is not installed anymore, some functions are now in
346 examples/nfc-utils.c
347 - devices.h, dev_acr122.h, dev_arygon.h, dev_pn531.h, dev_pn533.h and rs232.h
348 are not installed anymore
349 - New header mifareultag.h, like mifaretag.h for Mifare UltraLight
350 - New header nfc-messages.h with messages macros (DBG, ERR, INFO)
351
352 API Changes
353
354 * Types
355 - uint32_t which was used as size now are size_t
356 - chip_type became nfc_chip_t (enum)
357 - init_modulation became nfc_modulation_t (enum), and now have
358 NM_ACTIVE_DEP and NM_PASSIVE_DEP modulation values added
359
360 * Structures
361 - dev_info became nfc_device_t
362 - dev_config_option became nfc_device_option_t
363 - New nfc_device_desc_t to describe the way to access to a NFC device.
364 Initialisation example:
365 nfc_device_desc_t ndd = {
366 ndd.pcDriver = "ARYGON";
367 ndd.pcPort = "/dev/ttyUSB0";
368 ndd.uiSpeed = 115200;
369 };
370 - dev_callbacks became driver_callbacks and now have two function pointers
371 more: pick_device() and list_devices()
372 - New nfc_dep_info_t to handle DEP targets info
373 - tag_info_iso14443a became nfc_iso14443a_info_t
374 - tag_info_iso14443b became nfc_iso14443b_info_t
375 - tag_info_felica became nfc_felica_info_t
376 - tag_info_jewel became nfc_jewel_info_t
377 - tag_info became nfc_target_info_t, and now have extended union to
378 nfc_dep_info_t
379
380 * Functions
381 - nfc_connect() now takes 1 nfc_devive_desc_t argument (can be NULL)
382 - New nfc_list_devices(), it find available NFC devices using all know
383 drivers
384 - (experimental) New nfc_initiator_select_dep(), it looks for DEP targets
385 - (experimental) New nfc_initiator_transceive_dep_bytes(), like
386 nfc_initiator_transceive_bytes() for DEP targets
387 - (experimental) New nfc_target_receive_dep_bytes() and
388 nfc_target_send_dep_bytes(), to receive/send bytes to DEP target
389 (configured as initiator) while local NFC device is configured as target
390 - New nfc_device_name() returns the device's name
391 - New iso14443a_crc() computes CRC as described in ISO/IEC 14443
392 - New nfc_version() returns the actual version of libnfc (with SVN
393 revision, if available)
+0
-166
README less more
0 *-
1 * Free/Libre Near Field Communication (NFC) library
2 *
3 * Libnfc historical contributors:
4 * Copyright (C) 2009 Roel Verdult
5 * Copyright (C) 2009-2013 Romuald Conty
6 * Copyright (C) 2010-2012 Romain Tartière
7 * Copyright (C) 2010-2013 Philippe Teuwen
8 * Copyright (C) 2012-2013 Ludovic Rousseau
9 * Additional contributors:
10 * See AUTHORS file
11 -*
12
13 General Information
14 ===================
15
16 libnfc is a library which allows userspace application access to NFC devices.
17
18 The official web site is:
19 http://www.nfc-tools.org/
20
21 The official forum site is:
22 http://www.libnfc.org/community/
23
24 The official development site is:
25 http://libnfc.googlecode.com/
26
27 Important note: this file covers POSIX systems, for Windows please read README-Windows.txt
28
29 Requirements
30 ============
31
32 Some NFC drivers depend on third party software:
33
34 * pn53x_usb & acr122_usb:
35
36 - libusb-0.1 http://libusb.sf.net
37
38 * acr122_pcsc:
39
40 - pcsc-lite http://pcsclite.alioth.debian.org/
41
42 The regression test suite depends on the cutter framework:
43 http://cutter.sf.net
44
45 Installation
46 ============
47
48 See the file 'INSTALL' for configure, build and install details.
49
50 Additionnally, you may need to grant permissions to your user to drive your device.
51 Under GNU/Linux systems, if you use udev, you could use the provided udev rules.
52 e.g. under Debian, Ubuntu, etc.
53 sudo cp contrib/udev/42-pn53x.rules /lib/udev/rules.d/
54
55 Under FreeBSD, if you use devd, there is also a rules file: contrib/devd/pn53x.conf.
56
57 How to report bugs
58 ==================
59
60 To report a bug, visit http://code.google.com/p/libnfc/issues/list and fill
61 out a bug report form.
62
63 If you have questions, remarks, we encourage you to post this in the developers
64 community:
65 http://www.libnfc.org/community
66
67 Please make sure to include:
68
69 * The version of libnfc
70
71 * Information about your system. For instance:
72
73 - What operating system and version
74 - For Linux, what version of the C library
75
76 And anything else you think is relevant.
77
78 * A trace with debug activated.
79
80 Reproduce the bug with debug, e.g. if it was:
81 $ nfc-list -v
82 run it as:
83 $ LIBNFC_LOG_LEVEL=3 nfc-list -v
84
85 * How to reproduce the bug.
86
87 Please include a short test program that exhibits the behavior.
88 As a last resort, you can also provide a pointer to a larger piece
89 of software that can be downloaded.
90
91 * If the bug was a crash, the exact text that was printed out
92 when the crash occured.
93
94 * Further information such as stack traces may be useful, but
95 is not necessary.
96
97 Patches
98 =======
99
100 Patches can be posted to http://code.google.com/p/libnfc/issues/list or
101 can be sent directly to libnfc's developers:
102 http://nfc-tools.org/index.php?title=Contact
103
104 If the patch fixes a bug, it is usually a good idea to include
105 all the information described in "How to Report Bugs".
106
107 Building
108 ========
109
110 It should be as simple as running these two commands:
111
112 ./configure
113 make
114
115 Troubleshooting
116 ===============
117
118 Touchatag/ACR122:
119 -----------------
120 If your Touchatag or ACR122 device fails being detected by libnfc, make sure
121 that PCSC-lite daemon (pcscd) is installed and is running.
122
123 If your Touchatag or ACR122 device fails being detected by PCSC-lite daemon
124 (pcsc_scan doesn't see anything) then try removing the bogus firmware detection
125 of libccid: edit libccid_Info.plist configuration file (usually
126 /etc/libccid_Info.plist) and locate "<key>ifdDriverOptions</key>", turn
127 "<string>0x0000</string>" value into 0x0004 to allow bogus devices and restart
128 pcscd daemon.
129
130 ACR122:
131 -------
132 Using an ACR122 device with libnfc and without tag (e.g. to use NFCIP modes or
133 card emulation) needs yet another PCSC-lite tweak: You need to allow usage of
134 CCID Exchange command. To do this, edit libccid_Info.plist configuration file
135 (usually /etc/libccid_Info.plist) and locate "<key>ifdDriverOptions</key>",
136 turn "<string>0x0000</string>" value into 0x0001 to allow CCID exchange or
137 0x0005 to allow CCID exchange and bogus devices (cf previous remark) and
138 restart pcscd daemon.
139
140 Warning: if you use ACS CCID drivers (acsccid), configuration file is located
141 in something like: /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist
142
143 SCL3711:
144 --------
145 Libnfc cannot be used concurrently with the PCSC proprietary driver of SCL3711.
146 Two possible solutions:
147 * Either you don't install SCL3711 driver at all
148 * Or you stop the PCSC daemon when you want to use libnfc-based tools
149
150 PN533 USB device on Linux >= 3.1:
151 ---------------------------------
152 Since Linux kernel version 3.1, two kernel-modules must not be loaded in order
153 to use libnfc : "nfc" and "pn533".
154 To prevent kernel from loading automatically these modules, you can blacklist
155 them in a modprobe conf file. This file is provided within libnfc archive:
156 sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf
157
158 Proprietary Notes
159 =================
160
161 FeliCa is s registered trademark of the Sony Corporation.
162 MIFARE is a trademark of NXP Semiconductors.
163 Jewel Topaz is a trademark of Innovision Research & Technology.
164 All other trademarks are the property of their respective owners.
165
0 *-
1 * Free/Libre Near Field Communication (NFC) library
2 *
3 * Libnfc historical contributors:
4 * Copyright (C) 2009 Roel Verdult
5 * Copyright (C) 2009-2013 Romuald Conty
6 * Copyright (C) 2010-2012 Romain Tartière
7 * Copyright (C) 2010-2013 Philippe Teuwen
8 * Copyright (C) 2012-2013 Ludovic Rousseau
9 * Additional contributors of Windows-specific parts:
10 * Copyright (C) 2010 Glenn Ergeerts
11 * Copyright (C) 2013 Alex Lian
12 -*
13
14 Requirements
15 ============
16
17 - MinGW-w64 compiler toolchain [1]
18 - LibUsb-Win32 1.2.5.0 (or greater) [2]
19 - CMake 2.8 [3]
20
21 This was tested on Windows 7 64 bit, but should work on Windows Vista and
22 Windows XP and 32 bit as well.
23 Only the ACS ACR122 and the ASK Logo readers are tested at the moment, so any feedback about other devices is very welcome.
24
25 Community forum: http://www.libnfc.org/community/
26
27 Building
28 ========
29
30 To build the distribution the MinGW Makefiles generator of CMake was used. Here
31 is an example of how to generate a distribution with the above mentioned
32 requirements fulfilled (it is assumed the CMake binaries are in the system
33 path, this is optional during installation of CMake):
34
35 - Add the following directories to your PATH:
36
37 c:\MinGW64\bin;c:\MinGW64\x86_64-w64-mingw32\lib32;c:\MinGW64\x86_64-w64-mingw32\include
38
39 - Now it is possible to run CMake and mingw32-make:
40
41 C:\dev\libnfc-read-only> mkdir ..\libnfc-build
42 C:\dev\libnfc-read-only> cd ..\libnfc-build
43 C:\dev\libnfc-build> cmake-gui .
44
45 Now you can configure the build. Press "Configure", specify "MinGW32 Makefiles"
46 and then you have the opportunity to set some configuration variables. If you
47 don't want a Debug build change the variable CMAKE_BUILD_TYPE to "Release".
48
49 If a non-GUI solution is preferred one can use:
50
51 C:\dev\libnfc-build> cmake -G "MinGW Makefiles"
52 -DCMAKE_BUILD_TYPE=Release ..\libnfc-read-only
53
54 Now run mingw32-make to build:
55
56 C:\dev\libnfc-read-only\bin> mingw32-make
57
58 The build will create a shared library for Windows (nfc.dll) to link your applications against. It will compile
59 the tools against this shared library.
60
61 References
62 ==========
63 [1] the easiest way is to use the TDM-GCC installer.
64 Make sure to select MinGW-w64 in the installer, the regular MinGW does not contain headers for PCSC.
65 http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download
66
67 [2] http://sourceforge.net/projects/libusb-win32/files/
68
69 [3] http://www.cmake.org
+0
-68
README-Windows.txt less more
0 *-
1 * Free/Libre Near Field Communication (NFC) library
2 *
3 * Libnfc historical contributors:
4 * Copyright (C) 2009 Roel Verdult
5 * Copyright (C) 2009-2013 Romuald Conty
6 * Copyright (C) 2010-2012 Romain Tartière
7 * Copyright (C) 2010-2013 Philippe Teuwen
8 * Copyright (C) 2012-2013 Ludovic Rousseau
9 * Additional contributors of Windows-specific parts:
10 * Copyright (C) 2010 Glenn Ergeerts
11 * Copyright (C) 2013 Alex Lian
12 -*
13
14 Requirements
15 ============
16
17 - MinGW-w64 compiler toolchain [1]
18 - LibUsb-Win32 1.2.5.0 (or greater) [2]
19 - CMake 2.8 [3]
20 - PCRE for Windows [4]
21
22 This was tested on Windows 7 64 bit, but should work on Windows Vista and
23 Windows XP and 32 bit as well.
24 Only the ACS ACR122 and the ASK Logo readers are tested at the moment, so any feedback about other devices is very welcome.
25
26 Community forum: http://www.libnfc.org/community/
27
28 Building
29 ========
30
31 To build the distribution the MinGW Makefiles generator of CMake was used. Here
32 is an example of how to generate a distribution with the above mentioned
33 requirements fulfilled (it is assumed the CMake binaries are in the system
34 path, this is optional during installation of CMake):
35
36 - Add the following directories to your PATH : c:\MinGW64\bin;c:\MinGW64\x86_64-w64-mingw32\lib32;c:\MinGW64\x86_64-w64-mingw32\include
37
38 - Now it is possible to run CMake and mingw32-make:
39
40 C:\dev\libnfc-read-only> mkdir ..\libnfc-build
41 C:\dev\libnfc-read-only> cd ..\libnfc-build
42 C:\dev\libnfc-build> cmake-gui .
43
44 Now you can configure the build. Press "Configure", specify "MinGW32 Makefiles"
45 and then you have the opportunity to set some configuration variables. If you
46 don't want a Debug build change the variable CMAKE_BUILD_TYPE to "Release".
47
48 If a non-GUI solution is preferred one can use:
49
50 C:\dev\libnfc-build> cmake -G "MinGW Makefiles"
51 -DCMAKE_BUILD_TYPE=Release ..\libnfc-read-only
52
53 Now run mingw32-make to build:
54
55 C:\dev\libnfc-read-only\bin> mingw32-make
56
57 The build will create a shared library for Windows (nfc.dll) to link your applications against. It will compile
58 the tools against this shared library.
59
60 References
61 ==========
62 [1] the easiest way is to use the TDM-GCC installer.
63 Make sure to select MinGW-w64 in the installer, the regular MinGW does not contain headers for PCSC.
64 http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download
65 [2] http://sourceforge.net/projects/libusb-win32/files/
66 [3] http://www.cmake.org
67 [4] http://gnuwin32.sourceforge.net/packages/pcre.htm
0 ```
1 *-
2 * Free/Libre Near Field Communication (NFC) library
3 *
4 * Libnfc historical contributors:
5 * Copyright (C) 2009 Roel Verdult
6 * Copyright (C) 2009-2015 Romuald Conty
7 * Copyright (C) 2010-2012 Romain Tartière
8 * Copyright (C) 2010-2013 Philippe Teuwen
9 * Copyright (C) 2012-2013 Ludovic Rousseau
10 * Additional contributors:
11 * See AUTHORS file
12 -*
13 ```
14
15 General Information
16 ===================
17
18 libnfc is a library which allows userspace application access to NFC devices.
19
20 The official web site is:
21 http://www.nfc-tools.org/
22
23 The official forum site is:
24 http://www.libnfc.org/community/
25
26 The official development site is:
27 https://github.com/nfc-tools/libnfc
28
29 Important note: this file covers POSIX systems, for Windows please read README-Windows.md
30
31 Requirements
32 ============
33
34 Some NFC drivers depend on third party software:
35
36 * pn53x_usb & acr122_usb:
37
38 - libusb-0.1 http://libusb.sf.net
39
40 * acr122_pcsc:
41
42 - pcsc-lite http://pcsclite.alioth.debian.org/
43 - pcsc:
44
45 - Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test.
46
47 The regression test suite depends on the cutter framework:
48 http://cutter.sf.net
49
50 Installation
51 ============
52
53 See the file `INSTALL` for configure, build and install details.
54
55 Additionnally, you may need to grant permissions to your user to drive your device.
56 Under GNU/Linux systems, if you use udev, you could use the provided udev rules.
57 e.g. under Debian, Ubuntu, etc.
58
59 sudo cp contrib/udev/93-pn53x.rules /lib/udev/rules.d/
60
61 Under FreeBSD, if you use devd, there is also a rules file: contrib/devd/pn53x.conf.
62
63 Configuration
64 =============
65
66 In order to change the default behavior of the library, the libnfc uses a
67 configuration file located in sysconfdir (as provided to ./configure).
68
69 A sample commented file is available in sources: libnfc.conf.sample
70
71 If you have compiled using:
72
73 ./configure --prefix=/usr --sysconfdir=/etc
74
75 you can make configuration directory and copy the sample file:
76
77 sudo mkdir /etc/nfc
78 sudo cp libnfc.conf.sample /etc/nfc/libnfc.conf
79
80 To configure multiple devices, you can either modify libnfc.conf or create a
81 file per device in a nfc/devices.d directory:
82
83 sudo mkdir -p /etc/nfc/devices.d
84 printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf
85 printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf
86
87 How to report bugs
88 ==================
89
90 To report a bug, visit https://github.com/nfc-tools/libnfc/issues and fill
91 out a bug report form.
92
93 If you have questions, remarks, we encourage you to post this in the developers
94 community:
95 http://www.libnfc.org/community
96
97 Please make sure to include:
98
99 * The version of libnfc
100
101 * Information about your system. For instance:
102
103 - What operating system and version
104 - For Linux, what version of the C library
105
106 And anything else you think is relevant.
107
108 * A trace with debug activated.
109
110 Reproduce the bug with debug, e.g. if it was:
111
112 $ nfc-list -v
113
114 run it as:
115
116 $ LIBNFC_LOG_LEVEL=3 nfc-list -v
117
118 * How to reproduce the bug.
119
120 Please include a short test program that exhibits the behavior.
121
122 As a last resort, you can also provide a pointer to a larger piece
123
124 of software that can be downloaded.
125
126 * If the bug was a crash, the exact text that was printed out
127
128 when the crash occured.
129
130 * Further information such as stack traces may be useful, but
131
132 is not necessary.
133
134 Patches
135 =======
136
137 Patches can be posted to https://github.com/nfc-tools/libnfc/issues
138
139 If the patch fixes a bug, it is usually a good idea to include
140 all the information described in "How to Report Bugs".
141
142 Building
143 ========
144
145 It should be as simple as running these two commands:
146
147 ./configure
148 make
149
150 To build with specific driver(s), see option `--with-drivers=...` detailed in `./configure --help`.
151
152 Note: if you're using directly the development repository and not the release sources, you will have to execute firstly `autoreconf -vis`.
153
154 Troubleshooting
155 ===============
156
157 Touchatag/ACR122:
158 -----------------
159
160 If your Touchatag or ACR122 device fails being detected by libnfc, make sure
161 that PCSC-lite daemon (`pcscd`) is installed and is running.
162
163 If your Touchatag or ACR122 device fails being detected by PCSC-lite daemon
164 (`pcsc_scan` doesn't see anything) then try removing the bogus firmware detection
165 of libccid: edit libccid_Info.plist configuration file (usually
166 `/etc/libccid_Info.plist`) and locate `<key>ifdDriverOptions</key>`, turn
167 `<string>0x0000</string>` value into `0x0004` to allow bogus devices and restart
168 pcscd daemon.
169
170 ACR122:
171 -------
172
173 Using an ACR122 device with libnfc and without tag (e.g. to use NFCIP modes or
174 card emulation) needs yet another PCSC-lite tweak: You need to allow usage of
175 CCID Exchange command. To do this, edit `libccid_Info.plist` configuration file
176 (usually `/etc/libccid_Info.plist`) and locate `<key>ifdDriverOptions</key>`,
177 turn `<string>0x0000</string>` value into `0x0001` to allow CCID exchange or
178 `0x0005` to allow CCID exchange and bogus devices (cf previous remark) and
179 restart pcscd daemon.
180
181 Warning: if you use ACS CCID drivers (acsccid), configuration file is located
182 in something like: `/usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist`
183
184 SCL3711:
185 --------
186
187 Libnfc cannot be used concurrently with the PCSC proprietary driver of SCL3711.
188 Two possible solutions:
189
190 * Either you don't install SCL3711 driver at all
191 * Or you stop the PCSC daemon when you want to use libnfc-based tools
192
193 PN533 USB device on Linux >= 3.1:
194 ---------------------------------
195
196 Since Linux kernel version 3.1, a few kernel-modules must not be loaded in order
197 to use libnfc : "nfc", "pn533" and "pn533_usb".
198 To prevent kernel from loading automatically these modules, you can blacklist
199 them in a modprobe conf file. This file is provided within libnfc archive:
200
201 sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf
202
203 FEITIAN bR500 and R502:
204 -----------------------
205
206 Libnfc can work with PCSC proprietary driver of bR500 and R502, which is already available on most Linux setups.
207 To activate the PCSC support: `./configure --with-drivers=pcsc`.
208 Readers known to work:
209
210 - Feitian bR500
211 - Feitian R502 Dual interface reader
212 - Feitian R502 CL(Contactless) reader
213
214 These readers are support by CCID since v1.4.25, make sure your CCID driver version higher or equal to 1.4.25.
215
216 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)
217
218 ```
219 grep -A 1 CFBundleShortVersionString /usr/local/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
220 ```
221
222 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/)
223
224 ```
225 grep -A 1 CFBundleShortVersionString /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
226 ```
227
228 Proprietary Notes
229 =================
230 FeliCa is a registered trademark of the Sony Corporation.
231 MIFARE is a trademark of NXP Semiconductors.
232 Jewel Topaz is a trademark of Innovision Research & Technology.
233 All other trademarks are the property of their respective owners.
55 # set other_libs to a list of additional libs that cannot be reached by dependency analysis
66 SET(other_libs "")
77
8 SET(dirs "@LIBUSB_LIBRARY_DIR@" "@PCRE_BIN_DIRS@")
8 SET(dirs "@LIBUSB_LIBRARY_DIR@")
99
1010 fixup_bundle("${bundle}" "${other_libs}" "${dirs}")
0 # -*- cmake -*-
1
2
3 # Use the following variables to compile and link against LibNFC:
4 # LIBNFC_FOUND - True if LibNFC was found on your system
5 # LIBNFC_USE_FILE - The file making LibNFC usable
6 # LIBNFC_DEFINITIONS - Definitions needed to build with LibNFC
7 # LIBNFC_INCLUDE_DIR - Directory where nfc/nfc.h can be found
8 # LIBNFC_INCLUDE_DIRS - List of directories of LibNFC and it's dependencies
9 # LIBNFC_LIBRARY - LibNFC library location
10 # LIBNFC_LIBRARIES - List of libraries to link against LibNFC library
11 # LIBNFC_LIBRARY_DIRS - List of directories containing LibNFC' libraries
12 # LIBNFC_ROOT_DIR - The base directory of LibNFC
13 # LIBNFC_VERSION_STRING - A human-readable string containing the version
14 # LIBNFC_VERSION_MAJOR - The major version of LibNFC
15 # LIBNFC_VERSION_MINOR - The minor version of LibNFC
16 # LIBNFC_VERSION_PATCH - The patch version of LibNFC
17
18 set ( LIBNFC_FOUND 1 )
19 set ( LIBNFC_USE_FILE "@LIBNFC_USE_FILE@" )
20
21 set ( LIBNFC_DEFINITIONS "@LIBNFC_DEFINITIONS@" )
22 set ( LIBNFC_INCLUDE_DIR "@LIBNFC_INCLUDE_DIR@" )
23 set ( LIBNFC_INCLUDE_DIRS "@LIBNFC_INCLUDE_DIRS@" )
24 set ( LIBNFC_LIBRARY "@LIBNFC_LIBRARY@" )
25 set ( LIBNFC_LIBRARIES "@LIBNFC_LIBRARIES@" )
26 set ( LIBNFC_LIBRARY_DIRS "@LIBNFC_LIBRARY_DIRS@" )
27 set ( LIBNFC_ROOT_DIR "@LIBNFC_ROOT_DIR@" )
28
29 set ( LIBNFC_VERSION_STRING "@LIBNFC_VERSION_STRING@" )
30 set ( LIBNFC_VERSION_MAJOR "@LIBNFC_VERSION_MAJOR@" )
31 set ( LIBNFC_VERSION_MINOR "@LIBNFC_VERSION_MINOR@" )
32 set ( LIBNFC_VERSION_PATCH "@LIBNFC_VERSION_PATCH@" )
33
0 # This is a basic version file for the Config-mode of find_package().
1 # It is used by write_basic_package_version_file() as input file for configure_file()
2 # to create a version-file which can be installed along a config.cmake file.
3 #
4 # The created file sets PACKAGE_VERSION_EXACT if the current version string and
5 # the requested version string are exactly the same and it sets
6 # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
7 # The variable CVF_VERSION must be set before calling configure_file().
8
9 set(PACKAGE_VERSION "@LIBNFC_VERSION_STRING@")
10
11 if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
12 set(PACKAGE_VERSION_COMPATIBLE FALSE)
13 else()
14 set(PACKAGE_VERSION_COMPATIBLE TRUE)
15 if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
16 set(PACKAGE_VERSION_EXACT TRUE)
17 endif()
18 endif()
19
20 # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
21 if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
22 return()
23 endif()
24
25 # check that the installed version has the same 32/64bit-ness as the one which is currently searching:
26 if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
27 math(EXPR installedBits "8 * 8")
28 set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
29 set(PACKAGE_VERSION_UNSUITABLE TRUE)
30 endif()
22 EXTRA_DIST = \
33 FixBundle.cmake.in \
44 config_posix.h.cmake \
5 config_windows.h.cmake
5 config_windows.h.cmake \
6 LibNFCConfig.cmake.in \
7 LibNFCConfigVersion.cmake.in \
8 UseLibNFC.cmake
0 # -*- cmake -*-
1
2 add_definitions ( ${LIBNFC_DEFINITIONS} )
3 include_directories ( ${LIBNFC_INCLUDE_DIRS} )
4 link_directories ( ${LIBNFC_LIBRARY_DIRS} )
+0
-42
cmake/modules/FindPCRE.cmake less more
0 # This CMake script wants to use pcre functionality needed for windows
1 # compilation. However, since PCRE isn't really a default install location
2 # there isn't much to search.
3 #
4 # Operating Systems Supported:
5 # - Windows (requires MinGW)
6 # Tested with Windows XP/Windows 7
7 #
8 # This should work for both 32 bit and 64 bit systems.
9 #
10 # Author: A. Lian <alex.lian@gmail.com>
11 #
12
13 IF(WIN32)
14 IF(NOT PCRE_FOUND)
15 FIND_PATH(PCRE_INCLUDE_DIRS regex.h)
16 FIND_LIBRARY(PCRE_LIBRARIES NAMES PCRE pcre)
17 FIND_PATH(PCRE_BIN_DIRS pcre3.dll)
18
19 IF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS)
20 SET(PCRE_FOUND TRUE)
21 ENDIF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS)
22 ENDIF(NOT PCRE_FOUND)
23
24 IF(PCRE_FOUND)
25 IF(NOT PCRE_FIND_QUIETLY)
26 MESSAGE(STATUS "Found PCRE: ${PCRE_LIBRARIES} ${PCRE_INCLUDE_DIRS} ${PCRE_BIN_DIRS}")
27 ENDIF (NOT PCRE_FIND_QUIETLY)
28 ELSE(PCRE_FOUND)
29 IF(PCRE_FIND_REQUIRED)
30 MESSAGE(FATAL_ERROR "Could not find PCRE")
31 ENDIF(PCRE_FIND_REQUIRED)
32 ENDIF(PCRE_FOUND)
33
34 INCLUDE(FindPackageHandleStandardArgs)
35 FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG
36 PCRE_LIBRARIES
37 PCRE_INCLUDE_DIRS
38 PCRE_BIN_DIRS
39 )
40
41 ENDIF(WIN32)
0 SET(LIBNFC_DRIVER_PCSC OFF CACHE BOOL "Enable PC/SC reader support (Depends on PC/SC)")
01 SET(LIBNFC_DRIVER_ACR122_PCSC OFF CACHE BOOL "Enable ACR122 support (Depends on PC/SC)")
12 SET(LIBNFC_DRIVER_ACR122_USB ON CACHE BOOL "Enable ACR122 support (Direct USB connection)")
23 SET(LIBNFC_DRIVER_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)")
1011 ENDIF(WIN32)
1112 SET(LIBNFC_DRIVER_PN532_UART ON CACHE BOOL "Enable PN532 UART support (Use serial port)")
1213 SET(LIBNFC_DRIVER_PN53X_USB ON CACHE BOOL "Enable PN531 and PN531 USB support (Depends on libusb)")
14
15 IF(LIBNFC_DRIVER_PCSC)
16 FIND_PACKAGE(PCSC REQUIRED)
17 ADD_DEFINITIONS("-DDRIVER_PCSC_ENABLED")
18 SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pcsc")
19 ENDIF(LIBNFC_DRIVER_PCSC)
1320
1421 IF(LIBNFC_DRIVER_ACR122_PCSC)
1522 FIND_PACKAGE(PCSC REQUIRED)
6067 SET(USB_REQUIRED TRUE)
6168 ENDIF(LIBNFC_DRIVER_PN53X_USB)
6269
63 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/drivers)
70 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers)
11 COPYING-CMAKE-SCRIPTS \
22 FindLIBUSB.cmake \
33 FindPCSC.cmake \
4 FindPCRE.cmake \
54 UseDoxygen.cmake \
65 LibnfcDrivers.cmake
9090
9191 configure_file(${DOXYFILE_IN} Doxyfile ESCAPE_QUOTES IMMEDIATE @ONLY)
9292
93 get_target_property(DOC_TARGET doc TYPE)
94 if(NOT DOC_TARGET)
93 if(NOT TARGET doc)
9594 add_custom_target(doc)
9695 endif()
9796
00 # General init
11
22 # /!\ Don't forget to update 'CMakeLists.txt' too /!\
3 AC_INIT([libnfc],[1.7.1],[nfc-tools@googlegroups.com])
3 AC_INIT([libnfc],[1.8.0],[nfc-tools@googlegroups.com])
44
55 AC_CONFIG_MACRO_DIR([m4])
66
1212 AC_DEFINE_UNQUOTED([GIT_REVISION], ["$GIT_REVISION"], [GIT revision])
1313 fi
1414
15 AM_INIT_AUTOMAKE(subdir-objects dist-bzip2 no-dist-gzip)
15 AM_INIT_AUTOMAKE(subdir-objects dist-bzip2 no-dist-gzip foreign)
1616 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
1717
1818 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
4646 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])
4747 AC_CHECK_HEADERS([linux/spi/spidev.h], [spi_available="yes"])
4848 AC_CHECK_HEADERS([linux/i2c-dev.h], [i2c_available="yes"])
49 AC_CHECK_HEADERS([linux_nfc_api.h], [nfc_nci_available="yes"])
4950 AC_CHECK_FUNCS([memmove memset select strdup strerror strstr strtol usleep],
5051 [AC_DEFINE([_XOPEN_SOURCE], [600], [Enable POSIX extensions if present])])
5152
124125
125126 # Enable I2C if
126127 AM_CONDITIONAL(I2C_ENABLED, [test x"$i2c_required" = x"yes"])
128 if test x"$i2c_required" = x"yes"
129 then
130 AC_SEARCH_LIBS([clock_gettime], [rt])
131 fi
132
133 # Enable Libnfc-NCI if required
134 if test x"$nfc_nci_required" = x"yes"
135 then
136 PKG_CHECK_MODULES([LIBNFC_NCI], [libnfc-nci],
137 [AC_MSG_NOTICE([libnfc-nci present])],
138 [AC_MSG_ERROR([libnfc-nci not present but required for some drivers configuration])]
139 )
140 CFLAGS="$CFLAGS $LIBNFC_NCI_CFLAGS"
141 fi
127142
128143 # Documentation (default: no)
129144 AC_ARG_ENABLE([doc],AS_HELP_STRING([--enable-doc],[Enable documentation generation.]),[enable_doc=$enableval],[enable_doc="no"])
00 EXTRA_DIST = \
1 pn532_via_uart2usb.conf.sample \
2 arygon.conf.sample \
3 pn532_uart_on_rpi.conf.sample
1 arygon.conf.sample \
2 pn532_i2c_on_rpi.conf.sample \
3 pn532_spi_on_rpi.conf.sample \
4 pn532_uart_on_rpi_3.conf.sample \
5 pn532_uart_on_rpi.conf.sample \
6 pn532_via_uart2usb.conf.sample
0 ## Typical configuration file for PN532 device on R-Pi 3 connected using miniUART
1 ## Note: Changes have been made to R-Pi 3 with the addition of Bluetooth LE
2 ## The UART is now being used by the BLE module. Instead of disabling it, you can
3 ## use the PN532 device with the "mini UART", which is still hijacked by the linux kernel
4 ## as a serial console
5 ##
6 ## Tested recipe with PN532 breakout from Adafruit
7 ##
8 ## To enable uart on GPIO, add this line to bottom of /boot/config.txt
9 ## enable_uart=1
10 ##
11 ## Stop and disable serial console:
12 ## $ sudo systemctl stop serial-getty@ttyS0.service
13 ## $ sudo systemctl disable serial-getty@ttyS0.service
14 ##
15 ## Remove console from /boot/cmdline.txt by removing:
16 ## console=serial0,115200 Save and reboot for changes to take effect.
17 ##
18 name = "PN532 board via UART"
19 connstring = pn532_uart:/dev/ttyS0
20 allow_intrusive_scan = true
21
00 blacklist nfc
11 blacklist pn533
2 blacklist pn533_usb
+0
-21
contrib/udev/42-pn53x.rules less more
0 # udev rules file for PN531 and PN533 devices (for udev 0.98 version)
1 # to be installed in /etc/udev/rules.d
2
3 SUBSYSTEM!="usb|usb_device", GOTO="pn53x_rules_end"
4 ACTION!="add", GOTO="pn53x_rules_end"
5
6 # PN531
7 ATTRS{idVendor}=="04cc", ATTRS{idProduct}=="0531", MODE="0664", GROUP="plugdev"
8 ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0193", MODE="0664", GROUP="plugdev"
9
10 # PN533
11 ATTRS{idVendor}=="04cc", ATTRS{idProduct}=="2533", MODE="0664", GROUP="plugdev"
12 ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5591", MODE="0664", GROUP="plugdev"
13 ATTRS{idVendor}=="1fd3", ATTRS{idProduct}=="0608", MODE="0664", GROUP="plugdev"
14 ATTRS{idVendor}=="054c", ATTRS{idProduct}=="02e1", MODE="0664", GROUP="plugdev"
15
16 # ACR122 / Touchatag
17 ATTRS{idVendor}=="072f", ATTRS{idProduct}=="2200", MODE="0664", GROUP="plugdev"
18 ATTRS{idVendor}=="072f", ATTRS{idProduct}=="90cc", MODE="0664", GROUP="plugdev"
19
20 LABEL="pn53x_rules_end"
0 # udev rules file for PN531 and PN533 devices (for udev 0.98 version)
1 # to be installed in /etc/udev/rules.d
2
3 SUBSYSTEM!="usb|usb_device", GOTO="pn53x_rules_end"
4 ACTION!="add", GOTO="pn53x_rules_end"
5
6 # PN531
7 ATTRS{idVendor}=="04cc", ATTRS{idProduct}=="0531", MODE="0664", GROUP="plugdev"
8 ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0193", MODE="0664", GROUP="plugdev"
9
10 # PN533
11 ATTRS{idVendor}=="04cc", ATTRS{idProduct}=="2533", MODE="0664", GROUP="plugdev"
12 ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5591", MODE="0664", GROUP="plugdev"
13 ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5594", MODE="0664", GROUP="plugdev"
14 ATTRS{idVendor}=="1fd3", ATTRS{idProduct}=="0608", MODE="0664", GROUP="plugdev"
15 ATTRS{idVendor}=="054c", ATTRS{idProduct}=="02e1", MODE="0664", GROUP="plugdev"
16
17 # ACR122 / Touchatag
18 ATTRS{idVendor}=="072f", ATTRS{idProduct}=="2200", MODE="0664", GROUP="plugdev"
19 ATTRS{idVendor}=="072f", ATTRS{idProduct}=="90cc", MODE="0664", GROUP="plugdev"
20
21 LABEL="pn53x_rules_end"
00 EXTRA_DIST = \
1 42-pn53x.rules
1 93-pn53x.rules
122122 {
123123 struct serial_port_windows *spw;
124124
125 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d bauds.", uiPortSpeed);
125 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed);
126126 // Set port speed (Input and Output)
127127 switch (uiPortSpeed) {
128128 case 9600:
134134 case 460800:
135135 break;
136136 default:
137 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed);
137 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);
138138 return;
139139 };
140140 spw = (struct serial_port_windows *) sp;
33 EXPORTS
44 nfc_init
55 nfc_exit
6 nfc_register_driver
67 nfc_open
78 nfc_close
8 nfc_abbort_command
9 nfc_abort_command
910 nfc_list_devices
1011 nfc_idle
1112 nfc_initiator_init
1617 nfc_initiator_select_dep_target
1718 nfc_initiator_poll_dep_target
1819 nfc_initiator_deselect_target
19 nfc_initiator_poll_targets
2020 nfc_initiator_transceive_bytes
2121 nfc_initiator_transceive_bits
2222 nfc_initiator_transceive_bytes_timed
3535 nfc_device_get_connstring
3636 nfc_device_get_supported_modulation
3737 nfc_device_get_supported_baud_rate
38 nfc_device_get_supported_baud_rate_target_mode
3839 nfc_device_set_property_int
3940 nfc_device_set_property_bool
4041 iso14443a_crc
4142 iso14443a_crc_append
43 iso14443b_crc
44 iso14443b_crc_append
4245 iso14443a_locate_historical_bytes
46 nfc_free
4347 nfc_version
4448 nfc_device_get_information_about
4549 str_nfc_modulation_type
3333 // Handle platform specific includes
3434 #include "contrib/windows.h"
3535
36 //There is no setenv()and unsetenv() in windows,but we can use putenv() instead.
3637 int setenv(const char *name, const char *value, int overwrite)
3738 {
38 int exists = GetEnvironmentVariableA(name, NULL, 0);
39 if ((exists && overwrite) || (!exists)) {
40 if (!SetEnvironmentVariableA(name, value)) {
41 // Set errno here correctly
42 return -1;
43 }
44 return 0;
39 char *env = getenv(name);
40 if ((env && overwrite) || (!env)) {
41 char *str[32];
42 strcpy(str, name);
43 strcat(str, "=");
44 strcat(str, value);
45 return putenv(str);
4546 }
46 // Exists and overwrite is 0.
4747 return -1;
4848 }
4949
5050 void unsetenv(const char *name)
5151 {
52 SetEnvironmentVariableA(name, NULL);
52 char *str[32];
53 strcpy(str, name);
54 strcat(str, "=");
55 putenv(str);
5356 }
77 nfc-mfsetuid
88 nfc-poll
99 nfc-relay
10 pn53x-diagnose
11 pn53x-sam
12 pn53x-tamashell
1013 )
1114
1215 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc)
7373 pn53x_tamashell_SOURCES = pn53x-tamashell.c
7474 pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \
7575 $(top_builddir)/utils/libnfcutils.la
76 pn53x_tamashell_CFLAGS = @READLINE_INCLUDES@ -I$(top_srcdir)
7677 pn53x_tamashell_LDFLAGS = @READLINE_LIBS@
7778
7879 quick_start_example1_SOURCES = doc/quick_start_example1.c
2222 .B libnfc
2323 issue tracker at:
2424 .br
25 .BR http://code.google.com/p/libnfc/issues
25 .BR https://github.com/nfc-tools/libnfc/issues
2626 .SH LICENCE
2727 .B libnfc
2828 is licensed under the GNU Lesser General Public License (LGPL), version 3.
1717 .B libnfc
1818 issue tracker at:
1919 .br
20 .BR http://code.google.com/p/libnfc/issues
20 .BR https://github.com/nfc-tools/libnfc/issues
2121 .SH LICENCE
2222 .B libnfc
2323 is licensed under the GNU Lesser General Public License (LGPL), version 3.
1717 .B libnfc
1818 issue tracker at:
1919 .br
20 .BR http://code.google.com/p/libnfc/issues
20 .BR https://github.com/nfc-tools/libnfc/issues
2121 .SH LICENCE
2222 .B libnfc
2323 is licensed under the GNU Lesser General Public License (LGPL), version 3.
3434 Please report any bugs on the
3535 .Em libnfc
3636 issue tracker at:
37 .Em http://code.google.com/p/libnfc/issues
37 .Em https://github.com/nfc-tools/libnfc/issues
3838 .Sh LICENCE
3939 .Em libnfc
4040 is licensed under the GNU Lesser General Public License (LGPL), version 3.
3838 .B libnfc
3939 issue tracker at:
4040 .br
41 .BR http://code.google.com/p/libnfc/issues
41 .BR https://github.com/nfc-tools/libnfc/issues
4242 .SH LICENCE
4343 .B libnfc
4444 is licensed under the GNU Lesser General Public License (LGPL), version 3.
265265 },
266266 .nti = {
267267 .nai = {
268 abtAtqa = { 0x03, 0x44 },
269 abtUid = { 0x08, 0xab, 0xcd, 0xef },
270 btSak = 0x20,
268 .abtAtqa = { 0x03, 0x44 },
269 .abtUid = { 0x08, 0xab, 0xcd, 0xef },
270 .btSak = 0x20,
271271 .szUidLen = 4,
272272 .abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
273273 .szAtsLen = 5,
1313 The nfc-emulate-uid tool demonstrates that this can still be done using
1414 transmission of raw frames, and the desired UID can be optionally specified.
1515
16 This makes it a serious thread for security systems that rely only on the
16 This makes it a serious threat for security systems that rely only on the
1717 uniqueness of the UID.
1818
1919 Unfortunately, this example can't directly start in fully customisable
5353 .B libnfc
5454 issue tracker at:
5555 .br
56 .BR http://code.google.com/p/libnfc/issues
56 .BR https://github.com/nfc-tools/libnfc/issues
5757 .SH LICENCE
5858 .B libnfc
5959 is licensed under the GNU Lesser General Public License (LGPL), version 3.
7878 if (pnd != NULL) {
7979 printf("\nAborting current command...\n");
8080 nfc_abort_command(pnd);
81 }
81 nfc_close(pnd);
82 }
83 nfc_exit(context);
84 exit(EXIT_SUCCESS);
8285 }
8386
8487 static void
236239 }
237240 }
238241 }
239 nfc_close(pnd);
240 nfc_exit(context);
241 exit(EXIT_SUCCESS);
242242 }
2323 .B libnfc
2424 issue tracker at:
2525 .br
26 .BR http://code.google.com/p/libnfc/issues
26 .BR https://github.com/nfc-tools/libnfc/issues
2727 .SH LICENCE
2828 .B libnfc
2929 is licensed under the GNU Lesser General Public License (LGPL), version 3.
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
1111 * Copyright (C) 2011 Adam Laurie
12 * Copyright (C) 2014 Dario Carluccio
1213 *
1314 * Redistribution and use in source and binary forms, with or without
1415 * modification, are permitted provided that the following conditions are met:
139140 static void
140141 print_usage(char *argv[])
141142 {
142 printf("Usage: %s [OPTIONS] [UID]\n", argv[0]);
143 printf("Usage: %s [OPTIONS] [UID|BLOCK0]\n", argv[0]);
143144 printf("Options:\n");
144145 printf("\t-h\tHelp. Print this message.\n");
145146 printf("\t-f\tFormat. Delete all data (set to 0xFF) and reset ACLs to default.\n");
146147 printf("\t-q\tQuiet mode. Suppress output of READER and CARD data (improves timing).\n");
147148 printf("\n\tSpecify UID (4 HEX bytes) to set UID, or leave blank for default '01234567'.\n");
149 printf("\n\tSpecify BLOCK0 (16 HEX bytes) to set content of Block0. CRC (Byte 4) is recalculated an overwritten'.\n");
148150 printf("\tThis utility can be used to recover cards that have been damaged by writing bad\n");
149151 printf("\tdata (e.g. wrong BCC), thus making them non-selectable by most tools/readers.\n");
150152 printf("\n\t*** Note: this utility only works with special Mifare 1K cards (Chinese clones).\n\n");
176178 }
177179 abtData[4] = abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3];
178180 iso14443a_crc_append(abtData, 16);
181 } else if (strlen(argv[arg]) == 32) {
182 for (i = 0 ; i < 16 ; ++i) {
183 memcpy(tmp, argv[arg] + i * 2, 2);
184 sscanf(tmp, "%02x", &c);
185 abtData[i] = (char) c;
186 }
187 abtData[4] = abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3];
188 iso14443a_crc_append(abtData, 16);
179189 } else {
180190 ERR("%s is not supported option.", argv[arg]);
181191 print_usage(argv);
354364 // now reset UID
355365 iso14443a_crc_append(abtHalt, 2);
356366 transmit_bytes(abtHalt, 4);
357 transmit_bits(abtUnlock1, 7);
358 if (format) {
359 transmit_bytes(abtWipe, 1);
360 transmit_bytes(abtHalt, 4);
361 transmit_bits(abtUnlock1, 7);
362 }
363 transmit_bytes(abtUnlock2, 1);
367
368 if (!transmit_bits(abtUnlock1, 7)) {
369 printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
370 } else {
371 if (format) {
372 transmit_bytes(abtWipe, 1);
373 transmit_bytes(abtHalt, 4);
374 transmit_bits(abtUnlock1, 7);
375 }
376
377 if (transmit_bytes(abtUnlock2, 1)) {
378 printf("Card unlocked\n");
379 } else {
380 printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n");
381 }
382 }
383
364384 transmit_bytes(abtWrite, 4);
365385 transmit_bytes(abtData, 18);
366386 if (format) {
4141 .B libnfc
4242 issue tracker at:
4343 .br
44 .BR http://code.google.com/p/libnfc/issues
44 .BR https://github.com/nfc-tools/libnfc/issues
4545 .SH LICENCE
4646 .B libnfc
4747 is licensed under the GNU Lesser General Public License (LGPL), version 3.
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * Redistribution and use in source and binary forms, with or without
1314 * modification, are permitted provided that the following conditions are met:
100101
101102 const uint8_t uiPollNr = 20;
102103 const uint8_t uiPeriod = 2;
103 const nfc_modulation nmModulations[5] = {
104 const nfc_modulation nmModulations[6] = {
104105 { .nmt = NMT_ISO14443A, .nbr = NBR_106 },
105106 { .nmt = NMT_ISO14443B, .nbr = NBR_106 },
106107 { .nmt = NMT_FELICA, .nbr = NBR_212 },
107108 { .nmt = NMT_FELICA, .nbr = NBR_424 },
108109 { .nmt = NMT_JEWEL, .nbr = NBR_106 },
110 { .nmt = NMT_ISO14443BICLASS, .nbr = NBR_106 },
109111 };
110 const size_t szModulations = 5;
112 const size_t szModulations = 6;
111113
112114 nfc_target nt;
113115 int res = 0;
144146
145147 if (res > 0) {
146148 print_nfc_target(&nt, verbose);
149 printf("Waiting for card removing...");
150 fflush(stdout);
151 while (0 == nfc_initiator_target_is_present(pnd, NULL)) {}
152 nfc_perror(pnd, "nfc_initiator_target_is_present");
153 printf("done.\n");
147154 } else {
148155 printf("No target found.\n");
149156 }
150
151 printf("Waiting for card removing...");
152 while (0 == nfc_initiator_target_is_present(pnd, NULL)) {}
153 nfc_perror(pnd, "nfc_initiator_target_is_present");
154 printf("done.\n");
155157
156158 nfc_close(pnd);
157159 nfc_exit(context);
2121 .B libnfc
2222 issue tracker at:
2323 .br
24 .BR http://code.google.com/p/libnfc/issues
24 .BR https://github.com/nfc-tools/libnfc/issues
2525 .SH LICENCE
2626 .B libnfc
2727 is licensed under the GNU Lesser General Public License (LGPL), version 3.
1212 .B libnfc
1313 issue tracker at:
1414 .br
15 .BR http://code.google.com/p/libnfc/issues
15 .BR https://github.com/nfc-tools/libnfc/issues
1616 .SH LICENCE
1717 .B libnfc
1818 is licensed under the GNU Lesser General Public License (LGPL), version 3.
1818 .B libnfc
1919 issue tracker at:
2020 .br
21 .BR http://code.google.com/p/libnfc/issues
21 .BR https://github.com/nfc-tools/libnfc/issues
2222 .SH LICENCE
2323 .B libnfc
2424 is licensed under the GNU Lesser General Public License (LGPL), version 3.
00 #!/bin/sh
1
2 #DEBUG='//;'
13
24 cat << EOF | \
35 pn53x-tamashell |\
4 awk '\
6 awk $DEBUG'\
57 /^> #.*:/{
68 sub(/^> #/,"")
79 n=$0
2022 # Select one typeB target
2123 4A010300
2224
25 # SELECT AID "1TIC.ICA"
26 4001 00a4 0400 08 315449432e494341
27
2328 # Select ICC file
24 4001 80a4 0800 04 3f00 0002
29 4001 00a4 0000 02 3f00
30 4001 00a4 0000 02 0002
2531 #ICC:
26 4001 80b2 0104 1d
32 4001 00b2 0104 1d
2733
2834 # Select Holder file
29 4001 80a4 0800 04 3f00 3f1c
35 4001 00a4 0000 02 3f1c
3036 #Holder1:
31 4001 80b2 0104 1d
37 4001 00b2 0104 1d
3238 #Holder2:
33 4001 80b2 0204 1d
39 4001 00b2 0204 1d
3440
3541 # Select EnvHol file
36 4001 00a4 0800 04 2000 2001
42 4001 00a4 0000 00
43 4001 00a4 0000 02 2000
44 4001 00a4 0000 02 2001
3745 #EnvHol1:
3846 4001 00b2 0104 1d
3947 #EnvHol2:
4048 4001 00b2 0204 1d
4149
4250 # Select EvLog file
43 4001 00a4 0800 04 2000 2010
51 4001 00a4 0000 02 2010
4452 #EvLog1:
4553 4001 00b2 0104 1d
4654 #EvLog2:
4957 4001 00b2 0304 1d
5058
5159 # Select ConList file
52 4001 00a4 0800 04 2000 2050
60 4001 00a4 0000 02 2050
5361 #ConList:
5462 4001 00b2 0104 1d
5563
5664 # Select Contra file
57 4001 00a4 0800 04 2000 2020
65 4001 00a4 0000 02 2020
5866 #Contra1:
5967 4001 00b2 0104 1d
6068 #Contra2:
8189 4001 00b2 0c04 1d
8290
8391 # Select Counter file
84 4001 00a4 0800 04 2000 2069
92 4001 00a4 0000 02 2069
8593 #Counter:
8694 4001 00b2 0104 1d
8795
8896 # Select LoadLog file
89 4001 00a4 0800 04 1000 1014
97 4001 00a4 0000 00
98 4001 00a4 0000 02 1000
99 4001 00a4 0000 02 1014
90100 #LoadLog:
91101 4001 00b2 0104 1d
92102
93103 # Select Purcha file
94 4001 00a4 08 0004 1000 1015
104 4001 00a4 0000 02 1015
95105 #Purcha1:
96106 4001 00b2 0104 1d
97107 #Purcha2:
100110 4001 00b2 0304 1d
101111
102112 # Select SpecEv file
103 4001 00a4 08 0004 2000 2040
113 4001 00a4 0000 00
114 4001 00a4 0000 02 2000
115 4001 00a4 0000 02 2040
104116 #SpecEv1:
105117 4001 00b2 0104 1d
106118 #SpecEv2:
6767 .B libnfc
6868 issue tracker at:
6969 .br
70 .BR http://code.google.com/p/libnfc/issues
70 .BR https://github.com/nfc-tools/libnfc/issues
7171 .SH LICENCE
7272 .B libnfc
7373 is licensed under the GNU Lesser General Public License (LGPL), version 3.
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
234235 } nfc_iso14443bi_info;
235236
236237 /**
238 * @struct nfc_iso14443biclass_info
239 * @brief NFC ISO14443BiClass tag information
240 */
241 typedef struct {
242 uint8_t abtUID[8];
243 } nfc_iso14443biclass_info;
244
245 /**
237246 * @struct nfc_iso14443b2sr_info
238247 * @brief NFC ISO14443-2B ST SRx tag information
239248 */
259268 uint8_t btSensRes[2];
260269 uint8_t btId[4];
261270 } nfc_jewel_info;
271
272 /**
273 * @struct nfc_barcode_info
274 * @brief Thinfilm NFC Barcode information
275 */
276 typedef struct {
277 size_t szDataLen;
278 uint8_t abtData[32];
279 } nfc_barcode_info;
262280
263281 /**
264282 * @union nfc_target_info
273291 nfc_iso14443b2ct_info nci;
274292 nfc_jewel_info nji;
275293 nfc_dep_info ndi;
294 nfc_barcode_info nti; // "t" for Thinfilm, "b" already used
295 nfc_iso14443biclass_info nhi; // hid iclass / picopass - nii already used
276296 } nfc_target_info;
277297
278298 /**
300320 NMT_ISO14443B2CT, // ISO14443-2B ASK CTx
301321 NMT_FELICA,
302322 NMT_DEP,
323 NMT_BARCODE, // Thinfilm NFC Barcode
324 NMT_ISO14443BICLASS, // HID iClass 14443B mode
325 NMT_END_ENUM = NMT_ISO14443BICLASS, // dummy for sizing - always should alias last
303326 } nfc_modulation_type;
304327
305328 /**
2727 * @file nfc.h
2828 * @brief libnfc interface
2929 *
30 * Provide all usefull functions (API) to handle NFC devices.
30 * Provide all useful functions (API) to handle NFC devices.
3131 */
3232
3333 #ifndef _LIBNFC_H_
3434 # define _LIBNFC_H_
35
36 # include <sys/time.h>
3735
3836 # include <stdint.h>
3937 # include <stdbool.h>
126124 NFC_EXPORT const char *nfc_device_get_connstring(nfc_device *pnd);
127125 NFC_EXPORT int nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt);
128126 NFC_EXPORT int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
127 NFC_EXPORT int nfc_device_get_supported_baud_rate_target_mode(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
129128
130129 /* Properties accessors */
131130 NFC_EXPORT int nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value);
4646
4747 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses)
4848
49 IF(WIN32)
50 # Windows now requires regex, so we utilize PCRE
51 # since Windows doesn't get the benefit of finding in CMake
52 # it has to be added manually
53 IF(PCRE_FOUND)
54 INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS})
55 LINK_DIRECTORIES(${PCRE_LIBRARY_DIRS})
56 ENDIF(PCRE_FOUND)
57 ENDIF(WIN32)
58
5949 IF(PCSC_FOUND)
6050 INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS})
6151 LINK_DIRECTORIES(${PCSC_LIBRARY_DIRS})
8878 TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES})
8979 ENDIF(LIBUSB_FOUND)
9080
91 SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 0)
81 IF(LIBRT_FOUND)
82 TARGET_LINK_LIBRARIES(nfc ${LIBRT_LIBRARIES})
83 ENDIF(LIBRT_FOUND)
84
85 SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 6 VERSION 6.0.0)
9286
9387 IF(WIN32)
9488 # Libraries that are windows specific
9589 TARGET_LINK_LIBRARIES(nfc wsock32)
96 IF(PCRE_FOUND)
97 TARGET_LINK_LIBRARIES(nfc ${PCRE_LIBRARIES})
98 ENDIF(PCRE_FOUND)
9990
10091 ADD_CUSTOM_COMMAND(
10192 OUTPUT libnfc.lib
102 COMMAND dlltool -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll
93 COMMAND ${DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll
10394 DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def
10495 )
10596 ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib)
2121 nfc-internal.h \
2222 target-subr.h
2323
24 libnfc_la_LDFLAGS = -no-undefined -version-info 5:1:0 -export-symbols-regex '^nfc_|^iso14443a_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register'
24 libnfc_la_LDFLAGS = -no-undefined -version-info 6:0:0 -export-symbols-regex '^nfc_|^iso14443a_|^iso14443b_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register'
2525 libnfc_la_CFLAGS = @DRIVERS_CFLAGS@
2626 libnfc_la_LIBADD = \
2727 $(top_builddir)/libnfc/chips/libnfcchips.la \
4343 endif
4444
4545 EXTRA_DIST = \
46 CMakeLists.txt
46 CMakeLists.txt \
47 additional-pages.dox
134134
135135 if (recCount < 0) {
136136 res = NFC_EIO;
137 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR,
138 "Error: read only %d bytes (%d expected) (%s).", (int)recCount, (int) szRx, strerror(errno));
137139 } else {
138140 if (recCount < (ssize_t)szRx) {
139141 res = NFC_EINVARG;
166168 return NFC_SUCCESS;
167169 } else {
168170 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR,
169 "Error: wrote only %d bytes (%d expected).", (int)writeCount, (int) szTx);
171 "Error: wrote only %d bytes (%d expected) (%s).", (int)writeCount, (int) szTx, strerror(errno));
170172 return NFC_EIO;
171173 }
172174 }
188190 size_t szRes = 1;
189191
190192 res[0] = NULL;
191 DIR *dir;
192 if ((dir = opendir("/dev")) == NULL) {
193 DIR *pdDir;
194 if ((pdDir = opendir("/dev")) == NULL) {
193195 perror("opendir error: /dev");
194196 return res;
195197 }
196 struct dirent entry;
197 struct dirent *result;
198
199 while ((readdir_r(dir, &entry, &result) == 0) && (result != NULL)) {
198 struct dirent *pdDirEnt;
199 while ((pdDirEnt = readdir(pdDir)) != NULL) {
200200 const char **p = i2c_ports_device_radix;
201201 while (*p) {
202 if (!strncmp(entry.d_name, *p, strlen(*p))) {
202 if (!strncmp(pdDirEnt->d_name, *p, strlen(*p))) {
203203 char **res2 = realloc(res, (szRes + 1) * sizeof(char *));
204204 if (!res2) {
205205 perror("malloc");
206206 goto oom;
207207 }
208208 res = res2;
209 if (!(res[szRes - 1] = malloc(6 + strlen(entry.d_name)))) {
209 if (!(res[szRes - 1] = malloc(6 + strlen(pdDirEnt->d_name)))) {
210210 perror("malloc");
211211 goto oom;
212212 }
213 sprintf(res[szRes - 1], "/dev/%s", entry.d_name);
213 sprintf(res[szRes - 1], "/dev/%s", pdDirEnt->d_name);
214214
215215 szRes++;
216216 res[szRes - 1] = NULL;
219219 }
220220 }
221221 oom:
222 closedir(dir);
222 closedir(pdDir);
223223
224224 return res;
225225 }
195195 struct spi_ioc_transfer tr_send = {
196196 .tx_buf = (unsigned long) pbtTx,
197197 .rx_buf = 0,
198 .len = szTx ,
198 .len = szTx,
199199 .delay_usecs = 0,
200200 .speed_hz = 0,
201201 .bits_per_word = 0,
282282
283283 DIR *pdDir = opendir("/dev");
284284 struct dirent *pdDirEnt;
285 struct dirent entry;
286 struct dirent *result;
287 while ((readdir_r(pdDir, &entry, &result) == 0) && (result != NULL)) {
288 pdDirEnt = &entry;
285 while ((pdDirEnt = readdir(pdDir)) != NULL) {
289286 #if !defined(__APPLE__)
290287 if (!isdigit(pdDirEnt->d_name[strlen(pdDirEnt->d_name) - 1]))
291288 continue;
7373 #endif
7474
7575 # if defined(__APPLE__)
76 const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial-", NULL };
76 const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial", "tty.usbmodem", NULL };
7777 # elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__FreeBSD_kernel__)
7878 const char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL };
79 # elif defined (__linux__)
79 # elif defined (__NetBSD__)
80 const char *serial_ports_device_radix[] = { "tty0", "ttyC", "ttyS", "ttyU", "ttyY", NULL };
81 # elif defined (__linux__) || defined (__CYGWIN__)
8082 const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA", "ttyO", NULL };
8183 # else
8284 # error "Can't determine serial string for your system"
8385 # endif
86
87 // As of 2015/Feb/22, Cygwin does not handle FIONREAD on physical serial devices.
88 // We'll use TIOCINQ instead which is pretty much the same.
89 #ifdef __CYGWIN__
90 # include <sys/termios.h>
91 # define FIONREAD TIOCINQ
92 #endif
8493
8594 // Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
8695 # define CCLAIMED 0x80000000
178187 void
179188 uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
180189 {
181 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d bauds.", uiPortSpeed);
190 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed);
182191
183192 // Portability note: on some systems, B9600 != 9600 so we have to do
184193 // uint32_t <=> speed_t associations by hand.
214223 break;
215224 # endif
216225 default:
217 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).",
226 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 those defined in termios(3).",
218227 uiPortSpeed);
219228 return;
220229 };
384393 size_t szRes = 1;
385394
386395 res[0] = NULL;
387 DIR *dir;
388 if ((dir = opendir("/dev")) == NULL) {
396 DIR *pdDir;
397 if ((pdDir = opendir("/dev")) == NULL) {
389398 perror("opendir error: /dev");
390399 return res;
391400 }
392 struct dirent entry;
393 struct dirent *result;
394 while ((readdir_r(dir, &entry, &result) == 0) && (result != NULL)) {
401 struct dirent *pdDirEnt;
402 while ((pdDirEnt = readdir(pdDir)) != NULL) {
395403 #if !defined(__APPLE__)
396 if (!isdigit(entry.d_name[strlen(entry.d_name) - 1]))
404 if (!isdigit(pdDirEnt->d_name[strlen(pdDirEnt->d_name) - 1]))
397405 continue;
398406 #endif
399407 const char **p = serial_ports_device_radix;
400408 while (*p) {
401 if (!strncmp(entry.d_name, *p, strlen(*p))) {
409 if (!strncmp(pdDirEnt->d_name, *p, strlen(*p))) {
402410 char **res2 = realloc(res, (szRes + 1) * sizeof(char *));
403411 if (!res2) {
404412 perror("malloc");
405413 goto oom;
406414 }
407415 res = res2;
408 if (!(res[szRes - 1] = malloc(6 + strlen(entry.d_name)))) {
416 if (!(res[szRes - 1] = malloc(6 + strlen(pdDirEnt->d_name)))) {
409417 perror("malloc");
410418 goto oom;
411419 }
412 sprintf(res[szRes - 1], "/dev/%s", entry.d_name);
420 sprintf(res[szRes - 1], "/dev/%s", pdDirEnt->d_name);
413421
414422 szRes++;
415423 res[szRes - 1] = NULL;
418426 }
419427 }
420428 oom:
421 closedir(dir);
429 closedir(pdDir);
422430
423431 return res;
424432 }
3434
3535 #ifndef _WIN32
3636 // Under POSIX system, we use libusb (>= 0.1.12)
37 #include <stdint.h>
3738 #include <usb.h>
3839 #define USB_TIMEDOUT ETIMEDOUT
3940 #define _usb_strerror( X ) strerror(-X)
8080 #define TgGetTargetStatus 0x8A
8181
8282 /** @note PN53x's normal frame:
83 *
84 * .-- Start
85 * | .-- Packet length
86 * | | .-- Length checksum
87 * | | | .-- Direction (D4 Host to PN, D5 PN to Host)
88 * | | | | .-- Code
89 * | | | | | .-- Packet checksum
90 * | | | | | | .-- Postamble
91 * V | | | | | |
92 * ----- V V V V V V
93 * 00 FF 02 FE D4 02 2A 00
83 * See the PN532 (firmware) user manual, section 6.2.1.1: Normal information
84 * frame, figure 13. Normal information frame, page 28 rev. 02 - 2007-11-07.
85 *
86 * .-- Preamble
87 * | .-- Start
88 * | | .-- Packet length
89 * | | | .-- Length checksum
90 * | | | | .-- Direction (D4 Host to PN, D5 PN to Host)
91 * | | | | | .-- Code
92 * | | | | | | .-- Packet checksum
93 * | | | | | | | .-- Postamble
94 * | V | | | | | |
95 * V ----- V V V V V V
96 * 00 00 FF 02 FE D4 02 2A 00
9497 */
9598
9699 /** @note PN53x's extended frame:
97 *
98 * .-- Start
99 * | .-- Fixed to FF to enable extended frame
100 * | | .-- Packet length
101 * | | | .-- Length checksum
102 * | | | | .-- Direction (D4 Host to PN, D5 PN to Host)
103 * | | | | | .-- Code
104 * | | | | | | .-- Packet checksum
105 * | | | | | | | .-- Postamble
106 * V V V | | | | |
107 * ----- ----- ----- V V V V V
108 * 00 FF FF FF 00 02 FE D4 02 2A 00
100 * See the PN532 (firmware) user manual, section 6.2.1.2: Extended information
101 * frame, figure 14. Normal information frame, page 29 rev. 02 - 2007-11-07.
102 *
103 * .-- Preamble
104 * | .-- Start
105 * | | .-- Fixed to FF to enable extended frame
106 * | | | .-- Packet length
107 * | | | | .-- Length checksum
108 * | | | | | .-- Direction (D4 Host to PN, D5 PN to Host)
109 * | | | | | | .-- Code
110 * | | | | | | | .-- Packet checksum
111 * | | | | | | | | .-- Postamble
112 * | V V V | | | | |
113 * V ----- ----- ----- V V V V V
114 * 00 00 FF FF FF 00 02 FE D4 02 2A 00
109115 */
110116
111117 /**
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
5152 const uint8_t pn53x_ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
5253 const uint8_t pn53x_nack_frame[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 };
5354 static const uint8_t pn53x_error_frame[] = { 0x00, 0x00, 0xff, 0x01, 0xff, 0x7f, 0x81, 0x00 };
54 const nfc_baud_rate pn53x_iso14443a_supported_baud_rates[] = { NBR_106, 0 };
55 const nfc_baud_rate pn532_iso14443a_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 };
56 const nfc_baud_rate pn533_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
5557 const nfc_baud_rate pn53x_felica_supported_baud_rates[] = { NBR_424, NBR_212, 0 };
5658 const nfc_baud_rate pn53x_dep_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 };
5759 const nfc_baud_rate pn53x_jewel_supported_baud_rates[] = { NBR_106, 0 };
60 const nfc_baud_rate pn53x_barcode_supported_baud_rates[] = { NBR_106, 0 };
5861 const nfc_baud_rate pn532_iso14443b_supported_baud_rates[] = { NBR_106, 0 };
5962 const nfc_baud_rate pn533_iso14443b_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
6063 const nfc_modulation_type pn53x_supported_modulation_as_target[] = {NMT_ISO14443A, NMT_FELICA, NMT_DEP, 0};
8285 }
8386
8487 if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) {
85 CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * 9);
88 CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_END_ENUM + 1));
8689 if (! CHIP_DATA(pnd)->supported_modulation_as_initiator)
8790 return NFC_ESOFT;
8891 int nbSupportedModulation = 0;
9598 if (pnd->btSupportByte & SUPPORT_ISO14443B) {
9699 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B;
97100 nbSupportedModulation++;
101 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443BI;
102 nbSupportedModulation++;
103 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B2SR;
104 nbSupportedModulation++;
105 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B2CT;
106 nbSupportedModulation++;
107 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443BICLASS;
108 nbSupportedModulation++;
98109 }
99110 if (CHIP_DATA(pnd)->type != PN531) {
100111 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_JEWEL;
112 nbSupportedModulation++;
113 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_BARCODE;
101114 nbSupportedModulation++;
102115 }
103116 CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_DEP;
363376 pn53x_wrap_frame(const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar,
364377 uint8_t *pbtFrame)
365378 {
366 uint8_t btFrame;
367379 uint8_t btData;
368380 uint32_t uiBitPos;
369381 uint32_t uiDataPos = 0;
390402 // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + ..
391403 while (true) {
392404 // Reset the temporary frame byte;
393 btFrame = 0;
405 uint8_t btFrame = 0;
394406
395407 for (uiBitPos = 0; uiBitPos < 8; uiBitPos++) {
396408 // Copy as much data that fits in the frame byte
565577 memcpy(pnti->nsi.abtUID, pbtRawData, 8);
566578 break;
567579
580 case NMT_ISO14443BICLASS:
581 // Store the UID
582 for (uint8_t i = 0 ; i < 8 ; ++i)
583 pnti->nhi.abtUID[7 - i] = pbtRawData[i];
584 break;
585
568586 case NMT_ISO14443B2CT:
569587 // Store UID LSB
570588 memcpy(pnti->nci.abtUID, pbtRawData, 2);
603621 pbtRawData += 2;
604622 memcpy(pnti->nji.btId, pbtRawData, 4);
605623 break;
606 // Should not happend...
624 case NMT_BARCODE:
625 pnti->nti.szDataLen = szRawData;
626 memcpy(pnti->nti.abtData, pbtRawData, szRawData);
627 break;
628 // Should not happend...
607629 case NMT_DEP:
608630 return NFC_ECHIP;
609 break;
610631 }
611632 return NFC_SUCCESS;
612633 }
819840 case NP_TIMEOUT_ATR:
820841 CHIP_DATA(pnd)->timeout_atr = value;
821842 return pn53x_RFConfiguration__Various_timings(pnd, pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_atr), pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_communication));
822 break;
823843 case NP_TIMEOUT_COM:
824844 CHIP_DATA(pnd)->timeout_communication = value;
825845 return pn53x_RFConfiguration__Various_timings(pnd, pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_atr), pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_communication));
826 break;
827 // Following properties are invalid (not integer)
846 // Following properties are invalid (not integer)
828847 case NP_HANDLE_CRC:
829848 case NP_HANDLE_PARITY:
830849 case NP_ACTIVATE_FIELD:
862881 return res;
863882 pnd->bCrc = bEnable;
864883 return NFC_SUCCESS;
865 break;
866884
867885 case NP_HANDLE_PARITY:
868886 // Handle parity bit by PN53X chip or parse it as data bit
874892 return res;
875893 pnd->bPar = bEnable;
876894 return NFC_SUCCESS;
877 break;
878895
879896 case NP_EASY_FRAMING:
880897 pnd->bEasyFraming = bEnable;
881898 return NFC_SUCCESS;
882 break;
883899
884900 case NP_ACTIVATE_FIELD:
885901 return pn53x_RFConfiguration__RF_field(pnd, bEnable);
886 break;
887902
888903 case NP_ACTIVATE_CRYPTO1:
889904 btValue = (bEnable) ? SYMBOL_MF_CRYPTO1_ON : 0x00;
890905 return pn53x_write_register(pnd, PN53X_REG_CIU_Status2, SYMBOL_MF_CRYPTO1_ON, btValue);
891 break;
892906
893907 case NP_INFINITE_SELECT:
894908 // TODO Made some research around this point:
900914 (bEnable) ? 0xff : 0x01, // MxRtyPSL, default: 0x01
901915 (bEnable) ? 0xff : 0x02 // MxRtyPassiveActivation, default: 0xff (0x00 leads to problems with PN531)
902916 );
903 break;
904917
905918 case NP_ACCEPT_INVALID_FRAMES:
906919 btValue = (bEnable) ? SYMBOL_RX_NO_ERROR : 0x00;
907920 return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_NO_ERROR, btValue);
908 break;
909921
910922 case NP_ACCEPT_MULTIPLE_FRAMES:
911923 btValue = (bEnable) ? SYMBOL_RX_MULTIPLE : 0x00;
912924 return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_MULTIPLE, btValue);
913 break;
914925
915926 case NP_AUTO_ISO14443_4:
916927 if (bEnable == pnd->bAutoIso14443_4)
918929 return NFC_SUCCESS;
919930 pnd->bAutoIso14443_4 = bEnable;
920931 return pn53x_set_parameters(pnd, PARAM_AUTO_RATS, bEnable);
921 break;
922932
923933 case NP_FORCE_ISO14443_A:
924934 if (!bEnable) {
934944 }
935945 // Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
936946 return pn53x_write_register(pnd, PN53X_REG_CIU_TxAuto, SYMBOL_FORCE_100_ASK, 0x40);
937 break;
938947
939948 case NP_FORCE_ISO14443_B:
940949 if (!bEnable) {
946955 return res;
947956 }
948957 return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_FRAMING, 0x03);
949 break;
950958
951959 case NP_FORCE_SPEED_106:
952960 if (!bEnable) {
958966 return res;
959967 }
960968 return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_SPEED, 0x00);
961 break;
962 // Following properties are invalid (not boolean)
969 // Following properties are invalid (not boolean)
963970 case NP_TIMEOUT_COMMAND:
964971 case NP_TIMEOUT_ATR:
965972 case NP_TIMEOUT_COM:
966973 return NFC_EINVARG;
967 break;
968974 }
969975
970976 return NFC_EINVARG;
10501056 return NFC_SUCCESS;
10511057 }
10521058
1059 // iclass requires special modulation settings
1060 void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd)
1061 {
1062 // send a bunch of low level commands reverse engineered from a working iClass reader
1063 // original device was using a PN512
1064 //
1065 // // TxModeReg - Defines the data rate and framing during transmission.
1066 //// set bit 4 for target mode? - RxWaitRF Set to logic 1, the counter for RxWait starts only if an external RF field is detected in Target mode for NFCIP-1 or in Card Communication mode
1067 //pn512_write_register(0x12, "\x03", 1, false);
1068 pn53x_WriteRegister(pnd, PN53X_REG_CIU_TxMode, 0x03);
1069 //
1070 // // RxModeReg - Defines the data rate and framing during reception.
1071 //pn512_write_register(0x13, "\x03", 1, false);
1072 // addy changed to set bit 3 - RxNoErr (put data in fifo before flagging read end)
1073 //pn512_write_register(0x13, "\x0B", 1, false);
1074 pn53x_WriteRegister(pnd, PN53X_REG_CIU_RxMode, 0x0B);
1075
1076 // ManualRCVReg - Allows manual fine tuning of the internal receiver.
1077 //pn512_write_register(0x1d, "\x10", 1, false);
1078 pn53x_WriteRegister(pnd, PN53X_REG_CIU_ManualRCV, 0x10);
1079
1080 // RFCfgReg - Configures the receiver gain and RF level detector sensitivity.
1081 //pn512_write_register(0x26, "\x70", 1, false);
1082 pn53x_WriteRegister(pnd, PN53X_REG_CIU_RFCfg, 0x70);
1083
1084 // GsNOffReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched off.
1085 //pn512_write_register(0x23, "\x88", 1, false);
1086 pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOFF, 0x88);
1087
1088 // GsNOnReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched on.
1089 //pn512_write_register(0x27, "\xf8", 1, false);
1090 pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOn, 0xf8);
1091
1092 // CWGsPReg - Defines the conductance of the P-driver during times of no modulation.
1093 //pn512_write_register(0x28, "\x3f", 1, false);
1094 pn53x_WriteRegister(pnd, PN53X_REG_CIU_CWGsP, 0x3f);
1095
1096 // ModGsPReg - Defines the driver P-output conductance during modulation.
1097 //pn512_write_register(0x29, "\x10", 1, false);
1098 pn53x_WriteRegister(pnd, PN53X_REG_CIU_ModGsP, 0x10);
1099
1100 // TReloadReg (MSB) - Describes the MSB of the 16-bit long timer reload value.
1101 //pn512_write_register(0x2c, "\x69", 1, false);
1102 pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_hi, 0x69);
1103
1104 // TReloadReg (LSB) - Describes the LSB of the 16-bit long timer reload value.
1105 //pn512_write_register(0x2d, "\xf0", 1, false);
1106 pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_lo, 0xf0);
1107 }
1108
10531109 int
10541110 pn532_initiator_init_secure_element(struct nfc_device *pnd)
10551111 {
10671123 size_t szTargetsData = sizeof(abtTargetsData);
10681124 int res = 0;
10691125 nfc_target nttmp;
1070
1071 if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT) {
1126 memset(&nttmp, 0x00, sizeof(nfc_target));
1127
1128 if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT || nm.nmt == NMT_ISO14443BICLASS) {
10721129 if (CHIP_DATA(pnd)->type == RCS360) {
10731130 // TODO add support for RC-S360, at the moment it refuses to send raw frames without a first select
10741131 pnd->last_error = NFC_ENOTIMPL;
10951152 size_t szInitiateLen = 2;
10961153 uint8_t abtSelect[] = { 0x0e, 0x00 };
10971154 uint8_t abtRx[1];
1155 uint8_t *pbtInitData = (uint8_t *) "\x0b";
1156 size_t szInitData = 1;
10981157 // Getting random Chip_ID
10991158 if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) {
11001159 if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
11071166 return res;
11081167 }
11091168 szTargetsData = (size_t)res;
1169 if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) {
1170 if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
1171 continue;
1172 } else
1173 return res;
1174 }
1175 szTargetsData = (size_t)res;
11101176 } else if (nm.nmt == NMT_ISO14443B2CT) {
11111177 // Some work to do before getting the UID...
11121178 const uint8_t abtReqt[] = { 0x10 };
1179 uint8_t *pbtInitData = (uint8_t *) "\x9F\xFF\xFF";
1180 size_t szInitData = 3;
11131181 // Getting product code / fab code & store it in output buffer after the serial nr we'll obtain later
11141182 if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), abtTargetsData + 2, sizeof(abtTargetsData) - 2, timeout)) < 0) {
11151183 if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
11181186 return res;
11191187 }
11201188 szTargetsData = (size_t)res;
1121 }
1122
1123 if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) {
1124 if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
1125 continue;
1126 } else
1127 return res;
1128 }
1129 szTargetsData = (size_t)res;
1130 if (nm.nmt == NMT_ISO14443B2CT) {
1189 if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) {
1190 if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
1191 continue;
1192 } else
1193 return res;
1194 }
1195 szTargetsData = (size_t)res;
11311196 if (szTargetsData != 2)
11321197 return 0; // Target is not ISO14443B2CT
11331198 uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4)
11351200 return res;
11361201 }
11371202 szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB
1138 }
1203 } else if (nm.nmt == NMT_ISO14443BICLASS) {
1204 pn53x_initiator_init_iclass_modulation(pnd);
1205 //
1206 // Some work to do before getting the UID...
1207 // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response
1208 uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL
1209 uint8_t abtAnticol[11];
1210 if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout)) < 0) {
1211 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all");
1212 //if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
1213 // continue;
1214 //} else
1215 // return res;
1216 }
1217 // do select - returned anticol contains 'handle' for tag if present
1218 abtReqt[0] = 0x0c; // iClass SELECT
1219 abtAnticol[0] = 0x81; // iClass ANTICOL
1220 if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout)) < 0) {
1221 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol");
1222 return res;
1223 }
1224 // write back anticol handle to get UID
1225 if ((res = pn53x_initiator_transceive_bytes(pnd, abtAnticol, 9, abtTargetsData, 10, timeout)) < 0) {
1226 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass get UID");
1227 return res;
1228 }
1229 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "iClass raw UID: %02x %02x %02x %02x %02x %02x %02x %02x", abtTargetsData[0], abtTargetsData[1], abtTargetsData[2], abtTargetsData[3], abtTargetsData[4], abtTargetsData[5], abtTargetsData[6], abtTargetsData[7]);
1230 szTargetsData = 8;
1231 nttmp.nm = nm;
1232 if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) {
1233 return res;
1234 }
1235 } else {
1236
1237 if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) {
1238 if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
1239 continue;
1240 } else
1241 return res;
1242 }
1243 szTargetsData = (size_t)res;
1244 }
1245
11391246 nttmp.nm = nm;
11401247 if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) {
11411248 return res;
11551262 } while (pnd->bInfiniteSelect);
11561263 if (! found)
11571264 return 0;
1265 } else if (nm.nmt == NMT_BARCODE) {
1266 if (CHIP_DATA(pnd)->type == RCS360) {
1267 // TODO add support for RC-S360, at the moment it refuses to send raw frames without a first select
1268 pnd->last_error = NFC_ENOTIMPL;
1269 return pnd->last_error;
1270 }
1271 // No native support in InListPassiveTarget so we do discovery by hand
1272
1273 // We turn RF field off first for a better detection rate but this doesn't work well with ASK LoGO
1274 if ((! CHIP_DATA(pnd)->progressive_field) && (res = nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false)) < 0) {
1275 return res;
1276 }
1277 if ((res = nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false)) < 0) {
1278 return res;
1279 }
1280 if ((res = nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, false)) < 0) {
1281 return res;
1282 }
1283
1284 bool found = false;
1285 do {
1286 uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
1287 uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
1288 if ((res = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 0) {
1289 if ((res == NFC_ERFTRANS) || (res == NFC_ECHIP)) { // Broken reception
1290 continue;
1291 } else {
1292 nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);
1293 nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true);
1294 return res;
1295 }
1296 }
1297
1298 // Shuffle bits to produce NFC Barcode bitstream
1299 uint8_t uRemainder;
1300 size_t szPos;
1301 size_t szBytes = res / 8;
1302 size_t off = 0;
1303 uint8_t i;
1304 memset(abtTargetsData, 0x00, sizeof(abtTargetsData));
1305 // Reinject S bit
1306 abtTargetsData[off / 8] |= 1 << (7 - (off % 8));
1307 off++;
1308
1309 for (szPos = 0; szPos < szBytes; szPos++) {
1310 for (i = 0; i < 8; i++) {
1311 abtTargetsData[off / 8] |= ((abtRx[szPos] >> i) & 1) << (7 - (off % 8));
1312 off++;
1313 }
1314 abtTargetsData[off / 8] |= abtRxPar[szPos] << (7 - (off % 8));
1315 off++;
1316 }
1317 uRemainder = res % 8;
1318 for (i = 0; i < uRemainder; i++) {
1319 abtTargetsData[off / 8] |= ((abtRx[szPos] >> i) & 1) << (7 - (off % 8));
1320 off++;
1321 }
1322
1323 if (off % 128 != 0) {
1324 // NFC Barcode seems incomplete
1325 continue;
1326 }
1327
1328 szTargetsData = (size_t)off / 8;
1329
1330 // validate CRC
1331 uint8_t pbtCrc[2];
1332 iso14443a_crc(abtTargetsData, szTargetsData - 2, pbtCrc);
1333 if ((pbtCrc[1] != abtTargetsData[szTargetsData - 2]) || (pbtCrc[0] != abtTargetsData[szTargetsData - 1])) {
1334 continue;
1335 }
1336 nttmp.nm = nm;
1337 if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) {
1338 return res;
1339 }
1340 found = true;
1341 break;
1342 } while (pnd->bInfiniteSelect);
1343 if (! found) {
1344 return 0;
1345 }
11581346 } else {
1159
11601347 const pn53x_modulation pm = pn53x_nm_to_pm(nm);
1161 if (PM_UNDEFINED == pm) {
1348 if ((PM_UNDEFINED == pm) || (NBR_UNDEFINED == nm.nbr)) {
11621349 pnd->last_error = NFC_EINVARG;
11631350 return pnd->last_error;
11641351 }
11721359 nttmp.nm = nm;
11731360 if ((res = pn53x_decode_target_data(abtTargetsData + 1, szTargetsData - 1, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) {
11741361 return res;
1362 }
1363 if ((nm.nmt == NMT_ISO14443A) && (nm.nbr != NBR_106)) {
1364 uint8_t pncmd_inpsl[4] = { InPSL, 0x01 };
1365 pncmd_inpsl[2] = nm.nbr - 1;
1366 pncmd_inpsl[3] = nm.nbr - 1;
1367 if ((res = pn53x_transceive(pnd, pncmd_inpsl, sizeof(pncmd_inpsl), NULL, 0, 0)) < 0) {
1368 return res;
1369 }
11751370 }
11761371 }
11771372 if (pn53x_current_target_new(pnd, &nttmp) == NULL) {
11911386 const uint8_t *pbtInitData, const size_t szInitData,
11921387 nfc_target *pnt)
11931388 {
1194 return pn53x_initiator_select_passive_target_ext(pnd, nm, pbtInitData, szInitData, pnt, 0);
1389 return pn53x_initiator_select_passive_target_ext(pnd, nm, pbtInitData, szInitData, pnt, 300);
11951390 }
11961391
11971392 int
12211416 szTargetTypes++;
12221417 }
12231418 nfc_target ntTargets[2];
1419 memset(ntTargets, 0x00, sizeof(nfc_target) * 2);
1420
12241421 if ((res = pn53x_InAutoPoll(pnd, apttTargetTypes, szTargetTypes, uiPollNr, uiPeriod, ntTargets, 0)) < 0)
12251422 return res;
12261423 switch (res) {
1424 case 0:
1425 return pnd->last_error = NFC_SUCCESS;
1426 break;
12271427 case 1:
12281428 *pnt = ntTargets[0];
12291429 if (pn53x_current_target_new(pnd, pnt) == NULL) {
12301430 return pnd->last_error = NFC_ESOFT;
12311431 }
12321432 return res;
1233 break;
12341433 case 2:
12351434 *pnt = ntTargets[1]; // We keep the selected one
12361435 if (pn53x_current_target_new(pnd, pnt) == NULL) {
12371436 return pnd->last_error = NFC_ESOFT;
12381437 }
12391438 return res;
1240 break;
12411439 default:
12421440 return NFC_ECHIP;
1243 break;
12441441 }
12451442 } else {
12461443 bool bInfiniteSelect = pnd->bInfiniteSelect;
13021499 case NBR_847:
13031500 case NBR_UNDEFINED:
13041501 return NFC_EINVARG;
1305 break;
13061502 }
13071503
13081504 pn53x_current_target_free(pnd);
13331529 uint8_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN] = { InCommunicateThru };
13341530
13351531 // Check if we should prepare the parity bits ourself
1336 if (!pnd->bPar) {
1532 if ((!pnd->bPar) && (szTxBits > 0)) {
13371533 // Convert data with parity to a frame
13381534 if ((res = pn53x_wrap_frame(pbtTx, szTxBits, pbtTxPar, abtCmd + 1)) < 0)
13391535 return res;
14651661
14661662 static uint32_t __pn53x_get_timer(struct nfc_device *pnd, const uint8_t last_cmd_byte)
14671663 {
1468 uint8_t parity;
14691664 uint8_t counter_hi, counter_lo;
1470 uint16_t counter, u16cycles;
1665 uint16_t counter;
14711666 uint32_t u32cycles;
14721667 size_t off = 0;
14731668 if (CHIP_DATA(pnd)->type == PN533) {
14951690 // counter saturated
14961691 u32cycles = 0xFFFFFFFF;
14971692 } else {
1693 uint8_t parity;
1694 uint16_t u16cycles;
14981695 u16cycles = 0xFFFF - counter;
14991696 u32cycles = u16cycles;
15001697 u32cycles *= (CHIP_DATA(pnd)->timer_prescaler * 2 + 1);
17321929 if (pnd->bCrc) {
17331930 // We've to compute CRC ourselves to know last byte actually sent
17341931 uint8_t *pbtTxRaw;
1735 pbtTxRaw = (uint8_t *) malloc(szTx + 2);
1932 pbtTxRaw = (uint8_t *) calloc(szTx + 2, 1);
17361933 if (!pbtTxRaw)
17371934 return NFC_ESOFT;
17381935 memcpy(pbtTxRaw, pbtTx, szTx);
18432040 }
18442041 }
18452042 return ret;
2043 }
2044
2045 static int pn53x_ISO14443A_Barcode_is_present(struct nfc_device *pnd)
2046 {
2047 int ret;
2048 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Barcode");
2049
2050 // We turn RF field off first for a better detection rate but this doesn't work well with ASK LoGO
2051 if ((! CHIP_DATA(pnd)->progressive_field) && (ret = nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false)) < 0) {
2052 return ret;
2053 }
2054 if ((ret = nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false)) < 0)
2055 return ret;
2056 if ((ret = nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, false)) < 0)
2057 return ret;
2058
2059 int failures = 0;
2060 while (failures < 3) {
2061 if ((! CHIP_DATA(pnd)->progressive_field) && (ret = nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false)) < 0) {
2062 return ret;
2063 }
2064 uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
2065 uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
2066 if ((ret = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 1) {
2067 failures++;
2068 } else {
2069 nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);
2070 nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true);
2071 return NFC_SUCCESS;
2072 }
2073 }
2074 nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);
2075 nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true);
2076 return NFC_ETGRELEASED;
18462077 }
18472078
18482079 static int pn53x_ISO14443A_MFUL_is_present(struct nfc_device *pnd)
20152246 return ret;
20162247 }
20172248
2249 static int pn53x_ISO14443B_ICLASS_is_present(struct nfc_device *pnd)
2250 {
2251 int timeout = 300;
2252 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B iClass");
2253 pn53x_initiator_init_iclass_modulation(pnd);
2254 //
2255 // Some work to do before getting the UID...
2256 // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response
2257 uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL
2258 uint8_t abtAnticol[11];
2259 if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout) < 0) {
2260 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all");
2261 }
2262 // do select - returned anticol contains 'handle' for tag if present
2263 abtReqt[0] = 0x0c; // iClass SELECT
2264 abtAnticol[0] = 0x81; // iClass ANTICOL
2265 if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout) < 0) {
2266 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol");
2267 return NFC_ETGRELEASED;;
2268 }
2269 return NFC_SUCCESS;
2270 }
2271
20182272 static int pn53x_ISO14443B_CT_is_present(struct nfc_device *pnd)
20192273 {
20202274 int ret;
20552309 }
20562310
20572311 // Ping target
2058 int ret;
2312 int ret = NFC_EDEVNOTSUPP;
20592313 switch (CHIP_DATA(pnd)->current_target->nm.nmt) {
20602314 case NMT_ISO14443A:
20612315 if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x20) {
20802334 case NMT_JEWEL:
20812335 ret = pn53x_ISO14443A_Jewel_is_present(pnd);
20822336 break;
2337 case NMT_BARCODE:
2338 ret = pn53x_ISO14443A_Barcode_is_present(pnd);
2339 break;
20832340 case NMT_ISO14443B:
20842341 ret = pn53x_ISO14443B_4_is_present(pnd);
20852342 break;
20922349 case NMT_ISO14443B2CT:
20932350 ret = pn53x_ISO14443B_CT_is_present(pnd);
20942351 break;
2095 default:
2096 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type not supported");
2097 ret = NFC_EDEVNOTSUPP;
2352 case NMT_ISO14443BICLASS:
2353 ret = pn53x_ISO14443B_ICLASS_is_present(pnd);
20982354 break;
20992355 }
21002356 if (ret == NFC_ETGRELEASED)
21462402 case NMT_ISO14443BI:
21472403 case NMT_ISO14443B2SR:
21482404 case NMT_ISO14443B2CT:
2405 case NMT_ISO14443BICLASS:
21492406 case NMT_JEWEL:
2407 case NMT_BARCODE:
21502408 pnd->last_error = NFC_EDEVNOTSUPP;
21512409 return pnd->last_error;
2152 break;
21532410 }
21542411
21552412 // Let the PN53X be activated by the RF level detector from power down mode
22482505 case NMT_ISO14443BI:
22492506 case NMT_ISO14443B2SR:
22502507 case NMT_ISO14443B2CT:
2508 case NMT_ISO14443BICLASS:
22512509 case NMT_JEWEL:
2510 case NMT_BARCODE:
22522511 pnd->last_error = NFC_EDEVNOTSUPP;
22532512 return pnd->last_error;
2254 break;
22552513 }
22562514
22572515 bool targetActivated = false;
23962654 return pnd->last_error;
23972655 }
23982656 }
2399 // NO BREAK
2657 abtCmd[0] = TgGetInitiatorCommand;
2658 break;
24002659 case NMT_JEWEL:
2660 case NMT_BARCODE:
24012661 case NMT_ISO14443B:
24022662 case NMT_ISO14443BI:
24032663 case NMT_ISO14443B2SR:
24042664 case NMT_ISO14443B2CT:
2665 case NMT_ISO14443BICLASS:
24052666 case NMT_FELICA:
24062667 abtCmd[0] = TgGetInitiatorCommand;
24072668 break;
25012762 return pnd->last_error;
25022763 }
25032764 }
2504 // NO BREAK
2765 abtCmd[0] = TgResponseToInitiator;
2766 break;
25052767 case NMT_JEWEL:
2768 case NMT_BARCODE:
25062769 case NMT_ISO14443B:
25072770 case NMT_ISO14443BI:
25082771 case NMT_ISO14443B2SR:
25092772 case NMT_ISO14443B2CT:
2773 case NMT_ISO14443BICLASS:
25102774 case NMT_FELICA:
25112775 abtCmd[0] = TgResponseToInitiator;
25122776 break;
27192983 }
27202984 break;
27212985 case PM_JEWEL_106:
2986 case PM_BARCODE_106:
27222987 if (CHIP_DATA(pnd)->type == PN531) {
27232988 // These modulations are not supported by pn531
27242989 pnd->last_error = NFC_EDEVNOTSUPP;
29103175 case NBR_UNDEFINED:
29113176 pnd->last_error = NFC_EINVARG;
29123177 return pnd->last_error;
2913 break;
29143178 }
29153179
29163180 if (pbtNFCID3i) {
31273391 switch (nm.nmt) {
31283392 case NMT_ISO14443A:
31293393 return PM_ISO14443A_106;
3130 break;
31313394
31323395 case NMT_ISO14443B:
3396 case NMT_ISO14443BICLASS:
31333397 switch (nm.nbr) {
31343398 case NBR_106:
31353399 return PM_ISO14443B_106;
3136 break;
31373400 case NBR_212:
31383401 return PM_ISO14443B_212;
3139 break;
31403402 case NBR_424:
31413403 return PM_ISO14443B_424;
3142 break;
31433404 case NBR_847:
31443405 return PM_ISO14443B_847;
3145 break;
31463406 case NBR_UNDEFINED:
31473407 // Nothing to do...
31483408 break;
31513411
31523412 case NMT_JEWEL:
31533413 return PM_JEWEL_106;
3154 break;
3414
3415 case NMT_BARCODE:
3416 return PM_BARCODE_106;
31553417
31563418 case NMT_FELICA:
31573419 switch (nm.nbr) {
31583420 case NBR_212:
31593421 return PM_FELICA_212;
3160 break;
31613422 case NBR_424:
31623423 return PM_FELICA_424;
3163 break;
31643424 case NBR_106:
31653425 case NBR_847:
31663426 case NBR_UNDEFINED:
31933453 case PTT_MIFARE:
31943454 case PTT_ISO14443_4A_106:
31953455 return (const nfc_modulation) { .nmt = NMT_ISO14443A, .nbr = NBR_106 };
3196 break;
31973456
31983457 case PTT_ISO14443_4B_106:
31993458 case PTT_ISO14443_4B_TCL_106:
32003459 return (const nfc_modulation) { .nmt = NMT_ISO14443B, .nbr = NBR_106 };
3201 break;
32023460
32033461 case PTT_JEWEL_106:
32043462 return (const nfc_modulation) { .nmt = NMT_JEWEL, .nbr = NBR_106 };
3205 break;
32063463
32073464 case PTT_FELICA_212:
32083465 return (const nfc_modulation) { .nmt = NMT_FELICA, .nbr = NBR_212 };
3209 break;
3466
32103467 case PTT_FELICA_424:
32113468 return (const nfc_modulation) { .nmt = NMT_FELICA, .nbr = NBR_424 };
3212 break;
32133469
32143470 case PTT_DEP_PASSIVE_106:
32153471 case PTT_DEP_ACTIVE_106:
32163472 return (const nfc_modulation) { .nmt = NMT_DEP, .nbr = NBR_106 };
3217 break;
3473
32183474 case PTT_DEP_PASSIVE_212:
32193475 case PTT_DEP_ACTIVE_212:
32203476 return (const nfc_modulation) { .nmt = NMT_DEP, .nbr = NBR_212 };
3221 break;
3477
32223478 case PTT_DEP_PASSIVE_424:
32233479 case PTT_DEP_ACTIVE_424:
32243480 return (const nfc_modulation) { .nmt = NMT_DEP, .nbr = NBR_424 };
3225 break;
32263481 }
32273482 // We should never be here, this line silent compilation warning
32283483 return (const nfc_modulation) { .nmt = NMT_ISO14443A, .nbr = NBR_106 };
32343489 switch (nm.nmt) {
32353490 case NMT_ISO14443A:
32363491 return PTT_MIFARE;
3237 // return PTT_ISO14443_4A_106;
3238 break;
3492 // return PTT_ISO14443_4A_106;
32393493
32403494 case NMT_ISO14443B:
3495 case NMT_ISO14443BICLASS:
32413496 switch (nm.nbr) {
32423497 case NBR_106:
32433498 return PTT_ISO14443_4B_106;
3244 break;
3499
32453500 case NBR_UNDEFINED:
32463501 case NBR_212:
32473502 case NBR_424:
32533508
32543509 case NMT_JEWEL:
32553510 return PTT_JEWEL_106;
3256 break;
32573511
32583512 case NMT_FELICA:
32593513 switch (nm.nbr) {
32603514 case NBR_212:
32613515 return PTT_FELICA_212;
3262 break;
3516
32633517 case NBR_424:
32643518 return PTT_FELICA_424;
3265 break;
3519
32663520 case NBR_UNDEFINED:
32673521 case NBR_106:
32683522 case NBR_847:
32743528 case NMT_ISO14443BI:
32753529 case NMT_ISO14443B2SR:
32763530 case NMT_ISO14443B2CT:
3531 case NMT_BARCODE:
32773532 case NMT_DEP:
32783533 // Nothing to do...
32793534 break;
32983553 }
32993554
33003555 int
3301 pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
3556 pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
33023557 {
33033558 switch (nmt) {
33043559 case NMT_FELICA:
33053560 *supported_br = (nfc_baud_rate *)pn53x_felica_supported_baud_rates;
33063561 break;
3307 case NMT_ISO14443A:
3308 *supported_br = (nfc_baud_rate *)pn53x_iso14443a_supported_baud_rates;
3309 break;
3310 case NMT_ISO14443B:
3311 case NMT_ISO14443BI:
3312 case NMT_ISO14443B2SR:
3313 case NMT_ISO14443B2CT: {
3562 case NMT_ISO14443A: {
3563 if ((CHIP_DATA(pnd)->type != PN533) || (mode == N_TARGET)) {
3564 *supported_br = (nfc_baud_rate *)pn532_iso14443a_supported_baud_rates;
3565 } else {
3566 *supported_br = (nfc_baud_rate *)pn533_iso14443a_supported_baud_rates;
3567 }
3568 }
3569 break;
3570 case NMT_ISO14443B: {
33143571 if ((CHIP_DATA(pnd)->type != PN533)) {
33153572 *supported_br = (nfc_baud_rate *)pn532_iso14443b_supported_baud_rates;
33163573 } else {
33183575 }
33193576 }
33203577 break;
3578 case NMT_ISO14443BI:
3579 case NMT_ISO14443B2SR:
3580 case NMT_ISO14443B2CT:
3581 case NMT_ISO14443BICLASS:
3582 *supported_br = (nfc_baud_rate *)pn532_iso14443b_supported_baud_rates;
3583 break;
33213584 case NMT_JEWEL:
33223585 *supported_br = (nfc_baud_rate *)pn53x_jewel_supported_baud_rates;
3586 break;
3587 case NMT_BARCODE:
3588 *supported_br = (nfc_baud_rate *)pn53x_barcode_supported_baud_rates;
33233589 break;
33243590 case NMT_DEP:
33253591 *supported_br = (nfc_baud_rate *)pn53x_dep_supported_baud_rates;
34333699 free(*pbuf);
34343700 return res;
34353701 }
3436
34373702 for (int i = 0; nmt[i]; i++) {
34383703 if ((res = snprintf(buf, buflen, "%s%s (", (i == 0) ? "" : ", ", str_nfc_modulation_type(nmt[i]))) < 0) {
34393704 free(*pbuf);
34463711 }
34473712 buflen -= res;
34483713 const nfc_baud_rate *nbr;
3449 if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) {
3714 if ((res = nfc_device_get_supported_baud_rate_target_mode(pnd, nmt[i], &nbr)) < 0) {
34503715 free(*pbuf);
34513716 return res;
34523717 }
35753840
35763841 CHIP_DATA(pnd)->supported_modulation_as_target = NULL;
35773842
3843 // Set default progressive field flag
3844 CHIP_DATA(pnd)->progressive_field = false;
3845
35783846 return pnd->chip_data;
35793847 }
35803848
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
209210 /** Supported modulation type */
210211 nfc_modulation_type *supported_modulation_as_initiator;
211212 nfc_modulation_type *supported_modulation_as_target;
213 bool progressive_field;
212214 };
213215
214216 #define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data))
230232 PM_ISO14443B_106 = 0x03,
231233 /** Jewel Topaz (Innovision Research & Development) (Not supported by PN531) */
232234 PM_JEWEL_106 = 0x04,
235 /** Thinfilm NFC Barcode (Not supported by PN531) */
236 PM_BARCODE_106 = 0x05,
233237 /** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 (Not supported by PN531 nor PN532) */
234238 PM_ISO14443B_212 = 0x06,
235239 /** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 (Not supported by PN531 nor PN532) */
318322
319323 // NFC device as Initiator functions
320324 int pn53x_initiator_init(struct nfc_device *pnd);
325 void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd);
321326 int pn532_initiator_init_secure_element(struct nfc_device *pnd);
322327 int pn53x_initiator_select_passive_target(struct nfc_device *pnd,
323328 const nfc_modulation nm,
391396 int pn53x_check_error_frame(struct nfc_device *pnd, const uint8_t *pbtRxFrame, const size_t szRxFrameLen);
392397 int pn53x_build_frame(uint8_t *pbtFrame, size_t *pszFrame, const uint8_t *pbtData, const size_t szData);
393398 int pn53x_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt);
394 int pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
399 int pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
395400 int pn53x_get_information_about(nfc_device *pnd, char **pbuf);
396401
397402 void *pn53x_data_new(struct nfc_device *pnd, const struct pn53x_io *io);
3232 #ifdef CONFFILES
3333 #include <stdio.h>
3434 #include <stdlib.h>
35 #include <ctype.h>
3536 #include <dirent.h>
3637 #include <string.h>
37 #include <regex.h>
3838 #include <sys/stat.h>
3939
4040 #include <nfc/nfc.h>
5555 #define LIBNFC_CONFFILE LIBNFC_SYSCONFDIR"/libnfc.conf"
5656 #define LIBNFC_DEVICECONFDIR LIBNFC_SYSCONFDIR"/devices.d"
5757
58 static bool
59 conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const char *key, const char *value), void *data)
58 static int
59 escaped_value(const char line[BUFSIZ], int i, char **value)
60 {
61 if (line[i] != '"')
62 goto FAIL;
63 i++;
64 if (line[i] == 0 || line[i] == '\n')
65 goto FAIL;
66 int c = 0;
67 while (line[i] && line[i] != '"') {
68 i++;
69 c++;
70 }
71 if (line[i] != '"')
72 goto FAIL;
73 *value = malloc(c + 1);
74 if (!*value)
75 goto FAIL;
76 memset(*value, 0, c + 1);
77 memcpy(*value, &line[i - c], c);
78 i++;
79 while (line[i] && isspace(line[i]))
80 i++;
81 if (line[i] != 0 && line[i] != '\n')
82 goto FAIL;
83 return 0;
84
85 FAIL:
86 free(*value);
87 *value = NULL;
88 return -1;
89 }
90
91 static int
92 non_escaped_value(const char line[BUFSIZ], int i, char **value)
93 {
94 int c = 0;
95 while (line[i] && !isspace(line[i])) {
96 i++;
97 c++;
98 }
99 *value = malloc(c + 1);
100 if (!*value)
101 goto FAIL;
102 memset(*value, 0, c + 1);
103 memcpy(*value, &line[i - c], c);
104 i++;
105 while (line[i] && isspace(line[i]))
106 i++;
107 if (line[i] != 0)
108 goto FAIL;
109 return 0;
110
111 FAIL:
112 free(*value);
113 *value = NULL;
114 return -1;
115 }
116
117 static int
118 parse_line(const char line[BUFSIZ], char **key, char **value)
119 {
120 *key = NULL;
121 *value = NULL;
122 int i = 0;
123 int c = 0;
124
125 // optional initial spaces
126 while (isspace(line[i]))
127 i++;
128 if (line[i] == 0 || line[i] == '\n')
129 return -1;
130
131 // key
132 while (isalnum(line[i]) || line[i] == '_' || line[i] == '.') {
133 i++;
134 c++;
135 }
136 if (c == 0 || line[i] == 0 || line[i] == '\n') // key is empty
137 return -1;
138 *key = malloc(c + 1);
139 if (!*key)
140 return -1;
141 memset(*key, 0, c + 1);
142 memcpy(*key, &line[i - c], c);
143
144 // space before '='
145 while (isspace(line[i]))
146 i++;
147 if (line[i] != '=')
148 return -1;
149 i++;
150 if (line[i] == 0 || line[i] == '\n')
151 return -1;
152 // space after '='
153 while (isspace(line[i]))
154 i++;
155 if (line[i] == 0 || line[i] == '\n')
156 return -1;
157 if (escaped_value(line, i, value) == 0)
158 return 0;
159 else if (non_escaped_value(line, i, value) == 0)
160 return 0;
161
162 // Extracting key or value failed
163 free(*key);
164 *key = NULL;
165 free(*value);
166 *value = NULL;
167 return -1;
168 }
169
170 static void
171 conf_parse_file(const char *filename,
172 void (*conf_keyvalue)(void *data, const char *key, const char *value),
173 void *data)
60174 {
61175 FILE *f = fopen(filename, "r");
62176 if (!f) {
63177 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Unable to open file: %s", filename);
64 return false;
178 return;
65179 }
66180 char line[BUFSIZ];
67 const char *str_regex = "^[[:space:]]*([[:alnum:]_.]+)[[:space:]]*=[[:space:]]*(\"(.+)\"|([^[:space:]]+))[[:space:]]*$";
68 regex_t preg;
69 if (regcomp(&preg, str_regex, REG_EXTENDED | REG_NOTEOL) != 0) {
70 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Regular expression used for configuration file parsing is not valid.");
71 fclose(f);
72 return false;
73 }
74 size_t nmatch = preg.re_nsub + 1;
75 regmatch_t *pmatch = malloc(sizeof(*pmatch) * nmatch);
76 if (!pmatch) {
77 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Not enough memory: malloc failed.");
78 regfree(&preg);
79 fclose(f);
80 return false;
81 }
82181
83182 int lineno = 0;
84183 while (fgets(line, BUFSIZ, f) != NULL) {
88187 case '\n':
89188 break;
90189 default: {
91 int match;
92 if ((match = regexec(&preg, line, nmatch, pmatch, 0)) == 0) {
93 const size_t key_size = pmatch[1].rm_eo - pmatch[1].rm_so;
94 const off_t value_pmatch = pmatch[3].rm_eo != -1 ? 3 : 4;
95 const size_t value_size = pmatch[value_pmatch].rm_eo - pmatch[value_pmatch].rm_so;
96 char key[key_size + 1];
97 char value[value_size + 1];
98 strncpy(key, line + (pmatch[1].rm_so), key_size);
99 key[key_size] = '\0';
100 strncpy(value, line + (pmatch[value_pmatch].rm_so), value_size);
101 value[value_size] = '\0';
190 char *key;
191 char *value;
192 if (parse_line(line, &key, &value) == 0) {
102193 conf_keyvalue(data, key, value);
194 free(key);
195 free(value);
103196 } else {
104197 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line);
105198 }
106199 }
107 break;
108 }
109 }
110
111 free(pmatch);
112 regfree(&preg);
200 }
201 }
113202 fclose(f);
114 return false;
203 return;
115204 }
116205
117206 static void
176265 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Unable to open directory: %s", dirname);
177266 } else {
178267 struct dirent *de;
179 #ifdef WIN32
180268 while ((de = readdir(d)) != NULL) {
181 #else
182 struct dirent entry;
183 struct dirent *result;
184 while ((readdir_r(d, &entry, &result) == 0) && (result != NULL)) {
185 de = &entry;
186 #endif
269 // FIXME add a way to sort devices
187270 if (de->d_name[0] != '.') {
188271 const size_t filename_len = strlen(de->d_name);
189272 const size_t extension_len = strlen(".conf");
55 libnfcdrivers_la_SOURCES =
66 libnfcdrivers_la_CFLAGS = @DRIVERS_CFLAGS@ -I$(top_srcdir)/libnfc -I$(top_srcdir)/libnfc/buses
77 libnfcdrivers_la_LIBADD =
8
9 if DRIVER_PCSC_ENABLED
10 libnfcdrivers_la_SOURCES += pcsc.c pcsc.h
11 endif
812
913 if DRIVER_ACR122_PCSC_ENABLED
1014 libnfcdrivers_la_SOURCES += acr122_pcsc.c acr122_pcsc.h
3842 libnfcdrivers_la_SOURCES += pn532_i2c.c pn532_i2c.h
3943 endif
4044
45 if DRIVER_PN71XX_ENABLED
46 libnfcdrivers_la_LIBADD += @LIBNFC_NCI_LIBS@
47 libnfcdrivers_la_SOURCES += pn71xx.c pn71xx.h
48 endif
49
4150 if PCSC_ENABLED
4251 libnfcdrivers_la_CFLAGS += @libpcsclite_CFLAGS@
4352 libnfcdrivers_la_LIBADD += @libpcsclite_LIBS@
5858 # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500)
5959 #elif defined(__APPLE__)
6060 # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2))
61 #elif defined (__FreeBSD__) || defined (__OpenBSD__)
61 #elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__)
6262 # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2))
6363 #elif defined (__linux__)
6464 # include <reader.h>
9292 // Prototypes
9393 char *acr122_pcsc_firmware(nfc_device *pnd);
9494
95 const char *supported_devices[] = {
95 static const char *supported_devices[] = {
9696 "ACS ACR122", // ACR122U & Touchatag, last version
9797 "ACS ACR 38U-CCID", // Touchatag, early version
9898 "ACS ACR38U-CCID", // Touchatag, early version, under MacOSX
399399 {
400400 // FIXME: timeout is not handled
401401 (void) timeout;
402
403402 int len;
404 uint8_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 };
405403
406404 if (DRIVER_DATA(pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_T0) {
407405 /*
408406 * Retrieve the PN532 response.
409407 */
410408 DWORD dwRxLen = sizeof(DRIVER_DATA(pnd)->abtRx);
409 uint8_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 };
411410 abtRxCmd[4] = DRIVER_DATA(pnd)->abtRx[1];
412411 if (SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), abtRxCmd, sizeof(abtRxCmd), NULL, DRIVER_DATA(pnd)->abtRx, &dwRxLen) != SCARD_S_SUCCESS) {
413412 pnd->last_error = NFC_EIO;
261261 const struct acr122_usb_supported_device acr122_usb_supported_devices[] = {
262262 { 0x072F, 0x2200, "ACS ACR122" },
263263 { 0x072F, 0x90CC, "Touchatag" },
264 { 0x072F, 0x2214, "ACS ACR1222" },
264265 };
265266
266267 // Find transfer endpoints for bulk transfers
329330 // acr122_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice));
330331 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s Name %s", bus->dirname, dev->filename, acr122_usb_supported_devices[n].name);
331332 usb_close(udev);
332 snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename);
333 if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) {
334 // truncation occurred, skipping that one
335 continue;
336 }
333337 device_found++;
334338 // Test if we reach the maximum "wanted" devices
335339 if (device_found == connstrings_len) {
425429 goto free_mem;
426430 }
427431
428 res = usb_set_altinterface(data.pudh, 0);
429 if (res < 0) {
430 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", _usb_strerror(res));
431 usb_close(data.pudh);
432 // we failed to use the specified device
433 goto free_mem;
432 // Check if there are more than 0 alternative interfaces and claim the first one
433 if (dev->config->interface->altsetting->bAlternateSetting > 0) {
434 res = usb_set_altinterface(data.pudh, 0);
435 if (res < 0) {
436 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", _usb_strerror(res));
437 usb_close(data.pudh);
438 // we failed to use the specified device
439 goto free_mem;
440 }
434441 }
435442
436443 // Allocate memory for the device info and specification, fill it and return the info
421421
422422 while ((acPort = acPorts[iDevice++])) {
423423 sp = uart_open(acPort);
424 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ACR122S device on serial port: %s at %d bauds.", acPort, ACR122S_DEFAULT_SPEED);
424 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ACR122S device on serial port: %s at %d baud.", acPort, ACR122S_DEFAULT_SPEED);
425425
426426 if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
427427 // We need to flush input to be sure first reply does not comes from older byte transceive
561561 }
562562
563563 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG,
564 "Attempt to connect to: %s at %d bauds.", ndd.port, ndd.speed);
564 "Attempt to connect to: %s at %d baud.", ndd.port, ndd.speed);
565565
566566 sp = uart_open(ndd.port);
567567 if (sp == INVALID_SERIAL_PORT) {
9090
9191 // ARYGON frames
9292 static const uint8_t arygon_error_none[] = "FF000000\x0d\x0a";
93 static const uint8_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
9493 static const uint8_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
9594
9695 // Prototypes
108107
109108 while ((acPort = acPorts[iDevice++])) {
110109 sp = uart_open(acPort);
111 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ARYGON device on serial port: %s at %d bauds.", acPort, ARYGON_DEFAULT_SPEED);
110 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ARYGON device on serial port: %s at %d baud.", acPort, ARYGON_DEFAULT_SPEED);
112111
113112 if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
114113 // We need to flush input to be sure first reply does not comes from older byte transceive
252251 serial_port sp;
253252 nfc_device *pnd = NULL;
254253
255 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed);
254 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d baud.", ndd.port, ndd.speed);
256255 sp = uart_open(ndd.port);
257256
258257 if (sp == INVALID_SERIAL_PORT)
0 /*-
1 * Free/Libre Near Field Communication (NFC) library
2 *
3 * Libnfc historical contributors:
4 * Copyright (C) 2019 Frank Morgner
5 * See AUTHORS file for a more comprehensive list of contributors.
6 * Additional contributors of this file:
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
20 */
21
22 /**
23 * @file pcsc.c
24 * @brief Driver for non-ACR122 devices behind PC/SC
25 */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif // HAVE_CONFIG_H
30
31 #include <inttypes.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <string.h>
36
37 #include <nfc/nfc.h>
38
39 #include "drivers/pcsc.h"
40 #include "nfc-internal.h"
41
42 // Bus
43 #ifdef __APPLE__
44 #include <PCSC/winscard.h>
45 #include <PCSC/wintypes.h>
46 // define from pcsclite for apple
47 #define SCARD_AUTOALLOCATE (DWORD)(-1)
48
49 #define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
50
51 #define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */
52 #define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */
53 #define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */
54 #define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */
55 #define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */
56 #define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */
57 #define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */
58 #define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */
59 #define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */
60 #define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */
61
62 #define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) /**< Vendor name. */
63 #define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) /**< Vendor-supplied interface device type (model designation of reader). */
64 #define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) /**< Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb where MM = major version, mm = minor version, and bbbb = build number). */
65 #define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) /**< Vendor-supplied interface device serial number. */
66 #define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) /**< Single byte indicating smart card type */
67 #else
68 #ifndef _Win32
69 #include <reader.h>
70 #endif
71 #include <winscard.h>
72 #endif
73
74 #define PCSC_DRIVER_NAME "pcsc"
75
76 #include <nfc/nfc.h>
77
78 #define LOG_GROUP NFC_LOG_GROUP_DRIVER
79 #define LOG_CATEGORY "libnfc.driver.pcsc"
80
81 static const char *supported_devices[] = {
82 "ACS ACR122", // ACR122U & Touchatag, last version
83 "ACS ACR 38U-CCID", // Touchatag, early version
84 "ACS ACR38U-CCID", // Touchatag, early version, under MacOSX
85 "ACS AET65", // Touchatag using CCID driver version >= 1.4.6
86 " CCID USB", // ??
87 NULL
88 };
89
90 struct pcsc_data {
91 SCARDHANDLE hCard;
92 SCARD_IO_REQUEST ioCard;
93 DWORD dwShareMode;
94 DWORD last_error;
95 };
96
97 #define DRIVER_DATA(pnd) ((struct pcsc_data*)(pnd->driver_data))
98
99 static SCARDCONTEXT _SCardContext;
100 static int _iSCardContextRefCount = 0;
101
102 const nfc_baud_rate pcsc_supported_brs[] = {NBR_106, NBR_424, 0};
103 const nfc_modulation_type pcsc_supported_mts[] = {NMT_ISO14443A, NMT_ISO14443B, 0};
104
105 static SCARDCONTEXT *
106 pcsc_get_scardcontext(void)
107 {
108 if (_iSCardContextRefCount == 0) {
109 if (SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &_SCardContext) != SCARD_S_SUCCESS)
110 return NULL;
111 }
112 _iSCardContextRefCount++;
113
114 return &_SCardContext;
115 }
116
117 static void
118 pcsc_free_scardcontext(void)
119 {
120 if (_iSCardContextRefCount) {
121 _iSCardContextRefCount--;
122 if (!_iSCardContextRefCount) {
123 SCardReleaseContext(_SCardContext);
124 }
125 }
126 }
127
128 #define ICC_TYPE_UNKNOWN 0
129 #define ICC_TYPE_14443A 5
130 #define ICC_TYPE_14443B 6
131
132 bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd);
133
134 static int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len, uint8_t *rx, size_t *rx_len)
135 {
136 struct pcsc_data *data = pnd->driver_data;
137 DWORD dw_rx_len = *rx_len;
138 //in libfreefare, tx_len = 1, and it leads to 0x80100008 error, with PC/SC reader, the input tx_len at least two bytes for the SW value
139 //so if found the reader is Feitian reader, we set to 2
140 if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) {
141 dw_rx_len = 2;
142 }
143
144 LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len);
145
146 data->last_error = SCardTransmit(data->hCard, &data->ioCard, tx, tx_len,
147 NULL, rx, &dw_rx_len);
148 if (data->last_error != SCARD_S_SUCCESS) {
149 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed");
150 return NFC_EIO;
151 }
152 *rx_len = dw_rx_len;
153
154 LOG_HEX(NFC_LOG_GROUP_COM, "RX", rx, *rx_len);
155
156 return NFC_SUCCESS;
157 }
158
159 static int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t *atr, size_t *atr_len)
160 {
161 struct pcsc_data *data = pnd->driver_data;
162 DWORD dw_atr_len = *atr_len, reader_len, state, protocol;
163
164 data->last_error = SCardStatus(data->hCard, NULL, &reader_len, &state, &protocol, atr, &dw_atr_len);
165 if (data->last_error != SCARD_S_SUCCESS
166 && data->last_error != SCARD_W_RESET_CARD) {
167 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Get status failed");
168 return NFC_EIO;
169 }
170
171 *target_present = state & SCARD_PRESENT;
172 *atr_len = dw_atr_len;
173
174 return NFC_SUCCESS;
175 }
176
177 static int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protocol, DWORD disposition)
178 {
179 struct pcsc_data *data = pnd->driver_data;
180
181 data->last_error = SCardReconnect(data->hCard, share_mode, protocol, disposition, &data->ioCard.dwProtocol);
182 if (data->last_error != SCARD_S_SUCCESS
183 && data->last_error != SCARD_W_RESET_CARD) {
184 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reconnect failed");
185 return NFC_EIO;
186 }
187
188 data->dwShareMode = share_mode;
189
190 return NFC_SUCCESS;
191 }
192
193 static uint8_t pcsc_get_icc_type(const struct nfc_device *pnd)
194 {
195 struct pcsc_data *data = pnd->driver_data;
196 uint8_t it = 0;
197 DWORD dwItLen = sizeof it;
198 data->last_error = SCardGetAttrib(data->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen);
199 return it;
200 }
201
202 static bool is_pcsc_reader_vendor(const struct nfc_device *pnd, const char *target_vendor_name)
203 {
204 bool isTarget = false;
205 if (pnd == NULL || strlen(pnd->name) == 0) {
206 return isTarget;
207 }
208
209 return isTarget = (strstr(pnd->name, target_vendor_name)) ? true : false;
210 }
211
212 bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd)
213 {
214 return is_pcsc_reader_vendor(pnd, "Feitian") || is_pcsc_reader_vendor(pnd, "FeiTian") || is_pcsc_reader_vendor(pnd, "feitian") || is_pcsc_reader_vendor(pnd, "FEITIAN");
215 }
216
217 //get atqa by send apdu
218 static int pcsc_get_atqa(struct nfc_device *pnd, uint8_t *atqa, size_t atqa_len)
219 {
220 const uint8_t get_data[] = {0xFF, 0xCA, 0x03, 0x00, 0x00};
221 uint8_t resp[256 + 2];
222 size_t resp_len = sizeof resp;
223
224 pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len);
225 if (pnd->last_error != NFC_SUCCESS)
226 return pnd->last_error;
227
228 if (resp_len < 2) {
229 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATQA");
230 pnd->last_error = NFC_EDEVNOTSUPP;
231 return pnd->last_error;
232 }
233 if (atqa_len < resp_len - 2) {
234 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ATQA length is wrong");
235 pnd->last_error = NFC_ESOFT;
236 return pnd->last_error;
237 }
238
239 memcpy(atqa, resp, resp_len - 2);
240 return resp_len - 2;
241 }
242
243 //get ats by send apdu
244 static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
245 {
246 const uint8_t get_data[] = {0xFF, 0xCA, 0x01, 0x00, 0x00};
247 uint8_t resp[256 + 2];
248 size_t resp_len = sizeof resp;
249
250 pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len);
251 if (pnd->last_error != NFC_SUCCESS)
252 return pnd->last_error;
253
254 if (resp_len < 2) {
255 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS");
256 pnd->last_error = NFC_EDEVNOTSUPP;
257 return pnd->last_error;
258 }
259 if (ats_len < resp_len - 2) {
260 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ATS length is wrong");
261 pnd->last_error = NFC_ESOFT;
262 return pnd->last_error;
263 }
264
265 //memcpy(ats, resp + 1, resp_len - 2 - 1);
266 memcpy(ats, resp + 1, resp[0] - 1);
267 return resp_len - 2 - 1;
268 }
269
270 //get sak by send apdu
271 static int pcsc_get_sak(struct nfc_device *pnd, uint8_t *sak, size_t sak_len)
272 {
273 const uint8_t get_data[] = {0xFF, 0xCA, 0x02, 0x00, 0x00};
274 uint8_t resp[256 + 2];
275 size_t resp_len = sizeof resp;
276
277 pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len);
278 if (pnd->last_error != NFC_SUCCESS)
279 return pnd->last_error;
280
281 if (resp_len < 2) {
282 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for SAK");
283 pnd->last_error = NFC_EDEVNOTSUPP;
284 return pnd->last_error;
285 }
286 if (sak_len < resp_len - 2) {
287 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SAK length is wrong");
288 pnd->last_error = NFC_ESOFT;
289 return pnd->last_error;
290 }
291
292 memcpy(sak, resp, resp_len - 2);
293 return resp_len - 2;
294 }
295
296 static int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len)
297 {
298 const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
299 uint8_t resp[256 + 2];
300 size_t resp_len = sizeof resp;
301
302 pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len);
303 if (pnd->last_error != NFC_SUCCESS)
304 return pnd->last_error;
305
306 if (resp_len < 2) {
307 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for UID");
308 pnd->last_error = NFC_EDEVNOTSUPP;
309 return pnd->last_error;
310 }
311 if (uid_len < resp_len - 2) {
312 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "UID too big");
313 pnd->last_error = NFC_ESOFT;
314 return pnd->last_error;
315 }
316
317 memcpy(uid, resp, resp_len - 2);
318 return resp_len - 2;
319 }
320
321 static int pcsc_props_to_target(struct nfc_device *pnd, uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt)
322 {
323 if (NULL != pnt) {
324 switch (nmt) {
325 case NMT_ISO14443A:
326 if ((it == ICC_TYPE_UNKNOWN || it == ICC_TYPE_14443A)
327 && (szuid <= 0 || szuid == 4 || szuid == 7 || szuid == 10)
328 && NULL != patr && szatr >= 5
329 && patr[0] == 0x3B
330 && patr[1] == (0x80 | ((uint8_t)(szatr - 5)))
331 && patr[2] == 0x80
332 && patr[3] == 0x01) {
333 memset(pnt, 0, sizeof * pnt);
334 pnt->nm.nmt = NMT_ISO14443A;
335 pnt->nm.nbr = pcsc_supported_brs[0];
336 if (szuid > 0) {
337 memcpy(pnt->nti.nai.abtUid, puid, szuid);
338 pnt->nti.nai.szUidLen = szuid;
339 }
340 if (is_pcsc_reader_vendor_feitian(pnd)) {
341 uint8_t atqa[2];
342 pcsc_get_atqa(pnd, atqa, sizeof(atqa));
343 //memcpy(pnt->nti.nai.abtAtqa,atqa,2);
344 pnt->nti.nai.abtAtqa[0] = atqa[1];
345 pnt->nti.nai.abtAtqa[1] = atqa[0];
346 uint8_t sak[1];
347 pcsc_get_sak(pnd, sak, sizeof(sak));
348 pnt->nti.nai.btSak = sak[0];
349 uint8_t ats[256];
350 int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats));
351 memcpy(pnt->nti.nai.abtAts, ats, ats_len);
352 //memcpy(pnt->nti.nai.abtAts + ats_len, patr + 4, (uint8_t)(szatr - 5));
353 pnt->nti.nai.szAtsLen = ats_len;// + szatr - 5;
354 } else {
355 /* SAK_ISO14443_4_COMPLIANT */
356 pnt->nti.nai.btSak = 0x20;
357 /* Choose TL, TA, TB, TC according to Mifare DESFire */
358 memcpy(pnt->nti.nai.abtAts, "\x75\x77\x81\x02", 4);
359 /* copy historical bytes */
360 memcpy(pnt->nti.nai.abtAts + 4, patr + 4, (uint8_t)(szatr - 5));
361 pnt->nti.nai.szAtsLen = 4 + (uint8_t)(szatr - 5);
362 }
363
364 return NFC_SUCCESS;
365 }
366 break;
367 case NMT_ISO14443B:
368 if ((ICC_TYPE_UNKNOWN == 0 || ICC_TYPE_14443B == 6)
369 && (szuid <= 0 || szuid == 8)
370 && NULL != patr && szatr == 5 + 8
371 && patr[0] == 0x3B
372 && patr[1] == (0x80 | 0x08)
373 && patr[2] == 0x80
374 && patr[3] == 0x01) {
375 memset(pnt, 0, sizeof * pnt);
376 pnt->nm.nmt = NMT_ISO14443B;
377 pnt->nm.nbr = pcsc_supported_brs[0];
378 memcpy(pnt->nti.nbi.abtApplicationData, patr + 4, 4);
379 memcpy(pnt->nti.nbi.abtProtocolInfo, patr + 8, 3);
380 /* PI_ISO14443_4_SUPPORTED */
381 pnt->nti.nbi.abtProtocolInfo[1] = 0x01;
382 return NFC_SUCCESS;
383 }
384 break;
385 default:
386 break;
387 }
388 }
389 return NFC_EINVARG;
390 }
391
392 #define PCSC_MAX_DEVICES 16
393 /**
394 * @brief List opened devices
395 *
396 * Probe PCSC to find any reader but the ACR122 devices (ACR122U and Touchatag/Tikitag).
397 *
398 * @param connstring array of nfc_connstring where found device's connection strings will be stored.
399 * @param connstrings_len size of connstrings array.
400 * @return number of devices found.
401 */
402 static size_t
403 pcsc_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
404 {
405 (void) context;
406 size_t szPos = 0;
407 char acDeviceNames[256 + 64 * PCSC_MAX_DEVICES];
408 size_t szDeviceNamesLen = sizeof(acDeviceNames);
409 SCARDCONTEXT *pscc;
410 int i;
411
412 // Clear the reader list
413 memset(acDeviceNames, '\0', szDeviceNamesLen);
414
415 // Test if context succeeded
416 if (!(pscc = pcsc_get_scardcontext())) {
417 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s", "PCSC context not found (make sure PCSC daemon is running).");
418 return 0;
419 }
420 // Retrieve the string array of all available pcsc readers
421 DWORD dwDeviceNamesLen = szDeviceNamesLen;
422 if (SCardListReaders(*pscc, NULL, acDeviceNames, &dwDeviceNamesLen) != SCARD_S_SUCCESS)
423 return 0;
424
425 size_t device_found = 0;
426 while ((acDeviceNames[szPos] != '\0') && (device_found < connstrings_len)) {
427 bool bSupported = false;
428 for (i = 0; supported_devices[i] && !bSupported; i++) {
429 int l = strlen(supported_devices[i]);
430 bSupported = 0 == !strncmp(supported_devices[i], acDeviceNames + szPos, l);
431 }
432
433 if (bSupported) {
434 // Supported non-ACR122 device found
435 snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s", PCSC_DRIVER_NAME, acDeviceNames + szPos);
436 device_found++;
437 } else {
438 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Skipping PCSC device [%s] as it is supported by acr122_pcsc driver.", acDeviceNames + szPos);
439 }
440
441 // Find next device name position
442 while (acDeviceNames[szPos++] != '\0');
443 }
444 pcsc_free_scardcontext();
445
446 return device_found;
447 }
448
449 struct pcsc_descriptor {
450 char *pcsc_device_name;
451 };
452
453 static nfc_device *
454 pcsc_open(const nfc_context *context, const nfc_connstring connstring)
455 {
456 struct pcsc_descriptor ndd;
457 int connstring_decode_level = connstring_decode(connstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL);
458
459 if (connstring_decode_level < 1) {
460 return NULL;
461 }
462
463 nfc_connstring fullconnstring;
464 if (connstring_decode_level == 1) {
465 // Device was not specified, take the first one we can find
466 size_t szDeviceFound = pcsc_scan(context, &fullconnstring, 1);
467 if (szDeviceFound < 1)
468 return NULL;
469 connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL);
470 if (connstring_decode_level < 2) {
471 return NULL;
472 }
473 } else {
474 memcpy(fullconnstring, connstring, sizeof(nfc_connstring));
475 }
476 if (strlen(ndd.pcsc_device_name) < 5) { // We can assume it's a reader ID as pcsc_name always ends with "NN NN"
477 // Device was not specified, only ID, retrieve it
478 size_t index;
479 if (sscanf(ndd.pcsc_device_name, "%4" SCNuPTR, &index) != 1) {
480 free(ndd.pcsc_device_name);
481 return NULL;
482 }
483 nfc_connstring *ncs = malloc(sizeof(nfc_connstring) * (index + 1));
484 if (!ncs) {
485 perror("malloc");
486 free(ndd.pcsc_device_name);
487 return NULL;
488 }
489 size_t szDeviceFound = pcsc_scan(context, ncs, index + 1);
490 if (szDeviceFound < index + 1) {
491 free(ncs);
492 free(ndd.pcsc_device_name);
493 return NULL;
494 }
495 strncpy(fullconnstring, ncs[index], sizeof(nfc_connstring));
496 fullconnstring[sizeof(nfc_connstring) - 1] = '\0';
497 free(ncs);
498 connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL);
499
500 if (connstring_decode_level < 2) {
501 free(ndd.pcsc_device_name);
502 return NULL;
503 }
504 }
505
506 nfc_device *pnd = nfc_device_new(context, fullconnstring);
507 if (!pnd) {
508 perror("malloc");
509 goto error;
510 }
511 pnd->driver_data = malloc(sizeof(struct pcsc_data));
512 if (!pnd->driver_data) {
513 perror("malloc");
514 goto error;
515 }
516
517 SCARDCONTEXT *pscc;
518
519 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open %s", ndd.pcsc_device_name);
520 // Test if context succeeded
521 if (!(pscc = pcsc_get_scardcontext()))
522 goto error;
523 DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
524 if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) {
525 // We can not connect to this device.
526 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed");
527 goto error;
528 }
529 // Configure I/O settings for card communication
530 DRIVER_DATA(pnd)->ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST);
531 DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT;
532
533 // Done, we found the reader we are looking for
534 snprintf(pnd->name, sizeof(pnd->name), "%s", ndd.pcsc_device_name);
535
536 pnd->driver = &pcsc_driver;
537
538 free(ndd.pcsc_device_name);
539 return pnd;
540
541 error:
542 free(ndd.pcsc_device_name);
543 nfc_device_free(pnd);
544 return NULL;
545 }
546
547 static void
548 pcsc_close(nfc_device *pnd)
549 {
550 SCardDisconnect(DRIVER_DATA(pnd)->hCard, SCARD_LEAVE_CARD);
551 pcsc_free_scardcontext();
552
553 nfc_device_free(pnd);
554 }
555
556 static const char *stringify_error(const LONG pcscError)
557 {
558 static char strError[75];
559 const char *msg = NULL;
560
561 switch (pcscError) {
562 case SCARD_S_SUCCESS:
563 msg = "Command successful.";
564 break;
565 case SCARD_F_INTERNAL_ERROR:
566 msg = "Internal error.";
567 break;
568 case SCARD_E_CANCELLED:
569 msg = "Command cancelled.";
570 break;
571 case SCARD_E_INVALID_HANDLE:
572 msg = "Invalid handle.";
573 break;
574 case SCARD_E_INVALID_PARAMETER:
575 msg = "Invalid parameter given.";
576 break;
577 case SCARD_E_INVALID_TARGET:
578 msg = "Invalid target given.";
579 break;
580 case SCARD_E_NO_MEMORY:
581 msg = "Not enough memory.";
582 break;
583 case SCARD_F_WAITED_TOO_LONG:
584 msg = "Waited too long.";
585 break;
586 case SCARD_E_INSUFFICIENT_BUFFER:
587 msg = "Insufficient buffer.";
588 break;
589 case SCARD_E_UNKNOWN_READER:
590 msg = "Unknown reader specified.";
591 break;
592 case SCARD_E_TIMEOUT:
593 msg = "Command timeout.";
594 break;
595 case SCARD_E_SHARING_VIOLATION:
596 msg = "Sharing violation.";
597 break;
598 case SCARD_E_NO_SMARTCARD:
599 msg = "No smart card inserted.";
600 break;
601 case SCARD_E_UNKNOWN_CARD:
602 msg = "Unknown card.";
603 break;
604 case SCARD_E_CANT_DISPOSE:
605 msg = "Cannot dispose handle.";
606 break;
607 case SCARD_E_PROTO_MISMATCH:
608 msg = "Card protocol mismatch.";
609 break;
610 case SCARD_E_NOT_READY:
611 msg = "Subsystem not ready.";
612 break;
613 case SCARD_E_INVALID_VALUE:
614 msg = "Invalid value given.";
615 break;
616 case SCARD_E_SYSTEM_CANCELLED:
617 msg = "System cancelled.";
618 break;
619 case SCARD_F_COMM_ERROR:
620 msg = "RPC transport error.";
621 break;
622 case SCARD_F_UNKNOWN_ERROR:
623 msg = "Unknown error.";
624 break;
625 case SCARD_E_INVALID_ATR:
626 msg = "Invalid ATR.";
627 break;
628 case SCARD_E_NOT_TRANSACTED:
629 msg = "Transaction failed.";
630 break;
631 case SCARD_E_READER_UNAVAILABLE:
632 msg = "Reader is unavailable.";
633 break;
634 /* case SCARD_P_SHUTDOWN: */
635 case SCARD_E_PCI_TOO_SMALL:
636 msg = "PCI struct too small.";
637 break;
638 case SCARD_E_READER_UNSUPPORTED:
639 msg = "Reader is unsupported.";
640 break;
641 case SCARD_E_DUPLICATE_READER:
642 msg = "Reader already exists.";
643 break;
644 case SCARD_E_CARD_UNSUPPORTED:
645 msg = "Card is unsupported.";
646 break;
647 case SCARD_E_NO_SERVICE:
648 msg = "Service not available.";
649 break;
650 case SCARD_E_SERVICE_STOPPED:
651 msg = "Service was stopped.";
652 break;
653 /* case SCARD_E_UNEXPECTED: */
654 /* case SCARD_E_ICC_CREATEORDER: */
655 /* case SCARD_E_UNSUPPORTED_FEATURE: */
656 /* case SCARD_E_DIR_NOT_FOUND: */
657 /* case SCARD_E_NO_DIR: */
658 /* case SCARD_E_NO_FILE: */
659 /* case SCARD_E_NO_ACCESS: */
660 /* case SCARD_E_WRITE_TOO_MANY: */
661 /* case SCARD_E_BAD_SEEK: */
662 /* case SCARD_E_INVALID_CHV: */
663 /* case SCARD_E_UNKNOWN_RES_MNG: */
664 /* case SCARD_E_NO_SUCH_CERTIFICATE: */
665 /* case SCARD_E_CERTIFICATE_UNAVAILABLE: */
666 case SCARD_E_NO_READERS_AVAILABLE:
667 msg = "Cannot find a smart card reader.";
668 break;
669 /* case SCARD_E_COMM_DATA_LOST: */
670 /* case SCARD_E_NO_KEY_CONTAINER: */
671 /* case SCARD_E_SERVER_TOO_BUSY: */
672 case SCARD_W_UNSUPPORTED_CARD:
673 msg = "Card is not supported.";
674 break;
675 case SCARD_W_UNRESPONSIVE_CARD:
676 msg = "Card is unresponsive.";
677 break;
678 case SCARD_W_UNPOWERED_CARD:
679 msg = "Card is unpowered.";
680 break;
681 case SCARD_W_RESET_CARD:
682 msg = "Card was reset.";
683 break;
684 case SCARD_W_REMOVED_CARD:
685 msg = "Card was removed.";
686 break;
687 /* case SCARD_W_SECURITY_VIOLATION: */
688 /* case SCARD_W_WRONG_CHV: */
689 /* case SCARD_W_CHV_BLOCKED: */
690 /* case SCARD_W_EOF: */
691 /* case SCARD_W_CANCELLED_BY_USER: */
692 /* case SCARD_W_CARD_NOT_AUTHENTICATED: */
693
694 case SCARD_E_UNSUPPORTED_FEATURE:
695 msg = "Feature not supported.";
696 break;
697 default:
698 (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX",
699 pcscError);
700 };
701
702 if (msg)
703 (void)strncpy(strError, msg, sizeof(strError));
704 else
705 (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX",
706 pcscError);
707
708 /* add a null byte */
709 strError[sizeof(strError) - 1] = '\0';
710
711 return strError;
712 }
713
714 static const char *
715 pcsc_strerror(const struct nfc_device *pnd)
716 {
717 return stringify_error(DRIVER_DATA(pnd)->last_error);
718 }
719
720 static int pcsc_initiator_init(struct nfc_device *pnd)
721 {
722 (void) pnd;
723 return NFC_SUCCESS;
724 }
725
726 static int pcsc_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt)
727 {
728 uint8_t atr[MAX_ATR_SIZE];
729 uint8_t uid[10];
730 int target_present;
731 size_t atr_len = sizeof atr;
732
733 (void) pbtInitData;
734 (void) szInitData;
735
736 if (nm.nbr != pcsc_supported_brs[0] && nm.nbr != pcsc_supported_brs[1])
737 return NFC_EINVARG;
738
739 pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len);
740 if (pnd->last_error != NFC_SUCCESS)
741 return pnd->last_error;
742
743 if (!target_present) {
744 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present");
745 return NFC_ENOTSUCHDEV;
746 }
747
748 uint8_t icc_type = pcsc_get_icc_type(pnd);
749 int uid_len = pcsc_get_uid(pnd, uid, sizeof uid);
750 if (pcsc_props_to_target(pnd, icc_type, atr, atr_len, uid, uid_len, nm.nmt, pnt) != NFC_SUCCESS) {
751 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Type of target not supported");
752 return NFC_EDEVNOTSUPP;
753 }
754
755 pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD);
756 if (pnd->last_error != NFC_SUCCESS)
757 return pnd->last_error;
758
759 return 1;
760 }
761
762 #if 0
763 static int pcsc_initiator_deselect_target(struct nfc_device *pnd)
764 {
765 pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD);
766 return pnd->last_error;
767 }
768 #endif
769
770 static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout)
771 {
772 size_t resp_len = szRx;
773
774 // FIXME: timeout is not handled
775 (void) timeout;
776
777 if (is_pcsc_reader_vendor_feitian(pnd)) {
778 LOG_HEX(NFC_LOG_GROUP_COM, "not feitian reader pcsc apdu send", pbtTx, szTx);
779
780 uint8_t apdu_data[256];
781 uint8_t resp[256 + 2];
782 size_t send_size = 0;
783 if (pbtTx[0] == 0x30) {//read data
784 apdu_data[0] = 0xFF;
785 apdu_data[1] = 0xB0;
786 apdu_data[2] = 0x00;
787 apdu_data[3] = pbtTx[1];
788 apdu_data[4] = 0x10;
789 send_size = 5;
790 } else if (pbtTx[0] == 0xA0 || pbtTx[0] == 0xA2) {//write data
791 apdu_data[0] = 0xFF;
792 apdu_data[1] = 0xD6;
793 apdu_data[2] = 0x00;
794 apdu_data[3] = pbtTx[1];
795 apdu_data[4] = szTx - 2;
796 memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
797 send_size = 5 + szTx - 2;
798 } else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A) { //Auth command
799 apdu_data[0] = 0xFF;
800 apdu_data[1] = 0x86;
801 apdu_data[2] = 0x00;
802 apdu_data[3] = 0x00;
803 apdu_data[4] = 0x05;
804 apdu_data[5] = 0x01;
805 apdu_data[6] = 0x00;
806 apdu_data[7] = pbtTx[1];//block index
807 apdu_data[8] = pbtTx[0];//type a or type b
808 apdu_data[9] = 0x01;
809 send_size = 10;
810 } else if (pbtTx[0] == 0xC0) { //DECREMENT cmd
811 apdu_data[0] = 0xFF;
812 apdu_data[1] = 0xD7;
813 apdu_data[2] = 0x00;
814 apdu_data[3] = pbtTx[1];//block index
815 apdu_data[4] = 0x05;
816 memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
817 send_size = 5 + szTx - 2;
818 } else if (pbtTx[0] == 0xC1) { //INCREMENT cmd
819 apdu_data[0] = 0xFF;
820 apdu_data[1] = 0xD7;
821 apdu_data[2] = 0x00;
822 apdu_data[3] = pbtTx[1];//block index
823 apdu_data[4] = 0x05;
824 memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
825 send_size = 5 + szTx - 2;
826 } else if (pbtTx[0] == 0xC2) { //STORE cmd
827 apdu_data[0] = 0xFF;
828 apdu_data[1] = 0xD8;
829 apdu_data[2] = 0x00;
830 apdu_data[3] = pbtTx[1];
831 apdu_data[4] = szTx - 2;
832 memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
833 send_size = 5 + szTx - 2;
834 } else {//other cmd
835 memcpy(apdu_data, pbtTx, szTx);
836 send_size = szTx;
837 }
838 LOG_HEX(NFC_LOG_GROUP_COM, "feitian reader pcsc apdu send:", apdu_data, send_size);
839 pnd->last_error = pcsc_transmit(pnd, apdu_data, send_size, resp, &resp_len);
840 LOG_HEX(NFC_LOG_GROUP_COM, "feitian reader pcsc apdu received:", resp, resp_len);
841
842 memcpy(pbtRx, resp, resp_len);
843 } else {
844 pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len);
845 }
846 if (pnd->last_error != NFC_SUCCESS)
847 return pnd->last_error;
848
849 return resp_len;
850 }
851
852 static int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
853 {
854 uint8_t atr[MAX_ATR_SIZE];
855 int target_present;
856 size_t atr_len = sizeof atr;
857 nfc_target nt;
858
859 pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len);
860 if (pnd->last_error != NFC_SUCCESS)
861 return pnd->last_error;
862
863 if (!target_present) {
864 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present");
865 return NFC_ENOTSUCHDEV;
866 }
867
868 if (pnt) {
869 if (pcsc_props_to_target(pnd, ICC_TYPE_UNKNOWN, atr, atr_len, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS
870 || pnt->nm.nmt != nt.nm.nmt || pnt->nm.nbr != nt.nm.nbr) {
871 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Target doesn't meet requirements");
872 return NFC_ENOTSUCHDEV;
873 }
874 }
875 return NFC_SUCCESS;
876 }
877
878 static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable)
879 {
880 (void) pnd;
881 switch (property) {
882 case NP_INFINITE_SELECT:
883 // ignore
884 return NFC_SUCCESS;
885 case NP_AUTO_ISO14443_4:
886 case NP_EASY_FRAMING:
887 if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
888 return NFC_SUCCESS;
889 break;
890 case NP_FORCE_ISO14443_A:
891 case NP_HANDLE_CRC:
892 case NP_HANDLE_PARITY:
893 case NP_FORCE_SPEED_106:
894 if (bEnable == true)
895 return NFC_SUCCESS;
896 break;
897 case NP_ACCEPT_INVALID_FRAMES:
898 case NP_ACCEPT_MULTIPLE_FRAMES:
899 if (bEnable == false)
900 return NFC_SUCCESS;
901 break;
902 case NP_ACTIVATE_FIELD:
903 if (bEnable == false) {
904 struct pcsc_data *data = pnd->driver_data;
905 pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD);
906 }
907 return NFC_SUCCESS;
908 default:
909 break;
910 }
911 return NFC_EDEVNOTSUPP;
912 }
913
914 static int pcsc_get_supported_modulation(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
915 {
916 (void) pnd;
917 if (mode == N_TARGET || NULL == supported_mt)
918 return NFC_EINVARG;
919 *supported_mt = pcsc_supported_mts;
920 return NFC_SUCCESS;
921 }
922
923 static int pcsc_get_supported_baud_rate(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
924 {
925 (void) pnd;
926 (void) nmt;
927 if (mode == N_TARGET || NULL == supported_br)
928 return NFC_EINVARG;
929 *supported_br = pcsc_supported_brs;
930 return NFC_SUCCESS;
931 }
932
933 static int
934 pcsc_get_information_about(nfc_device *pnd, char **pbuf)
935 {
936 struct pcsc_data *data = pnd->driver_data;
937 LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL;
938 DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE,
939 type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE;
940 int res = NFC_SUCCESS;
941 SCARDCONTEXT *pscc;
942
943 if (!(pscc = pcsc_get_scardcontext())) {
944 pnd->last_error = NFC_ESOFT;
945 return pnd->last_error;
946 }
947
948 SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len);
949 SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len);
950 SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len);
951 SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len);
952
953 *pbuf = malloc(name_len + type_len + version_len + serial_len + 30);
954 if (! *pbuf) {
955 res = NFC_ESOFT;
956 goto error;
957 }
958 sprintf((char *) *pbuf,
959 "%s" // model
960 "%s%s" // version
961 " (%s)" // vendor
962 "%s%s\n" // serial
963 ,
964 name && name_len > 0 && name[0] != '\0'
965 ? (char *)name : "unknown model",
966 version && version_len > 0 && version[0] != '\0'
967 ? " " : "", version_len > 0 ? (char *)version : "",
968 type && type_len > 0 && type[0] != '\0'
969 ? (char *)type : "unknown vendor",
970 serial && serial_len > 0 && serial[0] != '\0'
971 ? "\nserial: " : "", serial_len > 0 ? (char *)serial : "");
972
973 error:
974 #ifdef __APPLE__
975 if (pscc != NULL) {
976 SCardReleaseContext(*pscc);
977 }
978 if (name != NULL) {
979 free(name);
980 name = NULL;
981 }
982 if (type != NULL) {
983 free(type);
984 type = NULL;
985 }
986 if (version != NULL) {
987 free(version);
988 version = NULL;
989 }
990 if (serial != NULL) {
991 free(serial);
992 serial = NULL;
993 }
994 #else
995 SCardFreeMemory(*pscc, name);
996 SCardFreeMemory(*pscc, type);
997 SCardFreeMemory(*pscc, version);
998 SCardFreeMemory(*pscc, serial);
999 #endif
1000
1001 pnd->last_error = res;
1002 return pnd->last_error;
1003 }
1004
1005 const struct nfc_driver pcsc_driver = {
1006 .name = PCSC_DRIVER_NAME,
1007 .scan = pcsc_scan,
1008 .open = pcsc_open,
1009 .close = pcsc_close,
1010 .strerror = pcsc_strerror,
1011
1012 .initiator_init = pcsc_initiator_init,
1013 .initiator_init_secure_element = NULL, // No secure-element support
1014 .initiator_select_passive_target = pcsc_initiator_select_passive_target,
1015 .initiator_poll_target = NULL,
1016 .initiator_select_dep_target = NULL,
1017 .initiator_deselect_target = NULL,
1018 .initiator_transceive_bytes = pcsc_initiator_transceive_bytes,
1019 .initiator_transceive_bits = NULL,
1020 .initiator_transceive_bytes_timed = NULL,
1021 .initiator_transceive_bits_timed = NULL,
1022 .initiator_target_is_present = pcsc_initiator_target_is_present,
1023
1024 .target_init = NULL,
1025 .target_send_bytes = NULL,
1026 .target_receive_bytes = NULL,
1027 .target_send_bits = NULL,
1028 .target_receive_bits = NULL,
1029
1030 .device_set_property_bool = pcsc_device_set_property_bool,
1031 .device_set_property_int = NULL,
1032 .get_supported_modulation = pcsc_get_supported_modulation,
1033 .get_supported_baud_rate = pcsc_get_supported_baud_rate,
1034 .device_get_information_about = pcsc_get_information_about,
1035
1036 .abort_command = NULL, // Abort is not supported in this driver
1037 .idle = NULL,
1038 .powerdown = NULL,
1039 };
0 /*-
1 * Free/Libre Near Field Communication (NFC) library
2 *
3 * Libnfc historical contributors:
4 * Copyright (C) 2019 Frank Morgner
5 * See AUTHORS file for a more comprehensive list of contributors.
6 * Additional contributors of this file:
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
20 */
21
22 /**
23 * @file pcsc.h
24 * @brief Driver for non-ACR122 devices (behind PC/SC daemon)
25 */
26
27 #ifndef __NFC_DRIVER_PCSC_H__
28 #define __NFC_DRIVER_PCSC_H__
29
30 #include <nfc/nfc-types.h>
31
32 extern const struct nfc_driver pcsc_driver;
33
34 #endif // ! __NFC_DRIVER_PCSC_H__
5858 // I2C address of the PN532 chip.
5959 #define PN532_I2C_ADDR 0x24
6060
61 /*
62 * When sending lots of data, the pn532 occasionally fails to respond in time.
63 * Since it happens so rarely, lets try to fix it by re-sending the data. This
64 * define allows for fine tuning the number of retries.
65 */
66 #define PN532_SEND_RETRIES 3
67
6168 // Internal data structs
6269 const struct pn53x_io pn532_i2c_io;
6370
6673 volatile bool abort_flag;
6774 };
6875
69 /* Delay for the loop waiting for READY frame (in ms) */
70 #define PN532_RDY_LOOP_DELAY 90
71
72 const struct timespec rdyDelay = {
73 .tv_sec = 0,
74 .tv_nsec = PN532_RDY_LOOP_DELAY * 1000 * 1000
75 };
76 /* preamble and start bytes, see pn532-internal.h for details */
77 const uint8_t pn53x_preamble_and_start[] = { 0x00, 0x00, 0xff };
78 #define PN53X_PREAMBLE_AND_START_LEN (sizeof(pn53x_preamble_and_start) / sizeof(pn53x_preamble_and_start[0]))
7679
7780 /* Private Functions Prototypes */
7881
9497
9598
9699 #define DRIVER_DATA(pnd) ((struct pn532_i2c_data*)(pnd->driver_data))
100
101 /*
102 * Bus free time (in ms) between a STOP condition and START condition. See
103 * tBuf in the PN532 data sheet, section 12.25: Timing for the I2C interface,
104 * table 320. I2C timing specification, page 211, rev. 3.2 - 2007-12-07.
105 */
106 #define PN532_BUS_FREE_TIME 5
107 static struct timespec __transaction_stop;
108
109 /**
110 * @brief Wrapper around i2c_read to ensure proper timing by respecting the
111 * minimal free bus time between a STOP condition and a START condition.
112 *
113 * @note This is not thread safe, but since libnfc is single threaded
114 * this should be okay.
115 *
116 * @param id I2C device
117 * @param buf pointer on buffer used to store data
118 * @param len length of the buffer
119 * @return length (in bytes) of read data, or driver error code (negative value)
120 */
121 static ssize_t pn532_i2c_read(const i2c_device id,
122 uint8_t *buf, const size_t len)
123 {
124 struct timespec transaction_start, bus_free_time = { 0, 0 };
125 ssize_t ret;
126
127 clock_gettime(CLOCK_MONOTONIC, &transaction_start);
128 bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) -
129 (transaction_start.tv_nsec - __transaction_stop.tv_nsec);
130 nanosleep(&bus_free_time, NULL);
131
132 ret = i2c_read(id, buf, len);
133 clock_gettime(CLOCK_MONOTONIC, &__transaction_stop);
134 return ret;
135 }
136
137 /**
138 * @brief Wrapper around i2c_write to ensure proper timing by respecting the
139 * minimal free bus time between a STOP condition and a START condition.
140 *
141 * @note This is not thread safe, but since libnfc is single threaded
142 * this should be okay.
143 *
144 * @param id I2C device
145 * @param buf pointer on buffer containing data
146 * @param len length of the buffer
147 * @return NFC_SUCCESS on success, otherwise driver error code
148 */
149 static ssize_t pn532_i2c_write(const i2c_device id,
150 const uint8_t *buf, const size_t len)
151 {
152 struct timespec transaction_start, bus_free_time = { 0, 0 };
153 ssize_t ret;
154
155 clock_gettime(CLOCK_MONOTONIC, &transaction_start);
156 bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) -
157 (transaction_start.tv_nsec - __transaction_stop.tv_nsec);
158 nanosleep(&bus_free_time, NULL);
159
160 ret = i2c_write(id, buf, len);
161 clock_gettime(CLOCK_MONOTONIC, &__transaction_stop);
162 return ret;
163 }
97164
98165 /**
99166 * @brief Scan all available I2C buses to find PN532 devices.
307374 pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
308375 {
309376 int res = 0;
377 uint8_t retries;
310378
311379 // Discard any existing data ?
312380
333401 break;
334402 };
335403
336 uint8_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
404 uint8_t abtFrame[PN532_BUFFER_LEN];
337405 size_t szFrame = 0;
338406
407 memcpy(abtFrame, pn53x_preamble_and_start, PN53X_PREAMBLE_AND_START_LEN); // Every packet must start with the preamble and start bytes.
339408 if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) {
340409 pnd->last_error = res;
341410 return pnd->last_error;
342411 }
343412
344 res = i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame);
413 for (retries = PN532_SEND_RETRIES; retries > 0; retries--) {
414 res = pn532_i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame);
415 if (res >= 0)
416 break;
417
418 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Failed to transmit data. Retries left: %d.", retries - 1);
419 }
345420
346421 if (res < 0) {
347422 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
399474 }
400475
401476 do {
402 // Wait a little bit before reading
403 nanosleep(&rdyDelay, (struct timespec *) NULL);
404
405 int recCount = i2c_read(DRIVER_DATA(pnd)->dev, i2cRx, szDataLen + 1);
477 int recCount = pn532_i2c_read(DRIVER_DATA(pnd)->dev, i2cRx, szDataLen + 1);
406478
407479 if (DRIVER_DATA(pnd)->abort_flag) {
408480 // Reset abort flag
476548 goto error;
477549 }
478550
479 const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
480
481 if (0 != (memcmp(frameBuf, pn53x_preamble, 3))) {
551 if (0 != (memcmp(frameBuf, pn53x_preamble_and_start, PN53X_PREAMBLE_AND_START_LEN))) {
482552 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
483553 pnd->last_error = NFC_EIO;
484554 goto error;
571641 int
572642 pn532_i2c_ack(nfc_device *pnd)
573643 {
574 return i2c_write(DRIVER_DATA(pnd)->dev, pn53x_ack_frame, sizeof(pn53x_ack_frame));
644 return pn532_i2c_write(DRIVER_DATA(pnd)->dev, pn53x_ack_frame, sizeof(pn53x_ack_frame));
575645 }
576646
577647 /**
432432 goto error;
433433 }
434434
435 pnd->last_error = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, abtRxBuf , 4, true);
435 pnd->last_error = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, abtRxBuf, 4, true);
436436
437437 if (pnd->last_error < 0) {
438438 goto error;
8181
8282 while ((acPort = acPorts[iDevice++])) {
8383 sp = uart_open(acPort);
84 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on serial port: %s at %d bauds.", acPort, PN532_UART_DEFAULT_SPEED);
84 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on serial port: %s at %d baud.", acPort, PN532_UART_DEFAULT_SPEED);
8585
8686 if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
8787 // We need to flush input to be sure first reply does not comes from older byte transceive
224224 serial_port sp;
225225 nfc_device *pnd = NULL;
226226
227 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed);
227 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d baud.", ndd.port, ndd.speed);
228228 sp = uart_open(ndd.port);
229229
230230 if (sp == INVALID_SERIAL_PORT)
44 * Copyright (C) 2009 Roel Verdult
55 * Copyright (C) 2009-2013 Romuald Conty
66 * Copyright (C) 2010-2012 Romain Tartière
7 * Copyright (C) 2010-2013 Philippe Teuwen
7 * Copyright (C) 2010-2017 Philippe Teuwen
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
5959
6060 #define DRIVER_DATA(pnd) ((struct pn53x_usb_data*)(pnd->driver_data))
6161
62 const nfc_modulation_type no_target_support[] = {0};
63
6264 typedef enum {
6365 UNKNOWN,
6466 NXP_PN531,
6668 NXP_PN533,
6769 ASK_LOGO,
6870 SCM_SCL3711,
71 SCM_SCL3712,
6972 SONY_RCS360
7073 } pn53x_usb_model;
7174
7780 uint32_t uiEndPointOut;
7881 uint32_t uiMaxPacketSize;
7982 volatile bool abort_flag;
83 bool possibly_corrupted_usbdesc;
8084 };
8185
8286 // Internal io struct
120124 uint16_t product_id;
121125 pn53x_usb_model model;
122126 const char *name;
127 /* hardcoded known values for buggy hardware whose configuration vanishes */
128 uint32_t uiEndPointIn;
129 uint32_t uiEndPointOut;
130 uint32_t uiMaxPacketSize;
123131 };
124132
125133 const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = {
126 { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531" },
127 { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533" },
128 { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW" },
129 { 0x054c, 0x0193, SONY_PN531, "Sony / PN531" },
130 { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO" },
131 { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]" }
134 { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40 },
135 { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x84, 0x04, 0x40 },
136 { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x84, 0x04, 0x40 },
137 { 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0 }, // to check on real device
138 { 0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0x84, 0x04, 0x40 },
139 { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40 },
140 { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0x84, 0x04, 0x40 }
132141 };
142
143 // PN533 USB descriptors backup buffers
144
145 const uint8_t btXramUsbDesc_scl3711[] = {
146 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00,
147 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
148 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x1e, 0x03, 0x53, 0x00,
149 0x43, 0x00, 0x4c, 0x00, 0x33, 0x00, 0x37, 0x00, 0x31, 0x00, 0x31, 0x00,
150 0x2d, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x43, 0x00, 0x26, 0x00, 0x52, 0x00,
151 0x57,
152 };
153 const uint8_t btXramUsbDesc_nxppn533[] = {
154 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00,
155 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
156 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0c, 0x03, 0x50, 0x00,
157 0x4e, 0x00, 0x35, 0x00, 0x33, 0x00, 0x33, 0x00, 0x04, 0x03, 0x09, 0x04,
158 0x08, 0x03, 0x4e, 0x00, 0x58, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00,
160 };
161 const uint8_t btXramUsbDesc_asklogo[] = {
162 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, 0x04, 0x00,
163 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
164 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0a, 0x03, 0x4c, 0x00,
165 0x6f, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x04, 0x03, 0x09, 0x04, 0x08, 0x03,
166 0x41, 0x00, 0x53, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00,
168 };
169
170 static void pn533_fix_usbdesc(nfc_device *pnd)
171 {
172 // PN533 USB descriptors may have been corrupted by large commands/responses
173 // so they need to be restored before closing usb connection.
174 // cf PN5331B3HNC270 Release Note
175 uint32_t szXramUsbDesc = 0;
176 uint8_t *btXramUsbDesc = NULL;
177 if (DRIVER_DATA(pnd)->model == NXP_PN533) {
178 btXramUsbDesc = (uint8_t *)btXramUsbDesc_nxppn533;
179 szXramUsbDesc = sizeof(btXramUsbDesc_nxppn533);
180 } else if (DRIVER_DATA(pnd)->model == SCM_SCL3711) {
181 btXramUsbDesc = (uint8_t *)btXramUsbDesc_scl3711;
182 szXramUsbDesc = sizeof(btXramUsbDesc_scl3711);
183 } else if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
184 btXramUsbDesc = (uint8_t *)btXramUsbDesc_asklogo;
185 szXramUsbDesc = sizeof(btXramUsbDesc_asklogo);
186 }
187 #define MAXSZXRAMUSBDESC 61
188 if ((szXramUsbDesc == 0) || (MAXSZXRAMUSBDESC > 61))
189 return;
190 #if 0
191 // Debug routine to check if corruption occurred:
192 // Don't read more regs at once or it will trigger the bug and corrupt what we're busy reading!
193 uint8_t abtCmdRR[] = { ReadRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
194 uint8_t nRRreg = ((sizeof(abtCmdRR) - 1) / 2);
195 uint8_t abtRxRR[1 + nRRreg];
196 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Checking USB descriptors corruption in XRAM");
197 for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) {
198 for (uint8_t k = 0; k < nRRreg; k++) {
199 abtCmdRR[(2 * k) + 2] = i++;
200 }
201 if (pn53x_transceive(pnd, abtCmdRR, sizeof(abtCmdRR), abtRxRR, sizeof(abtRxRR), -1) < 0) {
202 return; // void
203 }
204 for (int k = 0; (k < nRRreg) && (j < szXramUsbDesc); k++) {
205 //printf("0x%02x, ", abtRxRR[1 + k]);
206 if (btXramUsbDesc[j] != abtRxRR[1 + k])
207 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "XRAM corruption @ addr 0x00%02X: got %02x, expected %02x", 0x0019 + (j - 1), abtRxRR[1 + k], btXramUsbDesc[j]);
208 j++;
209 }
210 }
211 #endif
212 // Abuse the overflow bug to restore USB descriptors in one go
213 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption");
214 uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = { GetFirmwareVersion };
215 for (uint8_t i = 0; i < szXramUsbDesc; i++) {
216 abtCmdWR[i + 19] = btXramUsbDesc[i];
217 }
218 size_t szCmdWR = sizeof(abtCmdWR);
219 uint8_t abtRxWR[4];
220 if (pn53x_transceive(pnd, abtCmdWR, szCmdWR, abtRxWR, sizeof(abtRxWR), -1) < 0) {
221 return; // void
222 }
223 DRIVER_DATA(pnd)->possibly_corrupted_usbdesc = false;
224 }
133225
134226 static pn53x_usb_model
135227 pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id)
141233 }
142234
143235 return UNKNOWN;
236 }
237
238 static bool
239 pn53x_usb_get_end_points_default(struct usb_device *dev, struct pn53x_usb_data *data)
240 {
241 for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) {
242 if ((dev->descriptor.idVendor == pn53x_usb_supported_devices[n].vendor_id) &&
243 (dev->descriptor.idProduct == pn53x_usb_supported_devices[n].product_id)) {
244 if (pn53x_usb_supported_devices[n].uiMaxPacketSize != 0) {
245 data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn;
246 data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut;
247 data->uiMaxPacketSize = pn53x_usb_supported_devices[n].uiMaxPacketSize;
248
249 return true;
250 }
251 }
252 }
253
254 return false;
144255 }
145256
146257 int pn53x_usb_ack(nfc_device *pnd);
193304 if ((pn53x_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) &&
194305 (pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) {
195306 // Make sure there are 2 endpoints available
196 // with libusb-win32 we got some null pointers so be robust before looking at endpoints:
197 if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) {
198 // Nope, we maybe want the next one, let's try to find another
199 continue;
200 }
201 if (dev->config->interface->altsetting->bNumEndpoints < 2) {
202 // Nope, we maybe want the next one, let's try to find another
203 continue;
307 // libusb-win32 may return a NULL dev->config,
308 // or the descriptors may be corrupted, hence
309 // let us assume we will use hardcoded defaults
310 // from pn53x_usb_supported_devices if available.
311 // otherwise get data from the descriptors.
312 if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) {
313 if (dev->config->interface == NULL || dev->config->interface->altsetting == NULL) {
314 // Nope, we maybe want the next one, let's try to find another
315 continue;
316 }
317 if (dev->config->interface->altsetting->bNumEndpoints < 2) {
318 // Nope, we maybe want the next one, let's try to find another
319 continue;
320 }
204321 }
205322
206323 usb_dev_handle *udev = usb_open(dev);
219336 // pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice));
220337 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s", bus->dirname, dev->filename);
221338 usb_close(udev);
222 snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename);
339 if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) {
340 // truncation occurred, skipping that one
341 continue;
342 }
223343 device_found++;
224344 // Test if we reach the maximum "wanted" devices
225345 if (device_found == connstrings_len) {
281401 .pudh = NULL,
282402 .uiEndPointIn = 0,
283403 .uiEndPointOut = 0,
404 .possibly_corrupted_usbdesc = false,
284405 };
285406 struct usb_bus *bus;
286407 struct usb_device *dev;
302423 // Open the USB device
303424 if ((data.pudh = usb_open(dev)) == NULL)
304425 continue;
305 // Retrieve end points
306 pn53x_usb_get_end_points(dev, &data);
426
427 //To retrieve real USB endpoints configuration:
428 //pn53x_usb_get_end_points(dev, &data);
429 //printf("DEBUG ENDPOINTS In:0x%x Out:0x%x Size:0x%x\n", data.uiEndPointIn, data.uiEndPointOut, data.uiMaxPacketSize);
430
431 // Retrieve end points, using hardcoded defaults if available
432 // or using the descriptors otherwise.
433 if (pn53x_usb_get_end_points_default(dev, &data) == false) {
434 pn53x_usb_get_end_points(dev, &data);
435 }
307436 // Set configuration
308437 int res = usb_set_configuration(data.pudh, 1);
309438 if (res < 0) {
346475 }
347476
348477 switch (DRIVER_DATA(pnd)->model) {
349 // empirical tuning
478 // empirical tuning
350479 case ASK_LOGO:
351480 CHIP_DATA(pnd)->timer_correction = 50;
481 CHIP_DATA(pnd)->progressive_field = true;
352482 break;
353483 case SCM_SCL3711:
484 case SCM_SCL3712:
354485 case NXP_PN533:
355486 CHIP_DATA(pnd)->timer_correction = 46;
356487 break;
404535 pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P32) | _BV(P33) | _BV(P35));
405536 }
406537
538 if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc)
539 pn533_fix_usbdesc(pnd);
540
407541 pn53x_idle(pnd);
408542
409543 int res;
432566 return pnd->last_error;
433567 }
434568
569 DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= szData > 17;
435570 if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), abtFrame, szFrame, timeout)) < 0) {
436571 pnd->last_error = res;
437572 return pnd->last_error;
451586 // For some reasons (eg. send another command while a previous one is
452587 // running), the PN533 sometimes directly replies the response packet
453588 // instead of ACK frame, so we send a NACK frame to force PN533 to resend
454 // response packet. With this hack, the nextly executed function (ie.
455 // pn53x_usb_receive()) will be able to retreive the correct response
589 // response packet. With this hack, the next executed function (ie.
590 // pn53x_usb_receive()) will be able to retrieve the correct response
456591 // packet.
457592 // FIXME Sony reader is also affected by this bug but NACK is not supported
458593 if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *)pn53x_nack_frame, sizeof(pn53x_nack_frame), timeout)) < 0) {
462597 return pnd->last_error;
463598 }
464599 }
465
466600 return NFC_SUCCESS;
467601 }
468602
600734 }
601735 // The PN53x command is done and we successfully received the reply
602736 pnd->last_error = 0;
737 DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= len > 16;
603738 return len;
604739 }
605740
663798 /* ie. Switch LED1 on and turn off progressive field */
664799 pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P33) | _BV(P35));
665800 }
801 if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc)
802 pn533_fix_usbdesc(pnd);
666803
667804 return NFC_SUCCESS;
668805 }
684821 }
685822 break;
686823 case SCM_SCL3711:
824 if (NP_ACTIVATE_FIELD == property) {
825 // Switch on/off LED according to ACTIVATE_FIELD option
826 if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0)
827 return res;
828 }
829 break;
830 case SCM_SCL3712:
687831 if (NP_ACTIVATE_FIELD == property) {
688832 // Switch on/off LED according to ACTIVATE_FIELD option
689833 if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0)
705849 pn53x_usb_abort_command(nfc_device *pnd)
706850 {
707851 DRIVER_DATA(pnd)->abort_flag = true;
852 return NFC_SUCCESS;
853 }
854
855 static int
856 pn53x_usb_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
857 {
858 if ((DRIVER_DATA(pnd)->model != ASK_LOGO) || (mode != N_TARGET))
859 return pn53x_get_supported_modulation(pnd, mode, supported_mt);
860 else // ASK_LOGO has no N_TARGET support
861 *supported_mt = no_target_support;
708862 return NFC_SUCCESS;
709863 }
710864
741895
742896 .device_set_property_bool = pn53x_usb_set_property_bool,
743897 .device_set_property_int = pn53x_set_property_int,
744 .get_supported_modulation = pn53x_get_supported_modulation,
898 .get_supported_modulation = pn53x_usb_get_supported_modulation,
745899 .get_supported_baud_rate = pn53x_get_supported_baud_rate,
746900 .device_get_information_about = pn53x_get_information_about,
747901
0
1 /**
2 * @file pn71xx.h
3 * @brief Driver for PN71XX using libnfc-nci library
4 */
5
6 #ifdef HAVE_CONFIG_H
7 # include "config.h"
8 #endif // HAVE_CONFIG_H
9
10 #include "pn71xx.h"
11
12 #include <stdio.h>
13 #include <inttypes.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <time.h>
18
19 #include <nfc/nfc.h>
20
21 #include "drivers.h"
22 #include "nfc-internal.h"
23
24 #include "linux_nfc_api.h"
25
26 #define PN71XX_DRIVER_NAME "pn71xx"
27
28 #define LOG_CATEGORY "libnfc.driver.pn71xx"
29 #define LOG_GROUP NFC_LOG_GROUP_DRIVER
30
31 const nfc_modulation_type pn71xx_supported_modulation_as_target[] = {NMT_ISO14443A, NMT_FELICA, NMT_ISO14443B, NMT_ISO14443BI, NMT_ISO14443B2SR, NMT_ISO14443B2CT, NMT_JEWEL, NMT_DEP, 0};
32 const nfc_modulation_type pn71xx_supported_modulation_as_initiator[] = {NMT_ISO14443A, NMT_FELICA, NMT_ISO14443B, NMT_ISO14443BI, NMT_ISO14443B2SR, NMT_ISO14443B2CT, NMT_JEWEL, NMT_DEP, 0};
33
34 const nfc_baud_rate pn71xx_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
35 const nfc_baud_rate pn71xx_felica_supported_baud_rates[] = { NBR_424, NBR_212, 0 };
36 const nfc_baud_rate pn71xx_dep_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 };
37 const nfc_baud_rate pn71xx_jewel_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
38 const nfc_baud_rate pn71xx_iso14443b_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
39
40 static nfcTagCallback_t TagCB;
41 static nfc_tag_info_t *TagInfo = NULL;
42
43 static void onTagArrival(nfc_tag_info_t *pTagInfo);
44 static void onTagDeparture(void);
45
46 /** ------------------------------------------------------------------------ */
47 /** ------------------------------------------------------------------------ */
48 /**
49 * @brief Initialize libnfc_nci library to verify presence of PN71xx device.
50 *
51 * @param context NFC context.
52 * @param connstrings array of 'nfc_connstring' buffer (allocated by caller). It is used to store the
53 * connection info strings of devices found.
54 * @param connstrings_len length of the connstrings array.
55 * @return number of devices found.
56 */
57 static size_t
58 pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
59 {
60 size_t device_found = 0;
61
62 if ((context == NULL) || (connstrings_len == 0)) return 0;
63
64 if (nfcManager_doInitialize() == 0) {
65 nfc_connstring connstring = "pn71xx";
66 memcpy(connstrings[device_found++], connstring, sizeof(nfc_connstring));
67 }
68
69 return device_found;
70 }
71
72 /**
73 * @brief Close connection to PN71xx by stopping the discovery loop and deinitializing the libnfc_nci library.
74 *
75 * @param pnd pointer on the device to close.
76 */
77 static void
78 pn71xx_close(nfc_device *pnd)
79 {
80 nfcManager_disableDiscovery();
81 nfcManager_deregisterTagCallback();
82 nfcManager_doDeinitialize();
83 nfc_device_free(pnd);
84 pnd = NULL;
85 }
86
87 /**
88 * @brief Open a connection to PN71xx, starting the discovery loop for tag detection.
89 *
90 * @param context NFC context.
91 * @param connstring connection info to the device
92 * @return pointer to the device, or NULL in case of error.
93 */
94 static nfc_device *
95 pn71xx_open(const nfc_context *context, const nfc_connstring connstring)
96 {
97 nfc_device *pnd;
98
99 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "open: %s", connstring);
100
101 pnd = nfc_device_new(context, connstring);
102 if (!pnd) {
103 perror("malloc");
104 return NULL;
105 }
106
107 pnd->driver = &pn71xx_driver;
108 strcpy(pnd->name, "pn71xx-device");
109 strcpy(pnd->connstring, connstring);
110
111 TagCB.onTagArrival = onTagArrival;
112 TagCB.onTagDeparture = onTagDeparture;
113 nfcManager_registerTagCallback(&TagCB);
114
115 nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 1, 0, 0);
116
117 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "wait 1 seconds for polling");
118 sleep(1);
119
120 return pnd;
121 }
122
123 /** ------------------------------------------------------------------------ */
124 /** ------------------------------------------------------------------------ */
125 static bool IsTechnology(nfc_tag_info_t *TagInfo, nfc_modulation_type nmt)
126 {
127 switch (nmt) {
128 case NMT_ISO14443A:
129 if (TagInfo->technology == TARGET_TYPE_ISO14443_4
130 || TagInfo->technology == TARGET_TYPE_ISO14443_3A
131 || TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC
132 || TagInfo->technology == TARGET_TYPE_MIFARE_UL)
133 return true;
134 break;
135
136 case NMT_ISO14443B:
137 case NMT_ISO14443BI:
138 case NMT_ISO14443B2SR:
139 case NMT_ISO14443B2CT:
140 if (TagInfo->technology == TARGET_TYPE_ISO14443_3B)
141 return true;
142 break;
143
144 case NMT_FELICA:
145 if (TagInfo->technology == TARGET_TYPE_FELICA)
146 return true;
147 break;
148
149 case NMT_JEWEL:
150 if (TagInfo->technology == TARGET_TYPE_ISO14443_3A
151 && TagInfo->protocol == NFA_PROTOCOL_T1T)
152 return true;
153 break;
154
155 default:
156 return false;
157 }
158 return false;
159 }
160
161 static void BufferPrintBytes(char *buffer, unsigned int buflen, const uint8_t *data, unsigned int datalen)
162 {
163 int cx = 0;
164 for (unsigned int i = 0x00; i < datalen; i++) {
165 cx += snprintf(buffer + cx, buflen - cx, "%02X ", data[i]);
166 }
167 }
168
169 static void PrintTagInfo(nfc_tag_info_t *TagInfo)
170 {
171 switch (TagInfo->technology) {
172 case TARGET_TYPE_UNKNOWN: {
173 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Unknown'");
174 }
175 break;
176 case TARGET_TYPE_ISO14443_3A: {
177 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 3A'");
178 }
179 break;
180 case TARGET_TYPE_ISO14443_3B: {
181 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 3B'");
182 }
183 break;
184 case TARGET_TYPE_ISO14443_4: {
185 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4A'");
186 }
187 break;
188 case TARGET_TYPE_FELICA: {
189 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type F'");
190 }
191 break;
192 case TARGET_TYPE_ISO15693: {
193 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type V'");
194 }
195 break;
196 case TARGET_TYPE_NDEF: {
197 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type NDEF'");
198 }
199 break;
200 case TARGET_TYPE_NDEF_FORMATABLE: {
201 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Formatable'");
202 }
203 break;
204 case TARGET_TYPE_MIFARE_CLASSIC: {
205 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Classic'");
206 }
207 break;
208 case TARGET_TYPE_MIFARE_UL: {
209 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Ul'");
210 }
211 break;
212 case TARGET_TYPE_KOVIO_BARCODE: {
213 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Kovio Barcode'");
214 }
215 break;
216 case TARGET_TYPE_ISO14443_3A_3B: {
217 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A/B'");
218 }
219 break;
220 default: {
221 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type %d (Unknown or not supported)'\n", TagInfo->technology);
222 }
223 break;
224 }
225 /*32 is max UID len (Kovio tags)*/
226 if ((0x00 != TagInfo->uid_length) && (32 >= TagInfo->uid_length)) {
227 char buffer [100];
228 int cx = 0;
229
230 if (4 == TagInfo->uid_length || 7 == TagInfo->uid_length || 10 == TagInfo->uid_length) {
231 cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID1 : \t'");
232 } else if (8 == TagInfo->uid_length) {
233 cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID2 : \t'");
234 } else {
235 cx += snprintf(buffer + cx, sizeof(buffer) - cx, "UID : \t'");
236 }
237
238 BufferPrintBytes(buffer + cx, sizeof(buffer) - cx, (unsigned char *) TagInfo->uid, TagInfo->uid_length);
239 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s'", buffer);
240 }
241 }
242
243 /** ------------------------------------------------------------------------ */
244 /** ------------------------------------------------------------------------ */
245
246 static void onTagArrival(nfc_tag_info_t *pTagInfo)
247 {
248 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag found");
249
250 TagInfo = malloc(sizeof(nfc_tag_info_t));
251 memcpy(TagInfo, pTagInfo, sizeof(nfc_tag_info_t));
252
253 PrintTagInfo(TagInfo);
254 }
255
256 static void onTagDeparture(void)
257 {
258 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag lost");
259
260 free(TagInfo);
261 TagInfo = NULL;
262 }
263
264 static int
265 pn71xx_initiator_init(struct nfc_device *pnd)
266 {
267 if (pnd == NULL) return NFC_EIO;
268 return NFC_SUCCESS;
269 }
270
271 static int
272 pn71xx_initiator_select_passive_target(struct nfc_device *pnd,
273 const nfc_modulation nm,
274 const uint8_t *pbtInitData, const size_t szInitData,
275 nfc_target *pnt)
276 {
277 if (pnd == NULL) return NFC_EIO;
278
279 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "select_passive_target");
280
281 if (TagInfo) {
282
283 nfc_target nttmp;
284 memset(&nttmp, 0x00, sizeof(nfc_target));
285 nttmp.nm = nm;
286
287 void *uidPtr = NULL;
288 unsigned int maxLen = 0;
289
290 switch (nm.nmt) {
291 case NMT_ISO14443A:
292 if (IsTechnology(TagInfo, nm.nmt)) {
293 maxLen = 10;
294 uidPtr = nttmp.nti.nai.abtUid;
295
296 if (TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC) {
297 nttmp.nti.nai.btSak = 0x08;
298 } else {
299 // make hardcoded desfire for freefare lib check
300 nttmp.nti.nai.btSak = 0x20;
301 nttmp.nti.nai.szAtsLen = 5;
302 memcpy(nttmp.nti.nai.abtAts, "\x75\x77\x81\x02", 4);
303 }
304 }
305 break;
306
307 case NMT_ISO14443B:
308 if (IsTechnology(TagInfo, nm.nmt)) {
309 maxLen = 4;
310 uidPtr = nttmp.nti.nbi.abtPupi;
311 }
312 break;
313
314 case NMT_ISO14443BI:
315 if (IsTechnology(TagInfo, nm.nmt)) {
316 maxLen = 4;
317 uidPtr = nttmp.nti.nii.abtDIV;
318 }
319 break;
320
321 case NMT_ISO14443B2SR:
322 if (IsTechnology(TagInfo, nm.nmt)) {
323 maxLen = 8;
324 uidPtr = nttmp.nti.nsi.abtUID;
325 }
326 break;
327
328 case NMT_ISO14443B2CT:
329 if (IsTechnology(TagInfo, nm.nmt)) {
330 maxLen = 4;
331 uidPtr = nttmp.nti.nci.abtUID;
332 }
333 break;
334
335 case NMT_FELICA:
336 if (IsTechnology(TagInfo, nm.nmt)) {
337 maxLen = 8;
338 uidPtr = nttmp.nti.nfi.abtId;
339 }
340 break;
341
342 case NMT_JEWEL:
343 if (IsTechnology(TagInfo, nm.nmt)) {
344 maxLen = 4;
345 uidPtr = nttmp.nti.nji.btId;
346 }
347 break;
348
349 default:
350 return 0;
351 }
352
353 if (uidPtr && TagInfo->uid_length) {
354 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "target found");
355 int len = TagInfo->uid_length > maxLen ? maxLen : TagInfo->uid_length;
356 memcpy(uidPtr, TagInfo->uid, len);
357 if (nm.nmt == NMT_ISO14443A)
358 nttmp.nti.nai.szUidLen = len;
359
360 // Is a tag info struct available
361 if (pnt) {
362 memcpy(pnt, &nttmp, sizeof(nfc_target));
363 }
364 return 1;
365 }
366 }
367
368 return 0;
369 }
370
371 static int
372 pn71xx_initiator_deselect_target(struct nfc_device *pnd)
373 {
374 if (pnd == NULL) return NFC_EIO;
375 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "deselect_passive_target");
376 return NFC_SUCCESS;
377 }
378
379
380 static int
381 pn71xx_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx,
382 const size_t szRx, int timeout)
383 {
384 if (pnd == NULL) return NFC_EIO;
385 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "transceive_bytes timeout=%d", timeout);
386
387 if (!TagInfo) return NFC_EINVARG;
388
389 char buffer[500];
390 BufferPrintBytes(buffer, sizeof(buffer), pbtTx, szTx);
391 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "===> %s", buffer);
392
393 int received = nfcTag_transceive(TagInfo->handle, (uint8_t *) pbtTx, szTx, pbtRx, szRx, 500);
394 if (received <= 0)
395 return NFC_EIO;
396
397 BufferPrintBytes(buffer, sizeof(buffer), pbtRx, received);
398 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "<=== %s", buffer);
399
400 return received;
401 }
402
403 static int
404 pn71xx_initiator_poll_target(struct nfc_device *pnd,
405 const nfc_modulation *pnmModulations, const size_t szModulations,
406 const uint8_t uiPollNr, const uint8_t uiPeriod,
407 nfc_target *pnt)
408 {
409 static int periodFactor = 150000;
410 int period = uiPeriod * periodFactor;
411
412 if (pnd == NULL) return 0;
413
414 for (int j = 0; j < uiPollNr; j++) {
415 for (unsigned int i = 0; i < szModulations; i++) {
416 const nfc_modulation nm = pnmModulations[i];
417
418 nfc_target nt;
419 int res = pn71xx_initiator_select_passive_target(pnd, nm, 0, 0, &nt);
420 if (res > 0 && pnt) {
421 memcpy(pnt, &nt, sizeof(nfc_target));
422 return res;
423 }
424 }
425 usleep(period);
426 }
427
428 return 0;
429 }
430
431 static int
432 pn71xx_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
433 {
434 if ((pnd == NULL) || (pnt == NULL)) return 1;
435 return !TagInfo;
436 }
437
438
439 /** ------------------------------------------------------------------------ */
440 /** ------------------------------------------------------------------------ */
441 static int
442 pn71xx_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
443 {
444 if (pnd == NULL) return NFC_EIO;
445
446 switch (mode) {
447 case N_TARGET:
448 *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_target;
449 break;
450 case N_INITIATOR:
451 *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_initiator;
452 break;
453 default:
454 return NFC_EINVARG;
455 }
456 return NFC_SUCCESS;
457 }
458
459 static int
460 pn71xx_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
461 {
462 if (pnd == NULL) return NFC_EIO;
463 if (mode) {}
464
465 switch (nmt) {
466 case NMT_FELICA:
467 *supported_br = (nfc_baud_rate *)pn71xx_felica_supported_baud_rates;
468 break;
469 case NMT_ISO14443A:
470 *supported_br = (nfc_baud_rate *)pn71xx_iso14443a_supported_baud_rates;
471 break;
472 case NMT_ISO14443B:
473 case NMT_ISO14443BI:
474 case NMT_ISO14443B2SR:
475 case NMT_ISO14443B2CT:
476 *supported_br = (nfc_baud_rate *)pn71xx_iso14443b_supported_baud_rates;
477 break;
478 case NMT_JEWEL:
479 *supported_br = (nfc_baud_rate *)pn71xx_jewel_supported_baud_rates;
480 break;
481 case NMT_DEP:
482 *supported_br = (nfc_baud_rate *)pn71xx_dep_supported_baud_rates;
483 break;
484 default:
485 return NFC_EINVARG;
486 }
487 return NFC_SUCCESS;
488 }
489
490 /** ------------------------------------------------------------------------ */
491 /** ------------------------------------------------------------------------ */
492
493 static int
494 pn71xx_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable)
495 {
496 if (pnd == NULL) return NFC_EIO;
497 return NFC_SUCCESS;
498 }
499
500 static int
501 pn71xx_set_property_int(struct nfc_device *pnd, const nfc_property property, const int value)
502 {
503 if (pnd == NULL) return NFC_EIO;
504 return NFC_SUCCESS;
505 }
506
507 static int
508 pn71xx_get_information_about(nfc_device *pnd, char **pbuf)
509 {
510 static const char *info = "PN71XX nfc driver using libnfc-nci userspace library";
511 size_t buflen = strlen(info) + 1;
512
513 if (pnd == NULL) return NFC_EIO;
514
515 *pbuf = malloc(buflen);
516 memcpy(*pbuf, info, buflen);
517
518 return buflen;
519 }
520 /**
521 * @brief Abort any pending operation
522 *
523 * @param pnd pointer on the NFC device.
524 * @return NFC_SUCCESS
525 */
526 static int
527 pn71xx_abort_command(nfc_device *pnd)
528 {
529 if (pnd == NULL) return NFC_EIO;
530 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "abort_command");
531 return NFC_SUCCESS;
532 }
533
534 static int
535 pn71xx_idle(struct nfc_device *pnd)
536 {
537 if (pnd == NULL) return NFC_EIO;
538 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "idle");
539 return NFC_SUCCESS;
540 }
541
542 static int
543 pn71xx_PowerDown(struct nfc_device *pnd)
544 {
545 if (pnd == NULL) return NFC_EIO;
546 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "PowerDown");
547 return NFC_SUCCESS;
548 }
549
550 /** ------------------------------------------------------------------------ */
551 /** ------------------------------------------------------------------------ */
552 const struct nfc_driver pn71xx_driver = {
553 .name = PN71XX_DRIVER_NAME,
554 .scan_type = NOT_INTRUSIVE,
555 .scan = pn71xx_scan,
556 .open = pn71xx_open,
557 .close = pn71xx_close,
558 .strerror = NULL,
559
560 .initiator_init = pn71xx_initiator_init,
561 .initiator_init_secure_element = NULL,
562 .initiator_select_passive_target = pn71xx_initiator_select_passive_target,
563 .initiator_poll_target = pn71xx_initiator_poll_target,
564 .initiator_select_dep_target = NULL,
565 .initiator_deselect_target = pn71xx_initiator_deselect_target,
566 .initiator_transceive_bytes = pn71xx_initiator_transceive_bytes,
567 .initiator_transceive_bits = NULL,
568 .initiator_transceive_bytes_timed = NULL,
569 .initiator_transceive_bits_timed = NULL,
570 .initiator_target_is_present = pn71xx_initiator_target_is_present,
571
572 .target_init = NULL,
573 .target_send_bytes = NULL,
574 .target_receive_bytes = NULL,
575 .target_send_bits = NULL,
576 .target_receive_bits = NULL,
577
578 .device_set_property_bool = pn71xx_set_property_bool,
579 .device_set_property_int = pn71xx_set_property_int,
580 .get_supported_modulation = pn71xx_get_supported_modulation,
581 .get_supported_baud_rate = pn71xx_get_supported_baud_rate,
582 .device_get_information_about = pn71xx_get_information_about,
583
584 .abort_command = pn71xx_abort_command,
585 .idle = pn71xx_idle,
586 .powerdown = pn71xx_PowerDown,
587 };
588
0 /**
1 * @file pn71xx.h
2 * @brief Driver for PN71XX using libnfc-nci library
3 */
4
5 #ifndef __NFC_DRIVER_PN71XX_H__
6 #define __NFC_DRIVER_PN71XX_H__
7
8 #include <nfc/nfc-types.h>
9
10 /* Reference to the driver structure */
11 extern const struct nfc_driver pn71xx_driver;
12
13 #endif // ! __NFC_DRIVER_7120_H__
4646 void
4747 iso14443a_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc)
4848 {
49 uint8_t bt;
5049 uint32_t wCrc = 0x6363;
5150
5251 do {
52 uint8_t bt;
5353 bt = *pbtData++;
5454 bt = (bt ^ (uint8_t)(wCrc & 0x00FF));
5555 bt = (bt ^ (bt << 4));
7777 void
7878 iso14443b_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc)
7979 {
80 uint8_t bt;
8180 uint32_t wCrc = 0xFFFF;
8281
8382 do {
83 uint8_t bt;
8484 bt = *pbtData++;
8585 bt = (bt ^ (uint8_t)(wCrc & 0x00FF));
8686 bt = (bt ^ (bt << 4));
3838 uint8_t mirror(uint8_t bt);
3939 uint32_t mirror32(uint32_t ui32Bits);
4040 uint64_t mirror64(uint64_t ui64Bits);
41 void mirror_uint8_ts(uint8_t *pbts, size_t szLen);
4241
4342 #endif // _LIBNFC_MIRROR_SUBR_H_
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
168169 prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t *pszInitiatorData)
169170 {
170171 switch (nm.nmt) {
171 case NMT_ISO14443B: {
172 case NMT_ISO14443B:
172173 // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
173174 *ppbtInitiatorData = (uint8_t *) "\x00";
174175 *pszInitiatorData = 1;
175 }
176 break;
177 case NMT_ISO14443BI: {
176 break;
177 case NMT_ISO14443BI:
178178 // APGEN
179179 *ppbtInitiatorData = (uint8_t *) "\x01\x0b\x3f\x80";
180180 *pszInitiatorData = 4;
181 }
182 break;
183 case NMT_ISO14443B2SR: {
184 // Get_UID
185 *ppbtInitiatorData = (uint8_t *) "\x0b";
186 *pszInitiatorData = 1;
187 }
188 break;
189 case NMT_ISO14443B2CT: {
190 // SELECT-ALL
191 *ppbtInitiatorData = (uint8_t *) "\x9F\xFF\xFF";
192 *pszInitiatorData = 3;
193 }
194 break;
195 case NMT_FELICA: {
181 break;
182 case NMT_FELICA:
196183 // polling payload must be present (see ISO/IEC 18092 11.2.2.5)
197184 *ppbtInitiatorData = (uint8_t *) "\x00\xff\xff\x01\x00";
198185 *pszInitiatorData = 5;
199 }
200 break;
186 break;
201187 case NMT_ISO14443A:
188 case NMT_ISO14443B2CT:
189 case NMT_ISO14443B2SR:
190 case NMT_ISO14443BICLASS:
202191 case NMT_JEWEL:
192 case NMT_BARCODE:
203193 case NMT_DEP:
204194 *ppbtInitiatorData = NULL;
205195 *pszInitiatorData = 0;
241231 int res = sscanf(connstring, format, param0, param1, param2);
242232
243233 if (res < 1 || ((0 != strcmp(param0, driver_name)) &&
244 (bus_name != NULL) &&
245234 (0 != strcmp(param0, bus_name)))) {
246235 // Driver name does not match.
247236 res = 0;
147147 int (*device_set_property_bool)(struct nfc_device *pnd, const nfc_property property, const bool bEnable);
148148 int (*device_set_property_int)(struct nfc_device *pnd, const nfc_property property, const int value);
149149 int (*get_supported_modulation)(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt);
150 int (*get_supported_baud_rate)(struct nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
150 int (*get_supported_baud_rate)(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
151151 int (*device_get_information_about)(struct nfc_device *pnd, char **buf);
152152
153153 int (*abort_command)(struct nfc_device *pnd);
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
7879 #include <stdlib.h>
7980 #include <stddef.h>
8081 #include <string.h>
82 #include <assert.h>
8183
8284 #include <nfc/nfc.h>
8385
8587 #include "target-subr.h"
8688 #include "drivers.h"
8789
90 #if defined (DRIVER_PCSC_ENABLED)
91 # include "drivers/pcsc.h"
92 #endif /* DRIVER_PCSC_ENABLED */
93
8894 #if defined (DRIVER_ACR122_PCSC_ENABLED)
8995 # include "drivers/acr122_pcsc.h"
9096 #endif /* DRIVER_ACR122_PCSC_ENABLED */
116122 #if defined (DRIVER_PN532_I2C_ENABLED)
117123 # include "drivers/pn532_i2c.h"
118124 #endif /* DRIVER_PN532_I2C_ENABLED */
125
126 #if defined (DRIVER_PN71XX_ENABLED)
127 # include "drivers/pn71xx.h"
128 #endif /* DRIVER_PN71XX_ENABLED */
119129
120130
121131 #define LOG_CATEGORY "libnfc.general"
128138
129139 const struct nfc_driver_list *nfc_drivers = NULL;
130140
141 // descritions for debugging
142 const char *nfc_property_name[] = {
143 "NP_TIMEOUT_COMMAND",
144 "NP_TIMEOUT_ATR",
145 "NP_TIMEOUT_COM",
146 "NP_HANDLE_CRC",
147 "NP_HANDLE_PARITY",
148 "NP_ACTIVATE_FIELD",
149 "NP_ACTIVATE_CRYPTO1",
150 "NP_INFINITE_SELECT",
151 "NP_ACCEPT_INVALID_FRAMES",
152 "NP_ACCEPT_MULTIPLE_FRAMES",
153 "NP_AUTO_ISO14443_4",
154 "NP_EASY_FRAMING",
155 "NP_FORCE_ISO14443_A",
156 "NP_FORCE_ISO14443_B",
157 "NP_FORCE_SPEED_106"
158 };
159
131160 static void
132161 nfc_drivers_init(void)
133162 {
134163 #if defined (DRIVER_PN53X_USB_ENABLED)
135164 nfc_register_driver(&pn53x_usb_driver);
136165 #endif /* DRIVER_PN53X_USB_ENABLED */
166 #if defined (DRIVER_PCSC_ENABLED)
167 nfc_register_driver(&pcsc_driver);
168 #endif /* DRIVER_ACR122_PCSC_ENABLED */
137169 #if defined (DRIVER_ACR122_PCSC_ENABLED)
138170 nfc_register_driver(&acr122_pcsc_driver);
139171 #endif /* DRIVER_ACR122_PCSC_ENABLED */
155187 #if defined (DRIVER_ARYGON_ENABLED)
156188 nfc_register_driver(&arygon_driver);
157189 #endif /* DRIVER_ARYGON_ENABLED */
158 }
159
190 #if defined (DRIVER_PN71XX_ENABLED)
191 nfc_register_driver(&pn71xx_driver);
192 #endif /* DRIVER_PN71XX_ENABLED */
193 }
194
195 static int
196 nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation *nm);
160197
161198 /** @ingroup lib
162199 * @brief Register an NFC device driver with libnfc.
168205 int
169206 nfc_register_driver(const struct nfc_driver *ndr)
170207 {
171 if (!ndr)
208 if (!ndr) {
209 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_register_driver returning NFC_EINVARG");
172210 return NFC_EINVARG;
211 }
173212
174213 struct nfc_driver_list *pndl = (struct nfc_driver_list *)malloc(sizeof(struct nfc_driver_list));
175214 if (!pndl)
273312 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Unable to open \"%s\".", ncs);
274313 return NULL;
275314 }
276 for (uint32_t i = 0; i > context->user_defined_device_count; i++) {
315 for (uint32_t i = 0; i < context->user_defined_device_count; i++) {
277316 if (strcmp(ncs, context->user_defined_devices[i].connstring) == 0) {
278317 // This is a device sets by user, we use the device name given by user
279318 strcpy(pnd->name, context->user_defined_devices[i].name);
385424 pndl = pndl->next;
386425 }
387426 } else if (context->user_defined_device_count == 0) {
388 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s" , "user must specify device(s) manually when autoscan is disabled");
427 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s", "user must specify device(s) manually when autoscan is disabled");
389428 }
390429
391430 return device_found;
405444 int
406445 nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value)
407446 {
447 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_int %s %s", nfc_property_name[property], value ? "True" : "False");
408448 HAL(device_set_property_int, pnd, property, value);
409449 }
410450
424464 int
425465 nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
426466 {
467 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_bool %s %s", nfc_property_name[property], bEnable ? "True" : "False");
427468 HAL(device_set_property_bool, pnd, property, bEnable);
428469 }
429470
479520 }
480521
481522 /** @ingroup initiator
482 * @brief Initialize NFC device as initiator with its secure element initiator (reader)
523 * @brief Initialize NFC device as initiator with its secure element as target (reader)
483524 * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
484525 * @param pnd \a nfc_device struct pointer that represent currently used device
485526 *
486527 * The NFC device is configured to function as secure element reader.
487528 * After initialization it can be used to communicate with the secure element.
488 * @note RF field is desactvated in order to some power
529 * @note RF field is deactivated in order to save some power
489530 */
490531 int
491532 nfc_initiator_init_secure_element(nfc_device *pnd)
525566 uint8_t *abtInit = NULL;
526567 uint8_t abtTmpInit[MAX(12, szInitData)];
527568 size_t szInit = 0;
569 int res;
570 if ((res = nfc_device_validate_modulation(pnd, N_INITIATOR, &nm)) != NFC_SUCCESS)
571 return res;
528572 if (szInitData == 0) {
529573 // Provide default values, if any
530574 prepare_initiator_data(nm, &abtInit, &szInit);
595639 break;
596640 }
597641 nfc_initiator_deselect_target(pnd);
598 // deselect has no effect on FeliCa and Jewel cards so we'll stop after one...
642 // deselect has no effect on FeliCa, Jewel and Thinfilm cards so we'll stop after one...
599643 // ISO/IEC 14443 B' cards are polled at 100% probability so it's not possible to detect correctly two cards at the same time
600 if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL) || (nm.nmt == NMT_ISO14443BI) || (nm.nmt == NMT_ISO14443B2SR) || (nm.nmt == NMT_ISO14443B2CT)) {
644 if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL) || (nm.nmt == NMT_BARCODE) ||
645 (nm.nmt == NMT_ISO14443BI) || (nm.nmt == NMT_ISO14443B2SR) || (nm.nmt == NMT_ISO14443B2CT)) {
601646 break;
602647 }
603648 }
639684 * @param pnd \a nfc_device struct pointer that represent currently used device
640685 * @param ndm desired D.E.P. mode (\a NDM_ACTIVE or \a NDM_PASSIVE for active, respectively passive mode)
641686 * @param nbr desired baud rate
642 * @param ndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL)
687 * @param pndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL)
643688 * @param[out] pnt is a \a nfc_target struct pointer where target information will be put.
644689 * @param timeout in milliseconds
645690 *
667712 * @param pnd \a nfc_device struct pointer that represent currently used device
668713 * @param ndm desired D.E.P. mode (\a NDM_ACTIVE or \a NDM_PASSIVE for active, respectively passive mode)
669714 * @param nbr desired baud rate
670 * @param ndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL)
715 * @param pndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL)
671716 * @param[out] pnt is a \a nfc_target struct pointer where target information will be put.
672717 * @param timeout in milliseconds
673718 *
9661011 * @param pnd \a nfc_device struct pointer that represent currently used device
9671012 *
9681013 * This function switch the device in idle mode.
969 * In initiator mode, the RF field is turned off and the device is set to low power mode (if avaible);
1014 * In initiator mode, the RF field is turned off and the device is set to low power mode (if available);
9701015 * In target mode, the emulation is stoped (no target available from external initiator) and the device is set to low power mode (if avaible).
9711016 */
9721017 int
11921237 }
11931238
11941239 /** @ingroup data
1195 * @brief Get supported baud rates.
1240 * @brief Get supported baud rates (initiator mode).
11961241 * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
11971242 * @param pnd \a nfc_device struct pointer that represent currently used device
11981243 * @param nmt \a nfc_modulation_type.
12021247 int
12031248 nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
12041249 {
1205 HAL(get_supported_baud_rate, pnd, nmt, supported_br);
1250 HAL(get_supported_baud_rate, pnd, N_INITIATOR, nmt, supported_br);
1251 }
1252
1253 /** @ingroup data
1254 * @brief Get supported baud rates for target mode.
1255 * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
1256 * @param pnd \a nfc_device struct pointer that represent currently used device
1257 * @param nmt \a nfc_modulation_type.
1258 * @param supported_br pointer of \a nfc_baud_rate array.
1259 *
1260 */
1261 int
1262 nfc_device_get_supported_baud_rate_target_mode(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
1263 {
1264 HAL(get_supported_baud_rate, pnd, N_TARGET, nmt, supported_br);
1265 }
1266
1267 /** @ingroup data
1268 * @brief Validate combination of modulation and baud rate on the currently used device.
1269 * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
1270 * @param pnd \a nfc_device struct pointer that represent currently used device
1271 * @param mode \a nfc_mode.
1272 * @param nm \a nfc_modulation.
1273 *
1274 */
1275 static int
1276 nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation *nm)
1277 {
1278 int res;
1279 const nfc_modulation_type *nmt = NULL;
1280 if ((res = nfc_device_get_supported_modulation(pnd, mode, &nmt)) < 0) {
1281 return res;
1282 }
1283 assert(nmt != NULL);
1284 for (int i = 0; nmt[i]; i++) {
1285 if (nmt[i] == nm->nmt) {
1286 const nfc_baud_rate *nbr = NULL;
1287 if (mode == N_INITIATOR) {
1288 if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) {
1289 return res;
1290 }
1291 } else {
1292 if ((res = nfc_device_get_supported_baud_rate_target_mode(pnd, nmt[i], &nbr)) < 0) {
1293 return res;
1294 }
1295 }
1296 assert(nbr != NULL);
1297 for (int j = 0; nbr[j]; j++) {
1298 if (nbr[j] == nm->nbr)
1299 return NFC_SUCCESS;
1300 }
1301 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_device_validate_modulation returning NFC_EINVARG");
1302 return NFC_EINVARG;
1303 }
1304 }
1305 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_device_validate_modulation returning NFC_EINVARG");
1306 return NFC_EINVARG;
12061307 }
12071308
12081309 /* Misc. functions */
12511352 /** @ingroup string-converter
12521353 * @brief Convert \a nfc_baud_rate value to string
12531354 * @return Returns nfc baud rate
1254 * @param \a nfc_baud_rate to convert
1355 * @param nbr \a nfc_baud_rate to convert
12551356 */
12561357 const char *
12571358 str_nfc_baud_rate(const nfc_baud_rate nbr)
12591360 switch (nbr) {
12601361 case NBR_UNDEFINED:
12611362 return "undefined baud rate";
1262 break;
12631363 case NBR_106:
12641364 return "106 kbps";
1265 break;
12661365 case NBR_212:
12671366 return "212 kbps";
1268 break;
12691367 case NBR_424:
12701368 return "424 kbps";
1271 break;
12721369 case NBR_847:
12731370 return "847 kbps";
1274 break;
1275 }
1276 // Should never go there..
1277 return "";
1371 }
1372
1373 return "???";
12781374 }
12791375
12801376 /** @ingroup string-converter
12811377 * @brief Convert \a nfc_modulation_type value to string
12821378 * @return Returns nfc modulation type
1283 * @param \a nfc_modulation_type to convert
1379 * @param nmt \a nfc_modulation_type to convert
12841380 */
12851381 const char *
12861382 str_nfc_modulation_type(const nfc_modulation_type nmt)
12881384 switch (nmt) {
12891385 case NMT_ISO14443A:
12901386 return "ISO/IEC 14443A";
1291 break;
12921387 case NMT_ISO14443B:
12931388 return "ISO/IEC 14443-4B";
1294 break;
12951389 case NMT_ISO14443BI:
12961390 return "ISO/IEC 14443-4B'";
1297 break;
1391 case NMT_ISO14443BICLASS:
1392 return "ISO/IEC 14443-2B-3B iClass (Picopass)";
12981393 case NMT_ISO14443B2CT:
12991394 return "ISO/IEC 14443-2B ASK CTx";
1300 break;
13011395 case NMT_ISO14443B2SR:
13021396 return "ISO/IEC 14443-2B ST SRx";
1303 break;
13041397 case NMT_FELICA:
13051398 return "FeliCa";
1306 break;
13071399 case NMT_JEWEL:
13081400 return "Innovision Jewel";
1309 break;
1401 case NMT_BARCODE:
1402 return "Thinfilm NFC Barcode";
13101403 case NMT_DEP:
13111404 return "D.E.P.";
1312 break;
1313 }
1314 // Should never go there..
1315 return "";
1405 }
1406
1407 return "???";
13161408 }
13171409
13181410 /** @ingroup string-converter
1319 * @brief Convert \a nfc_modulation_type value to string
1411 * @brief Convert \a nfc_target content to string
13201412 * @return Upon successful return, this function returns the number of characters printed (excluding the null byte used to end output to strings), otherwise returns libnfc's error code (negative value)
1321 * @param nt \a nfc_target struct to print
1413 * @param pnt \a nfc_target struct pointer to print
13221414 * @param buf pointer where string will be allocated, then nfc target information printed
1415 * @param verbose false for essential, true for detailed, human-readable, information
13231416 *
13241417 * @warning *buf must be freed using nfc_free()
13251418 */
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
497498 snprint_hex(dst + off, size - off, pnji->btId, 4);
498499 }
499500
501 void
502 snprint_nfc_barcode_info(char *dst, size_t size, const nfc_barcode_info *pnti, bool verbose)
503 {
504 (void) verbose;
505 int off = 0;
506 off += snprintf(dst + off, size - off, " Size (bits): %lu\n", (unsigned long)(pnti->szDataLen * 8));
507 off += snprintf(dst + off, size - off, " Content: ");
508 for (uint8_t i = 0; i < pnti->szDataLen; i++) {
509 off += snprintf(dst + off, size - off, "%02X", pnti->abtData[i]);
510 if ((i % 8 == 7) && (i < (pnti->szDataLen - 1))) {
511 off += snprintf(dst + off, size - off, "\n ");
512 }
513 }
514 snprintf(dst + off, size - off, "\n");
515 }
516
500517 #define PI_ISO14443_4_SUPPORTED 0x01
501518 #define PI_NAD_SUPPORTED 0x01
502519 #define PI_CID_SUPPORTED 0x02
593610 }
594611
595612 void
613 snprint_nfc_iso14443biclass_info(char *dst, size_t size, const nfc_iso14443biclass_info *pnic, bool verbose)
614 {
615 (void) verbose;
616 int off = 0;
617 off += snprintf(dst + off, size - off, " UID: ");
618 snprint_hex(dst + off, size - off, pnic->abtUID, 8);
619 }
620
621 void
596622 snprint_nfc_iso14443b2ct_info(char *dst, size_t size, const nfc_iso14443b2ct_info *pnci, bool verbose)
597623 {
598624 (void) verbose;
636662 case NMT_JEWEL:
637663 snprint_nfc_jewel_info(dst + off, size - off, &pnt->nti.nji, verbose);
638664 break;
665 case NMT_BARCODE:
666 snprint_nfc_barcode_info(dst + off, size - off, &pnt->nti.nti, verbose);
667 break;
639668 case NMT_FELICA:
640669 snprint_nfc_felica_info(dst + off, size - off, &pnt->nti.nfi, verbose);
641670 break;
648677 case NMT_ISO14443B2SR:
649678 snprint_nfc_iso14443b2sr_info(dst + off, size - off, &pnt->nti.nsi, verbose);
650679 break;
680 case NMT_ISO14443BICLASS:
681 snprint_nfc_iso14443biclass_info(dst + off, size - off, &pnt->nti.nhi, verbose);
682 break;
651683 case NMT_ISO14443B2CT:
652684 snprint_nfc_iso14443b2ct_info(dst + off, size - off, &pnt->nti.nci, verbose);
653685 break;
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * This program is free software: you can redistribute it and/or modify it
1314 * under the terms of the GNU Lesser General Public License as published by the
3637 void snprint_nfc_iso14443b_info(char *dst, size_t size, const nfc_iso14443b_info *pnbi, bool verbose);
3738 void snprint_nfc_iso14443bi_info(char *dst, size_t size, const nfc_iso14443bi_info *pnii, bool verbose);
3839 void snprint_nfc_iso14443b2sr_info(char *dst, size_t size, const nfc_iso14443b2sr_info *pnsi, bool verbose);
40 void snprint_nfc_iso14443biclass_info(char *dst, size_t size, const nfc_iso14443biclass_info *pnic, bool verbose);
3941 void snprint_nfc_iso14443b2ct_info(char *dst, size_t size, const nfc_iso14443b2ct_info *pnci, bool verbose);
4042 void snprint_nfc_felica_info(char *dst, size_t size, const nfc_felica_info *pnfi, bool verbose);
4143 void snprint_nfc_jewel_info(char *dst, size_t size, const nfc_jewel_info *pnji, bool verbose);
44 void snprint_nfc_barcode_info(char *dst, size_t size, const nfc_barcode_info *pnti, bool verbose);
4245 void snprint_nfc_dep_info(char *dst, size_t size, const nfc_dep_info *pndi, bool verbose);
4346 void snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose);
4447
33 [
44 AC_MSG_CHECKING(which drivers to build)
55 AC_ARG_WITH(drivers,
6 AS_HELP_STRING([--with-drivers=DRIVERS], [Use a custom driver set, where DRIVERS is a coma-separated list of drivers to build support for. Available drivers are: 'acr122_pcsc', 'acr122_usb', 'acr122s', 'arygon', 'pn532_i2c', 'pn532_spi', 'pn532_uart' and 'pn53x_usb'. Default drivers set is 'acr122_usb,acr122s,arygon,pn532_i2c,pn532_spi,pn532_uart,pn53x_usb'. The special driver set 'all' compile all available drivers.]),
6 AS_HELP_STRING([--with-drivers=DRIVERS], [Use a custom driver set, where DRIVERS is a coma-separated list of drivers to build support for. Available drivers are: 'acr122_pcsc', 'acr122_usb', 'acr122s', 'arygon', 'pcsc', 'pn532_i2c', 'pn532_spi', 'pn532_uart', 'pn53x_usb' and 'pn71xx'. Default drivers set is 'acr122_usb,acr122s,arygon,pn532_i2c,pn532_spi,pn532_uart,pn53x_usb'. The special driver set 'all' compile all available drivers.]),
7
78 [ case "${withval}" in
89 yes | no)
910 dnl ignore calls without any arguments
3536 fi
3637 ;;
3738 all)
38 DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart"
39 DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart pcsc"
40
3941 if test x"$spi_available" = x"yes"
4042 then
4143 DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_spi"
4446 then
4547 DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_i2c"
4648 fi
49 if test x"$nfc_nci_available" = x"yes"
50 then
51 DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn71xx"
52 fi
4753 ;;
4854 esac
4955
5056 DRIVERS_CFLAGS=""
5157
58 driver_pcsc_enabled="no"
5259 driver_acr122_pcsc_enabled="no"
5360 driver_acr122_usb_enabled="no"
5461 driver_acr122s_enabled="no"
5764 driver_pn532_uart_enabled="no"
5865 driver_pn532_spi_enabled="no"
5966 driver_pn532_i2c_enabled="no"
67 driver_pn71xx_enabled="no"
6068
6169 for driver in ${DRIVER_BUILD_LIST}
6270 do
6371 case "${driver}" in
72 pcsc)
73 pcsc_required="yes"
74 driver_pcsc_enabled="yes"
75 DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PCSC_ENABLED"
76 ;;
6477 acr122_pcsc)
6578 pcsc_required="yes"
6679 driver_acr122_pcsc_enabled="yes"
101114 driver_pn532_i2c_enabled="yes"
102115 DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN532_I2C_ENABLED"
103116 ;;
117 pn71xx)
118 nfc_nci_required="yes"
119 driver_pn71xx_enabled="yes"
120 DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN71XX_ENABLED"
121 ;;
104122 *)
105123 AC_MSG_ERROR([Unknow driver: $driver])
106124 ;;
108126 done
109127 AC_SUBST(DRIVERS_CFLAGS)
110128 AM_CONDITIONAL(DRIVER_ACR122_PCSC_ENABLED, [test x"$driver_acr122_pcsc_enabled" = xyes])
129 AM_CONDITIONAL(DRIVER_PCSC_ENABLED, [test x"$driver_pcsc_enabled" = xyes])
111130 AM_CONDITIONAL(DRIVER_ACR122_USB_ENABLED, [test x"$driver_acr122_usb_enabled" = xyes])
112131 AM_CONDITIONAL(DRIVER_ACR122S_ENABLED, [test x"$driver_acr122s_enabled" = xyes])
113132 AM_CONDITIONAL(DRIVER_PN53X_USB_ENABLED, [test x"$driver_pn53x_usb_enabled" = xyes])
115134 AM_CONDITIONAL(DRIVER_PN532_UART_ENABLED, [test x"$driver_pn532_uart_enabled" = xyes])
116135 AM_CONDITIONAL(DRIVER_PN532_SPI_ENABLED, [test x"$driver_pn532_spi_enabled" = xyes])
117136 AM_CONDITIONAL(DRIVER_PN532_I2C_ENABLED, [test x"$driver_pn532_i2c_enabled" = xyes])
137 AM_CONDITIONAL(DRIVER_PN71XX_ENABLED, [test x"$driver_pn71xx_enabled" = xyes])
118138 ])
119139
120140 AC_DEFUN([LIBNFC_DRIVERS_SUMMARY],[
121141 echo
122142 echo "Selected drivers:"
143 echo " pcsc............. $driver_pcsc_enabled"
123144 echo " acr122_pcsc...... $driver_acr122_pcsc_enabled"
124145 echo " acr122_usb....... $driver_acr122_usb_enabled"
125146 echo " acr122s.......... $driver_acr122s_enabled"
128149 echo " pn532_uart....... $driver_pn532_uart_enabled"
129150 echo " pn532_spi....... $driver_pn532_spi_enabled"
130151 echo " pn532_i2c........ $driver_pn532_i2c_enabled"
152 echo " pn71xx........... $driver_pn71xx_enabled"
131153 ])
0 #!/bin/sh
1 PROJECT_DIR=$(readlink -e $(dirname $0))
2 cd "$PROJECT_DIR"
3
4 WITH_USB=1
5
6 LIBUSB_WIN32_BIN_VERSION="1.2.6.0"
7 LIBUSB_WIN32_BIN_ARCHIVE="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION.zip"
8 LIBUSB_WIN32_BIN_URL="http://freefr.dl.sourceforge.net/project/libusb-win32/libusb-win32-releases/$LIBUSB_WIN32_BIN_VERSION/$LIBUSB_WIN32_BIN_ARCHIVE"
9 LIBUSB_WIN32_BIN_DIR="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION"
10
11 if [ "$WITH_USB" = "1" ]; then
12 if [ ! -d $LIBUSB_WIN32_BIN_DIR ]; then
13 wget -c $LIBUSB_WIN32_BIN_URL
14 unzip $LIBUSB_WIN32_BIN_ARCHIVE
15 fi
16 fi
17
18
19 rm -rf build
20 mkdir build
21 cd build
22
23
24 case $1 in
25 32*)
26 mingw32-cmake .. -DLIBUSB_INCLUDE_DIRS="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/include -DLIBUSB_LIBRARIES="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/bin/x86/libusb0_x86.dll -DLIBNFC_ROOT_DIR=$PWD/.. -DLIBNFC_SYSCONFDIR='C:\\Program Files (x86)\\libnfc\\config'
27 mingw32-make;;
28 64*)
29 mingw64-cmake .. -DLIBUSB_INCLUDE_DIRS="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/include -DLIBUSB_LIBRARIES="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/bin/amd64/libusb0.dll -DLIBNFC_ROOT_DIR=.. -DLIBNFC_SYSCONFDIR='C:\\Program Files\\libnfc\\config'
30 mingw64-make;;
31 *)
32 echo "specify whether to build 32-bit or 64-bit version by supplying 32 or 64 as parameter";;
33 esac
+0
-91
mingw-cross-configure.sh less more
0 #!/bin/sh
1
2 WITH_USB=1
3
4 LIBUSB_WIN32_BIN_VERSION="1.2.6.0"
5 LIBUSB_WIN32_BIN_ARCHIVE="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION.zip"
6 LIBUSB_WIN32_BIN_URL="http://freefr.dl.sourceforge.net/project/libusb-win32/libusb-win32-releases/$LIBUSB_WIN32_BIN_VERSION/$LIBUSB_WIN32_BIN_ARCHIVE"
7 LIBUSB_WIN32_BIN_DIR="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION"
8
9 if [ "$WITH_USB" = "1" ]; then
10 if [ ! -d $LIBUSB_WIN32_BIN_DIR ]; then
11 wget -c $LIBUSB_WIN32_BIN_URL
12 unzip $LIBUSB_WIN32_BIN_ARCHIVE
13 fi
14 fi
15
16 MINGW="${MINGW:=i686-w64-mingw32}"
17 MINGW_DIR="/usr/$MINGW"
18
19 # Use MinGW binaries before others
20 #export PATH=$MINGW_DIR/bin:$PATH
21
22 # Set CPATH to MinGW include files
23 export CPATH=$MINGW_DIR/include
24 export LD_LIBRARY_PATH=$MINGW_DIR/lib
25 export LD_RUN_PATH=$MINGW_DIR/lib
26
27 # Force pkg-config to search in cross environement directory
28 export PKG_CONFIG_LIBDIR=$MINGW_DIR/lib/pkgconfig
29
30 # Stop compilation on first error
31 export CFLAGS="-Wfatal-errors"
32
33 # Include default MinGW include directory, and libnfc's win32 files
34 export CFLAGS="$CFLAGS -I$MINGW_DIR/include -I$PWD/contrib/win32"
35
36 if [ "$MINGW" = "i686-w64-mingw32" ]; then
37 # mingw-64 includes winscard.a and winscard.h
38 #
39 # It is not enough to set libpcsclite_LIBS to "-lwinscard", because it is
40 # forgotten when libnfc is created with libtool. That's why we are setting
41 # LIBS.
42 export LIBS="-lwinscard"
43
44 echo "MinGW-w64 ships all requirements libnfc."
45 echo "Unfortunately the MinGW-w64 header are currently"
46 echo "buggy. Also, Libtool doesn't support MinGW-w64"
47 echo "very well."
48 echo ""
49 echo "Warning ________________________________________"
50 echo "You will only be able to compile libnfc.dll, but"
51 echo "none of the executables (see utils and examples)."
52 echo ""
53 # You can fix winbase.h by adding the following lines:
54 # #include <basetsd.h>
55 # #include <windef.h>
56 # But the problem with Libtool remains.
57 else
58 if [ -z "$libpcsclite_LIBS$libpcsclite_CFLAGS" ]; then
59 echo "Error __________________________________________"
60 echo "You need to get the PC/SC library from a Windows"
61 echo "machine and the appropriate header files. Then"
62 echo "specify libpcsclite_LIBS=.../WinScard.dll and"
63 echo "libpcsclite_CFLAGS=-I..."
64 fi
65 exit 1
66 fi
67
68 ## Configure to cross-compile using mingw32msvc
69 if [ "$WITH_USB" = "1" ]; then
70 # with direct-USB drivers (use libusb-win32)
71 DRIVERS="all"
72 else
73 # with UART divers only (can be tested under wine)
74 DRIVERS="pn532_uart,arygon"
75 fi
76
77 if [ ! -x configure ]; then
78 autoreconf -is
79 fi
80
81 ./configure --target=$MINGW --host=$MINGW \
82 --with-drivers=$DRIVERS \
83 --with-libusb-win32=$PWD/$LIBUSB_WIN32_BIN_DIR \
84 $*
85
86 if [ "$MINGW" = "i686-w64-mingw32" ]; then
87 # due to the buggy headers from MINGW-64 we always add "contrib/windows.h",
88 # otherwise some windows types won't be available.
89 echo "#include \"contrib/windows.h\"" >> config.h
90 fi
4444 echo-cutter:
4545 @echo $(CUTTER)
4646
47 EXTRA_DIST = run-test.sh
4847 CLEANFILES = *.gcno
4948
5049 endif
50 EXTRA_DIST = run-test.sh
4444 .nbr = NBR_106,
4545 };
4646 res = nfc_initiator_list_passive_targets(device, nm, ant, MAX_TARGET_COUNT);
47 cut_assert_operator_int(res, >= , 0, cut_message("nfc_initiator_list_passive_targets"));
47 cut_assert_operator_int(res, >=, 0, cut_message("nfc_initiator_list_passive_targets"));
4848
4949 nfc_close(device);
5050 }
8585
8686 uint8_t abtRx[1024];
8787 int res = nfc_target_init(device, &nt, abtRx, sizeof(abtRx), 0);
88 cut_assert_operator_int(res, > , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
88 cut_assert_operator_int(res, >, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
8989 if (res < 0) { thread_res = -1; return (void *) thread_res; }
9090
9191 res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500);
92 cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
92 cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
9393 const uint8_t abtAttRx[] = "Hello DEP target!";
9494 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
9595 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
9696
9797 const uint8_t abtTx[] = "Hello DEP initiator!";
9898 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
99 cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
99 cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
100100 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
101101
102102 return (void *) thread_res;
124124 // Active mode
125125 printf("=========== INITIATOR %s (Active mode / %s Kbps) =========\n", nfc_device_get_name(device), str_nfc_baud_rate(nbr));
126126 res = nfc_initiator_select_dep_target(device, NDM_ACTIVE, nbr, NULL, &nt, 1000);
127 cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
127 cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
128128 cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation"));
129129 cut_assert_equal_int(nbr, nt.nm.nbr, cut_message("Invalid target baud rate"));
130130 cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3"));
135135 const uint8_t abtTx[] = "Hello DEP target!";
136136 uint8_t abtRx[1024];
137137 res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 5000);
138 cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
138 cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
139139
140140 const uint8_t abtAttRx[] = "Hello DEP initiator!";
141141 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data (as initiator)"));
142142 if (res < 0) { thread_res = -1; return (void *) thread_res; }
143143 res = nfc_initiator_deselect_target(device);
144 cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
144 cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
145145 if (res < 0) { thread_res = -1; return (void *) thread_res; }
146146
147147 return (void *) thread_res;
8585 uint8_t abtRx[1024];
8686 size_t szRx = sizeof(abtRx);
8787 int res = nfc_target_init(device, &nt, abtRx, szRx, 0);
88 cut_assert_operator_int(res, > , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
88 cut_assert_operator_int(res, >, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
8989 if (res < 0) { thread_res = -1; return (void *) thread_res; }
9090
9191 // First pass
9292 res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500);
93 cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
93 cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
9494
9595 const uint8_t abtAttRx[] = "Hello DEP target!";
9696 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
9898
9999 const uint8_t abtTx[] = "Hello DEP initiator!";
100100 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
101 cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
101 cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
102102 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
103103
104104 // Second pass
105105 res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500);
106 cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
107
108 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
109 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
110
111 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
112 cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
106 cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
107
108 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
109 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
110
111 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
112 cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
113113 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
114114
115115 // Third pass
116116 res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500);
117 cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
118
119 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
120 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
121
122 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
123 cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
117 cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
118
119 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
120 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
121
122 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
123 cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
124124 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
125125
126126 // Fourth pass
127127 res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500);
128 cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
129
130 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
131 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
132
133 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
134 cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
128 cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
129
130 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
131 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
132
133 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
134 cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
135135 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
136136
137137 return (void *) thread_res;
159159 // Passive mode / 106Kbps
160160 printf("=========== INITIATOR %s (Passive mode / 106Kbps) =========\n", nfc_device_get_name(device));
161161 res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_106, NULL, &nt, 5000);
162 cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
162 cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
163163 cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation"));
164164 cut_assert_equal_int(NBR_106, nt.nm.nbr, cut_message("Invalid target baud rate"));
165165 cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3"));
170170 const uint8_t abtTx[] = "Hello DEP target!";
171171 uint8_t abtRx[1024];
172172 res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 500);
173 cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
173 cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
174174
175175 const uint8_t abtAttRx[] = "Hello DEP initiator!";
176176 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
177177 if (res < 0) { thread_res = -1; return (void *) thread_res; }
178178
179179 res = nfc_initiator_deselect_target(device);
180 cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
180 cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
181181 if (res < 0) { thread_res = -1; return (void *) thread_res; }
182182
183183 // Passive mode / 212Kbps (second pass)
184184 printf("=========== INITIATOR %s (Passive mode / 212Kbps) =========\n", nfc_device_get_name(device));
185185 res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_212, NULL, &nt, 1000);
186 cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
186 cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
187187 cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation"));
188188 cut_assert_equal_int(NBR_212, nt.nm.nbr, cut_message("Invalid target baud rate"));
189189 cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3"));
192192 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
193193
194194 res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 1000);
195 cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
196
197 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
198 if (res < 0) { thread_res = -1; return (void *) thread_res; }
199
200 res = nfc_initiator_deselect_target(device);
201 cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
195 cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
196
197 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
198 if (res < 0) { thread_res = -1; return (void *) thread_res; }
199
200 res = nfc_initiator_deselect_target(device);
201 cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
202202 if (res < 0) { thread_res = -1; return (void *) thread_res; }
203203
204204 // Passive mode / 212Kbps
205205 printf("=========== INITIATOR %s (Passive mode / 212Kbps, second pass) =========\n", nfc_device_get_name(device));
206206 res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_212, NULL, &nt, 1000);
207 cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
207 cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
208208 cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation"));
209209 cut_assert_equal_int(NBR_212, nt.nm.nbr, cut_message("Invalid target baud rate"));
210210 cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3"));
213213 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
214214
215215 res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 5000);
216 cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
217
218 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
219 if (res < 0) { thread_res = -1; return (void *) thread_res; }
220
221 res = nfc_initiator_deselect_target(device);
222 cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
216 cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
217
218 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
219 if (res < 0) { thread_res = -1; return (void *) thread_res; }
220
221 res = nfc_initiator_deselect_target(device);
222 cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
223223 if (res < 0) { thread_res = -1; return (void *) thread_res; }
224224
225225 // Passive mode / 424Kbps
226226 printf("=========== INITIATOR %s (Passive mode / 424Kbps) =========\n", nfc_device_get_name(device));
227227 res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_424, NULL, &nt, 1000);
228 cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
228 cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
229229 cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation"));
230230 cut_assert_equal_int(NBR_424, nt.nm.nbr, cut_message("Invalid target baud rate"));
231231 cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3"));
234234 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
235235
236236 res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 5000);
237 cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
238
239 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
240 if (res < 0) { thread_res = -1; return (void *) thread_res; }
241
242 res = nfc_initiator_deselect_target(device);
243 cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
237 cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
238
239 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
240 if (res < 0) { thread_res = -1; return (void *) thread_res; }
241
242 res = nfc_initiator_deselect_target(device);
243 cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
244244 if (res < 0) { thread_res = -1; return (void *) thread_res; }
245245
246246 return (void *) thread_res;
6565
6666 // 1) nfc_target_init should take target in idle mode
6767 int res = nfc_target_init(device, &nt, abtRx, sizeof(abtRx), 500);
68 cut_assert_operator_int(res, >= , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
68 cut_assert_operator_int(res, >=, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
6969 if (res < 0) { thread_res = -1; return (void *) thread_res; }
7070
7171 // 2) act as target
9191 };
9292 sleep(6);
9393 res = nfc_target_init(device, &nt1, abtRx, sizeof(abtRx), 0);
94 cut_assert_operator_int(res, > , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
94 cut_assert_operator_int(res, >, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device)));
9595 if (res < 0) { thread_res = -1; return (void *) thread_res; }
9696
9797 res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500);
98 cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
98 cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device)));
9999
100100 const uint8_t abtAttRx[] = "Hello DEP target!";
101101 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
103103
104104 const uint8_t abtTx[] = "Hello DEP initiator!";
105105 res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500);
106 cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
106 cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device)));
107107 if (res <= 0) { thread_res = -1; return (void *) thread_res; }
108108
109109 // 3) idle mode
143143 // Passive mode / 106Kbps
144144 printf("=========== INITIATOR %s (Passive mode / 106Kbps) =========\n", nfc_device_get_name(device));
145145 res = nfc_initiator_poll_dep_target(device, NDM_PASSIVE, NBR_106, NULL, &nt1, 5000);
146 cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
146 cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device)));
147147 cut_assert_equal_int(NMT_DEP, nt1.nm.nmt, cut_message("Invalid target modulation"));
148148 cut_assert_equal_int(NBR_106, nt1.nm.nbr, cut_message("Invalid target baud rate"));
149149 cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt1.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3"));
154154 const uint8_t abtTx[] = "Hello DEP target!";
155155 uint8_t abtRx[1024];
156156 res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 500);
157 cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
157 cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device)));
158158
159159 const uint8_t abtAttRx[] = "Hello DEP initiator!";
160160 cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data"));
161161 if (res < 0) { thread_res = -1; return (void *) thread_res; }
162162
163163 res = nfc_initiator_deselect_target(device);
164 cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
164 cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device)));
165165 if (res < 0) { thread_res = -1; return (void *) thread_res; }
166166
167167 // 3) As other device should be in idle mode, nfc_initiator_poll_dep_target should return 0
00 SET(UTILS-SOURCES
1 nfc-barcode
12 nfc-emulate-forum-tag4
23 nfc-jewel
34 nfc-list
00 bin_PROGRAMS = \
1 nfc-barcode \
12 nfc-emulate-forum-tag4 \
23 nfc-jewel \
34 nfc-list \
1314 noinst_LTLIBRARIES = libnfcutils.la
1415
1516 libnfcutils_la_SOURCES = nfc-utils.c
17 libnfcutils_la_LIBADD = -lnfc
18
19 nfc_barcode_SOURCES = nfc-barcode.c
20 nfc_barcode_LDADD = $(top_builddir)/libnfc/libnfc.la \
21 libnfcutils.la
1622
1723 nfc_emulate_forum_tag4_SOURCES = nfc-emulate-forum-tag4.c nfc-utils.h
1824 nfc_emulate_forum_tag4_LDADD = $(top_builddir)/libnfc/libnfc.la \
4551 libnfcutils.la
4652
4753 dist_man_MANS = \
54 nfc-barcode.1 \
4855 nfc-emulate-forum-tag4.1 \
4956 nfc-jewel.1 \
5057 nfc-list.1 \
9696 break;
9797 default:
9898 return false;
99 break;
10099 }
101100
102101 if (nfc_initiator_transceive_bytes(pnd, (uint8_t *)&req, nLenReq, (uint8_t *)pres, nLenRes, -1) < 0) {
6767 abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
6868
6969 switch (mc) {
70 // Read and store command have no parameter
70 // Read and store command have no parameter
7171 case MC_READ:
7272 case MC_STORE:
7373 szParamLen = 0;
7474 break;
7575
76 // Authenticate command
76 // Authenticate command
7777 case MC_AUTH_A:
7878 case MC_AUTH_B:
7979 szParamLen = sizeof(struct mifare_param_auth);
8080 break;
8181
82 // Data command
82 // Data command
8383 case MC_WRITE:
8484 szParamLen = sizeof(struct mifare_param_data);
8585 break;
8686
87 // Value command
87 // Value command
8888 case MC_DECREMENT:
8989 case MC_INCREMENT:
9090 case MC_TRANSFER:
9191 szParamLen = sizeof(struct mifare_param_value);
9292 break;
9393
94 // Please fix your code, you never should reach this statement
94 // Please fix your code, you never should reach this statement
9595 default:
9696 return false;
97 break;
9897 }
9998
10099 // When available, copy the parameter bytes
130129
131130 // When we have executed a read command, copy the received bytes into the param
132131 if (mc == MC_READ) {
133 if (res == 16) {
132
133 //Check the length of response data, with PCSC reader, there have 2 bytes for SW value
134 if (res == 16 || res == (16 + 2)) {
134135 memcpy(pmp->mpd.abtData, abtRx, 16);
135136 } else {
136137 return false;
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2017-2018 Adam Laurie
1112 *
1213 * Redistribution and use in source and binary forms, with or without
1314 * modification, are permitted provided that the following conditions are met:
7172 uint8_t abtValue[4];
7273 };
7374
75 struct mifare_param_trailer {
76 uint8_t abtKeyA[6];
77 uint8_t abtAccessBits[4];
78 uint8_t abtKeyB[6];
79 };
80
7481 typedef union {
7582 struct mifare_param_auth mpa;
7683 struct mifare_param_data mpd;
7784 struct mifare_param_value mpv;
85 struct mifare_param_trailer mpt;
7886 } mifare_param;
7987
8088 // Reset struct alignment to default
125133 uint8_t otp[4];
126134 } mifareul_block_manufacturer;
127135
136 // MIFARE Ultralight EV1 MF0UL11 Config Pages
137 typedef struct {
138 uint8_t mod;
139 uint8_t rfui1[2];
140 uint8_t auth0;
141 uint8_t access;
142 uint8_t vctid;
143 uint8_t rfui2[2];
144 uint8_t pwd[4];
145 uint8_t pack[2];
146 uint8_t rfui3[2];
147 } mifareul_block_config11;
148
149 // MIFARE Ultralight EV1 MF0UL21 ConfigA Pages
150 typedef struct {
151 uint8_t lock[3];
152 uint8_t rfui0;
153 uint8_t mod;
154 uint8_t rfui1[2];
155 uint8_t auth0;
156 uint8_t access;
157 uint8_t vctid;
158 uint8_t rfui2[2];
159 uint8_t pwd[4];
160 } mifareul_block_config21A;
161
162 // MIFARE Ultralight EV1 MF0UL21 ConfigB Pages
163 typedef struct {
164 uint8_t pack[2];
165 uint8_t rfui3[2];
166 uint8_t dummy[12];
167 } mifareul_block_config21B;
168
169 // MIFARE NTAG21[3/5/6] Manufacturer Pages
170 typedef struct {
171 uint8_t sn0[4];
172 } mifarentag_block_manuf21356A;
173 typedef struct {
174 uint8_t sn1[4];
175 } mifarentag_block_manuf21356B;
176 typedef struct {
177 uint8_t sn2;
178 uint8_t internal;
179 uint8_t lock[2];
180 } mifarentag_block_manuf21356C;
181 typedef struct {
182 uint8_t cc[4];
183 } mifarentag_block_manuf21356D;
184
185 // MIFARE NTAG21[3/5/6] Config Pages
186 typedef struct {
187 uint8_t dynlock[3];
188 uint8_t rfui0;
189 } mifarentag_block_config21356A;
190 typedef struct {
191 uint8_t cfg0[4];
192 } mifarentag_block_config21356B;
193 typedef struct {
194 uint8_t cfg1[4];
195 } mifarentag_block_config21356C;
196 typedef struct {
197 uint8_t pwd[4];
198 } mifarentag_block_config21356D;
199 typedef struct {
200 uint8_t pack[2];
201 uint8_t rfui1[2];
202 } mifarentag_block_config21356E;
203
128204 typedef struct {
129205 uint8_t abtData[16];
130206 } mifareul_block_data;
131207
208 typedef struct {
209 uint8_t abtData[4];
210 } mifarentag_block_data;
211
212 typedef union {
213 mifarentag_block_manuf21356A mbm21356a;
214 mifarentag_block_manuf21356B mbm21356b;
215 mifarentag_block_manuf21356C mbm21356c;
216 mifarentag_block_manuf21356D mbm21356d;
217 mifarentag_block_data mbd;
218 mifarentag_block_config21356A mbc21356a;
219 mifarentag_block_config21356B mbc21356b;
220 mifarentag_block_config21356C mbc21356c;
221 mifarentag_block_config21356D mbc21356d;
222 mifarentag_block_config21356E mbc21356e;
223 } mifarentag_block;
224
132225 typedef union {
133226 mifareul_block_manufacturer mbm;
134227 mifareul_block_data mbd;
228 mifareul_block_config11 mbc11;
229 mifareul_block_config21A mbc21a;
230 mifareul_block_config21B mbc21b;
135231 } mifareul_block;
136232
233 // standard UL tag - 1 manuf block + 3 user blocks
137234 typedef struct {
138235 mifareul_block amb[4];
139236 } mifareul_tag;
140237
238 // UL EV1 MF0UL11 tag - 1 manuf block + 3 user blocks + 1 config block
239 typedef struct {
240 mifareul_block amb[5];
241 } mifareul_ev1_mf0ul11_tag;
242
243 // UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1/4 lock block + 1 config block
244 // (note that tag is actually 3 bytes smaller due to 1/4 block, so don't rely on this for sizing!)
245 typedef struct {
246 mifareul_block amb[11];
247 } mifareul_ev1_mf0ul21_tag;
248
249 // NTAG is a range of NXP tags some of which are essentially Ultralights so we can support them here
250 // if Edwin van Andel doesn't distract us...
251 // https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf
252
253 // NTAG213 EEPROM: 180 bytes, organized in 45 pages of 4 byte per page.
254 // 26 bytes reserved for manufacturer and configuration data
255 // 34 bits used for the read-only locking mechanism
256 // 4 bytes available as capability container
257 // 144 bytes user programmable read/write memory
258 typedef struct {
259 mifarentag_block amb[45];
260 } mifarentag_213_tag;
261
262 // NTAG215 EEPROM: 540 bytes, organized in 135 pages of 4 byte per page.
263 // 26 bytes reserved for manufacturer and configuration data
264 // 28 bits used for the read-only locking mechanism
265 // 4 bytes available as capability container
266 // 504 bytes user programmable read/write memory
267 typedef struct {
268 mifarentag_block amb[135];
269 } mifarentag_215_tag;
270
271 // NTAG216 EEPROM: 924 bytes, organized in 231 pages of 4 byte per page.
272 // 26 bytes reserved for manufacturer and configuration data
273 // 37 bits used for the read-only locking mechanism
274 // 4 bytes available as capability container
275 // 888 bytes user programmable read/write memory
276 typedef struct {
277 mifarentag_block amb[231];
278 } mifarentag_216_tag;
279
280 // dummy max size with all structures in it for reading, rounded up to a multiple of 16 bytes
281 typedef union {
282 mifareul_block ul[58];
283 mifarentag_block nt[232];
284 } maxtag;
285
141286 // Reset struct alignment to default
142287 # pragma pack()
143288
0 .TH nfc-barcode 1 "May, 2017" "libnfc" "libnfc's examples"
1 .SH NAME
2 nfc-barcode \- NFC Barcode (Tag-Talks-First) reader
3 .SH SYNOPSIS
4 .B nfc-barcode
5 .SH DESCRIPTION
6 .B nfc-barcode
7 is a utility to read and decode NFC Barcodes
8
9 .SH OPTIONS
10 .B -d
11 Decode content, if possible.
12
13 .B -v
14 Verbose.
15
16 .SH BUGS
17 Please report any bugs on the
18 .B libnfc
19 issue tracker at:
20 .br
21 .BR https://github.com/nfc-tools/libnfc/issues
22 .SH LICENCE
23 .B libnfc
24 is licensed under the GNU Lesser General Public License (LGPL), version 3.
25 .br
26 .B libnfc-utils
27 and
28 .B libnfc-examples
29 are covered by the the BSD 2-Clause license.
30 .SH AUTHORS
31 Philippe Teuwen <yobibe@gmail.com>
32 .PP
33 This manual page was written by Philippe Teuwen <yobibe@gmail.com>.
34 It is licensed under the terms of the GNU GPL (version 2 or later).
0 /*-
1 * Free/Libre Near Field Communication (NFC) library
2 *
3 * Libnfc historical contributors:
4 * Copyright (C) 2017 Philippe Teuwen
5 * See AUTHORS file for a more comprehensive list of contributors.
6 * Additional contributors of this file:
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * 1) Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2 )Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Note that this license only applies on the examples, NFC library itself is under LGPL
29 *
30 */
31
32 /**
33 * @file nfc-barcode.c
34 * @brief Reads a NFC Barcode tag
35 */
36
37 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif // HAVE_CONFIG_H
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <stddef.h>
44 #include <stdint.h>
45 #include <stdbool.h>
46 #include <string.h>
47
48 #include <nfc/nfc.h>
49
50 #include "nfc-utils.h"
51
52 #define MAX_FRAME_LEN 264
53
54 static nfc_device *pnd;
55
56 bool verbose = false;
57
58 static void
59 print_usage(char *argv[])
60 {
61 printf("Usage: %s [OPTIONS]\n", argv[0]);
62 printf("Options:\n");
63 printf("\t-h\tHelp. Print this message.\n");
64 printf("\t-q\tVerbose mode.\n");
65 }
66
67
68 static bool
69 decode_barcode(uint8_t *pbtBarcode, const size_t szBarcode)
70 {
71 if (verbose) {
72 printf("Manufacturer ID field: %02X\n", pbtBarcode[0]);
73 switch (pbtBarcode[0]) {
74 case 0xb7:
75 printf("Manufacturer: Thinfilm\n");
76 break;
77 default:
78 printf("Manufacturer: unknown\n");
79 break;
80 }
81 }
82 if (verbose) {
83 printf("Data Format Field: %02X\n", pbtBarcode[1]);
84 }
85 switch (pbtBarcode[1]) {
86 case 0:
87 printf("Data Format Field: Reserved for allocation by tag manufacturer\n");
88 return false;
89 break;
90 case 1:
91 case 2:
92 case 3:
93 case 4:
94 switch (pbtBarcode[1]) {
95 case 1:
96 printf("http://www.");
97 break;
98 case 2:
99 printf("https://www.");
100 break;
101 case 3:
102 printf("http://");
103 break;
104 case 4:
105 printf("https://");
106 break;
107 }
108 for (uint8_t i = 2; i < 15; i++) {
109 if ((pbtBarcode[i] == 0xfe) || (i == 14)) {
110 pbtBarcode[i] = '\n';
111 pbtBarcode[i + 1] = 0;
112 break;
113 }
114 }
115 printf("%s", (char *)pbtBarcode + 2);
116 break;
117 case 5:
118 printf("EPC: ");
119 for (uint8_t i = 0; i < 12; i++) {
120 printf("%02x", pbtBarcode[i + 2]);
121 }
122 printf("\n");
123 break;
124 default:
125 printf("Data Format Field: unknown (%02X)\n", pbtBarcode[1]);
126 printf("Data:");
127 for (uint8_t i = 2; i < szBarcode - 2; i++) {
128 printf("%02x", pbtBarcode[i]);
129 }
130 printf("\n");
131 break;
132 }
133 return true;
134 }
135
136 int
137 main(int argc, char *argv[])
138 {
139 int arg;
140
141 // Get commandline options
142 for (arg = 1; arg < argc; arg++) {
143 if (0 == strcmp(argv[arg], "-h")) {
144 print_usage(argv);
145 exit(EXIT_SUCCESS);
146 } else if (0 == strcmp(argv[arg], "-v")) {
147 verbose = true;
148 } else {
149 ERR("%s is not supported option.", argv[arg]);
150 print_usage(argv);
151 exit(EXIT_FAILURE);
152 }
153 }
154
155 nfc_context *context;
156 nfc_init(&context);
157 if (context == NULL) {
158 ERR("Unable to init libnfc (malloc)");
159 exit(EXIT_FAILURE);
160 }
161
162 // Try to open the NFC reader
163 pnd = nfc_open(context, NULL);
164
165 if (pnd == NULL) {
166 ERR("Error opening NFC reader");
167 nfc_exit(context);
168 exit(EXIT_FAILURE);
169 }
170
171 // Initialise NFC device as "initiator"
172 if (nfc_initiator_init(pnd) < 0) {
173 nfc_perror(pnd, "nfc_initiator_init");
174 nfc_close(pnd);
175 nfc_exit(context);
176 exit(EXIT_FAILURE);
177 }
178
179 printf("NFC reader: %s opened\n\n", nfc_device_get_name(pnd));
180
181 nfc_modulation nm;
182 nm.nmt = NMT_BARCODE;
183 nm.nbr = NBR_106;
184 nfc_target ant[1];
185 // List NFC Barcode targets
186 if ((nfc_initiator_list_passive_targets(pnd, nm, ant, 1)) == 1) {
187 if (verbose) {
188 for (uint8_t i = 0; i < (&ant[0])->nti.nti.szDataLen; i++) {
189 printf("%02x", (&ant[0])->nti.nti.abtData[i]);
190 }
191 printf("\n");
192 }
193 decode_barcode((&ant[0])->nti.nti.abtData, (&ant[0])->nti.nti.szDataLen);
194 }
195 nfc_close(pnd);
196 nfc_exit(context);
197 exit(EXIT_SUCCESS);
198 }
4545 Please report any bugs on the
4646 .Em libnfc
4747 issue tracker at:
48 .Em http://code.google.com/p/libnfc/issues
48 .Em https://github.com/nfc-tools/libnfc/issues
4949 .Sh LICENCE
5050 .Em libnfc
5151 is licensed under the GNU Lesser General Public License (LGPL), version 3.
3434 .B libnfc
3535 issue tracker at:
3636 .br
37 .BR http://code.google.com/p/libnfc/issues
37 .BR https://github.com/nfc-tools/libnfc/issues
3838 .SH LICENCE
3939 .B libnfc
4040 is licensed under the GNU Lesser General Public License (LGPL), version 3.
2626 .TP
2727 \fB-t\fP \fIX\fP
2828 Polls only for types according to bitfield value of \fIX\fP:
29
2930 1: ISO14443A
3031 2: Felica (212 kbps)
3132 4: Felica (424 kbps)
3334 16: ISO14443B'
3435 32: ISO14443B-2 ST SRx
3536 64: ISO14443B-2 ASK CTx
36 128: Jewel
37 128: ISO14443B iClass
38 256: ISO14443A-3 Jewel
39 512: ISO14443A-2 NFC Barcode
3740
38 So 255 (default) polls for all types.
39
40 Note that if 16, 32 or 64 then 8 is selected too.
41 So 1023 (default) polls for all types.
42 Note that if 16, 32, 64 or 128 then 8 is selected too.
4143
4244 .SH EXAMPLE
4345 For an ISO/IEC 14443-A tag (i.e.Mifare DESFire):
5254 .B libnfc
5355 issue tracker at:
5456 .br
55 .BR http://code.google.com/p/libnfc/issues
57 .BR https://github.com/nfc-tools/libnfc/issues
5658 .SH LICENCE
5759 .B libnfc
5860 is licensed under the GNU Lesser General Public License (LGPL), version 3.
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2020 Adam Laurie
1112 *
1213 * Redistribution and use in source and binary forms, with or without
1314 * modification, are permitted provided that the following conditions are met:
7071 printf("\t 16: ISO14443B'\n");
7172 printf("\t 32: ISO14443B-2 ST SRx\n");
7273 printf("\t 64: ISO14443B-2 ASK CTx\n");
73 printf("\t 128: Jewel\n");
74 printf("\tSo 255 (default) polls for all types.\n");
75 printf("\tNote that if 16, 32 or 64 then 8 is selected too.\n");
74 printf("\t 128: ISO14443B iClass\n");
75 printf("\t 256: ISO14443A-3 Jewel\n");
76 printf("\t 512: ISO14443A-2 NFC Barcode\n");
77 printf("\tSo 1023 (default) polls for all types.\n");
78 printf("\tNote that if 16, 32, 64 or 128 then 8 is selected too.\n");
7679 }
7780
7881 int
8386 size_t i;
8487 bool verbose = false;
8588 int res = 0;
86 int mask = 0xff;
89 int mask = 0x3ff;
8790 int arg;
8891
8992 nfc_context *context;
107110 } else if ((0 == strcmp(argv[arg], "-t")) && (arg + 1 < argc)) {
108111 arg++;
109112 mask = atoi(argv[arg]);
110 if ((mask < 1) || (mask > 255)) {
113 if ((mask < 1) || (mask > 0x3ff)) {
111114 ERR("%i is invalid value for type bitfield.", mask);
112115 print_usage(argv[0]);
113116 exit(EXIT_FAILURE);
114117 }
115118 // Force TypeB for all derivatives of B
116 if (mask & 0x70)
119 if (mask & 0xf0)
117120 mask |= 0x08;
118121 } else {
119122 ERR("%s is not supported option.", argv[arg]);
270273 }
271274
272275 if (mask & 0x80) {
276 nm.nmt = NMT_ISO14443BICLASS;
277 nm.nbr = NBR_106;
278 // List ISO14443B iClass targets
279 if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) {
280 int n;
281 if (verbose || (res > 0)) {
282 printf("%d ISO14443B iClass passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":");
283 }
284 for (n = 0; n < res; n++) {
285 print_nfc_target(&ant[n], verbose);
286 printf("\n");
287 }
288 }
289 }
290
291 if (mask & 0x100) {
273292 nm.nmt = NMT_JEWEL;
274293 nm.nbr = NBR_106;
275294 // List Jewel targets
276295 if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) {
277296 int n;
278297 if (verbose || (res > 0)) {
279 printf("%d Jewel passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":");
280 }
281 for (n = 0; n < res; n++) {
282 print_nfc_target(&ant[n], verbose);
283 printf("\n");
284 }
285 }
286 }
298 printf("%d ISO14443A-3 Jewel passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":");
299 }
300 for (n = 0; n < res; n++) {
301 print_nfc_target(&ant[n], verbose);
302 printf("\n");
303 }
304 }
305 }
306
307 if (mask & 0x200) {
308 nm.nmt = NMT_BARCODE;
309 nm.nbr = NBR_106;
310 // List NFC Barcode targets
311 if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) {
312 int n;
313 if (verbose || (res > 0)) {
314 printf("%d ISO14443A-2 NFC Barcode passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":");
315 }
316 for (n = 0; n < res; n++) {
317 print_nfc_target(&ant[n], verbose);
318 printf("\n");
319 }
320 }
321 }
322
287323 nfc_close(pnd);
288324 }
289325
44 .B nfc-mfclassic
55 .RI \fR\fBf\fR|\fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR
66 .RI \fR\fBa\fR|\fR\fBA\fR|\fBb\fR\fR|\fBB\fR
7 .RI \fR\fBu\fR\fR|\fBU\fR<\fBuid\fR>\fR
78 .IR DUMP
89 .RI [
910 .IR KEYS
5556 .B B
5657 ).
5758
59 When using multiple tags infront of a reader, the
60 .B U
61 option can be used to supply the UID of tag to be read or written. Append the
62 hexadecimal UID to the U option. For example U01ab23cd for the 4 byte UID
63 0x01 0xab 0x23 0xcd. Using the
64 .B u
65 parameter instead will use whatever libnfc decides which generally is the lowest
66 UID.
67
5868 *** Note that
5969 .B W
6070 and
8999 B
90100 ).
91101 .TP
102 .BR u " | " U
103 Use the default UID (
104 .B u
105 ) or supply a valid 4 byte UID (
106 .B U<uid>
107 ).
108 .TP
92109 .IR DUMP
93110 MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
94111 .TP
105122 .B libnfc
106123 issue tracker at:
107124 .br
108 .BR http://code.google.com/p/libnfc/issues
125 .BR https://github.com/nfc-tools/libnfc/issues
109126 .SH LICENCE
110127 .B libnfc
111128 is licensed under the GNU Lesser General Public License (LGPL), version 3.
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
1111 * Copyright (C) 2011-2013 Adam Laurie
12 * Copyright (C) 2018-2019 Danielle Bruneo
1213 *
1314 * Redistribution and use in source and binary forms, with or without
1415 * modification, are permitted provided that the following conditions are met:
6970 static bool bTolerateFailures;
7071 static bool bFormatCard;
7172 static bool magic2 = false;
73 static bool magic3 = false;
74 static bool unlocked = false;
7275 static uint8_t uiBlocks;
7376 static uint8_t keys[] = {
7477 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9699 static uint8_t abtRx[MAX_FRAME_LEN];
97100 static int szRxBits;
98101
99 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
102 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
100103
101104 // special unlock command
102 uint8_t abtUnlock1[1] = { 0x40 };
103 uint8_t abtUnlock2[1] = { 0x43 };
104
105 static bool
105 uint8_t abtUnlock1[1] = { 0x40 };
106 uint8_t abtUnlock2[1] = { 0x43 };
107
108 static bool
106109 transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
107110 {
108111 // Show transmitted command
120123 }
121124
122125
123 static bool
126 static bool
124127 transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
125128 {
126129 // Show transmitted command
146149 *uiBlockCounter += 1;
147150 }
148151
149 static bool
152 static bool
150153 is_first_block(uint32_t uiBlock)
151154 {
152155 // Test if we are in the small or big sectors
156159 return ((uiBlock) % 16 == 0);
157160 }
158161
159 static bool
162 static bool
160163 is_trailer_block(uint32_t uiBlock)
161164 {
162165 // Test if we are in the small or big sectors
166169 return ((uiBlock + 1) % 16 == 0);
167170 }
168171
169 static uint32_t
172 static uint32_t
170173 get_trailer_block(uint32_t uiFirstBlock)
171174 {
172175 // Test if we are in the small or big sectors
179182 return trailer_block;
180183 }
181184
182 static bool
185 static bool
183186 authenticate(uint32_t uiBlock)
184187 {
185188 mifare_cmd mc;
186 uint32_t uiTrailerBlock;
187189
188190 // Set the authentication information (uid)
189191 memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
195197 if (bUseKeyFile) {
196198
197199 // Locate the trailer (with the keys) used for this sector
200 uint32_t uiTrailerBlock;
198201 uiTrailerBlock = get_trailer_block(uiBlock);
199202
200203 // Extract the right key from dump file
201204 if (bUseKeyA)
202 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6);
205 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, sizeof(mp.mpa.abtKey));
203206 else
204 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);
207 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, sizeof(mp.mpa.abtKey));
205208
206209 // Try to authenticate for the current sector
207210 if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
208211 return true;
209 }
210
211 // If formatting or not using key file, try to guess the right key
212 if (bFormatCard || !bUseKeyFile) {
212
213 } else if (magic3) {
214 //If it's a One Time Write card, we're gonna authenticate with the default keys
215 memcpy(mp.mpa.abtKey, default_key, sizeof(default_key));
216
217
218 // Try to authenticate for the current sector
219 if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
220 return true;
221 }
222 // If formatting or not using key file, try to guess the right key
223 } else if (bFormatCard || !bUseKeyFile) {
213224 for (size_t key_index = 0; key_index < num_keys; key_index++) {
214225 memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
215226 if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
216227 if (bUseKeyA)
217 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
228 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, sizeof(mtKeys.amb[uiBlock].mbt.abtKeyA));
218229 else
219 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6);
230 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, sizeof(mtKeys.amb[uiBlock].mbt.abtKeyB));
220231 return true;
221232 }
222233 if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
232243 static bool
233244 unlock_card(void)
234245 {
235 if (magic2) {
236 printf("Don't use R/W with this card, this is not required!\n");
237 return false;
238 }
239
240246 // Configure the CRC
241247 if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
242248 nfc_perror(pnd, "nfc_configure");
252258 transmit_bytes(abtHalt, 4);
253259 // now send unlock
254260 if (!transmit_bits(abtUnlock1, 7)) {
255 printf("unlock failure!\n");
256 return false;
257 }
258 if (!transmit_bytes(abtUnlock2, 1)) {
259 printf("unlock failure!\n");
260 return false;
261 printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
262 } else {
263 if (transmit_bytes(abtUnlock2, 1)) {
264 printf("Card unlocked\n");
265 unlocked = true;
266 } else {
267 printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n");
268 }
261269 }
262270
263271 // reset reader
278286 get_rats(void)
279287 {
280288 int res;
281 uint8_t abtRats[2] = { 0xe0, 0x50};
289 uint8_t abtRats[2] = { 0xe0, 0x50};
282290 // Use raw send/receive methods
283291 if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
284292 nfc_perror(pnd, "nfc_configure");
306314 return res;
307315 }
308316
309 static bool
317 static bool
310318 read_card(int read_unlocked)
311319 {
312320 int32_t iBlock;
313 bool bFailure = false;
321 bool bFailure = false;
314322 uint32_t uiReadBlocks = 0;
315323
316 if (read_unlocked)
317 if (!unlock_card())
318 return false;
324 if (read_unlocked) {
325 //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
326 //need to use the R mode. We'll trigger a warning and let them proceed.
327 if (magic2) {
328 printf("Note: This card does not require an unlocked read (R) \n");
329 read_unlocked = 0;
330 } else {
331 //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out.
332 if (!unlock_card()) {
333 return false;
334 }
335 }
336 }
319337
320338 printf("Reading out %d blocks |", uiBlocks + 1);
321339 // Read the card from end to begin
341359 // Try to read out the trailer
342360 if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
343361 if (read_unlocked) {
344 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
362 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
345363 } else {
346 // Copy the keys over from our key dump and store the retrieved access bits
347 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6);
348 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);
349 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
364 //If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL
365 if (magic3) {
366 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key));
367 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
368 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key));
369 } else {
370 // Copy the keys over from our key dump and store the retrieved access bits
371 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
372 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
373 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
374 }
350375 }
351376 } else {
352377 printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
357382 if (!bFailure) {
358383 // Try to read out the data block
359384 if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
360 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
385 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
361386 } else {
362387 printf("!\nError: unable to read block 0x%02x\n", iBlock);
363388 bFailure = true;
366391 }
367392 // Show if the readout went well for each block
368393 print_success_or_failure(bFailure, &uiReadBlocks);
369 if ((! bTolerateFailures) && bFailure)
394 if ((!bTolerateFailures) && bFailure)
370395 return false;
371396 }
372397 printf("|\n");
376401 return true;
377402 }
378403
379 static bool
404 static bool
380405 write_card(int write_block_zero)
381406 {
382407 uint32_t uiBlock;
383 bool bFailure = false;
408 bool bFailure = false;
384409 uint32_t uiWriteBlocks = 0;
385410
386 if (write_block_zero)
387 if (!unlock_card())
388 return false;
411 //Determine if we have to unlock the card
412 if (write_block_zero) {
413 //If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
414 //need to use the W mode. We'll trigger a warning and let them proceed.
415 if (magic2) {
416 printf("Note: This card does not require an unlocked write (W) \n");
417 write_block_zero = 0;
418 } else {
419 //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out.
420 if (!unlock_card()) {
421 return false;
422 }
423 }
424 }
389425
390426 printf("Writing %d blocks |", uiBlocks + 1);
391 // Write the card from begin to end;
392 for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
427 // Completely write the card, end to start, but skipping block 0
428 for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
393429 // Authenticate everytime we reach the first sector of a new block
394430 if (is_first_block(uiBlock)) {
395431 if (bFailure) {
404440 fflush(stdout);
405441
406442 // Try to authenticate for the current sector
407 if (!write_block_zero && !authenticate(uiBlock)) {
408 printf("!\nError: authentication failed for block %02x\n", uiBlock);
409 return false;
410 }
411 }
412
413 if (is_trailer_block(uiBlock)) {
414 if (bFormatCard) {
415 // Copy the default key and reset the access bits
416 memcpy(mp.mpd.abtData, default_key, 6);
417 memcpy(mp.mpd.abtData + 6, default_acl, 4);
418 memcpy(mp.mpd.abtData + 10, default_key, 6);
443 // If we are are writing to a chinese magic card, we've already unlocked
444 // If we're writing to a One Time Write card, we need to authenticate
445 // If we're writing something else, we'll need to authenticate
446 if ((write_block_zero && magic3) || !write_block_zero) {
447 if (!authenticate(uiBlock) && !bTolerateFailures) {
448 printf("!\nError: authentication failed for block %02x\n", uiBlock);
449 return false;
450 }
451 }
452
453 if (is_trailer_block(uiBlock)) {
454 if (bFormatCard) {
455 // Copy the default key and reset the access bits
456 memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA));
457 memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
458 memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB));
459 } else {
460 // Copy the keys over from our key dump and store the retrieved access bits
461 memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA));
462 memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits));
463 memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB));
464 }
465
466 // Try to write the trailer
467 if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) {
468 printf("failed to write trailer block %d \n", uiBlock);
469 bFailure = true;
470 }
419471 } else {
420 // Copy the keys over from our key dump and store the retrieved access bits
421 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6);
422 memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4);
423 memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6);
424 }
425
426 // Try to write the trailer
427 if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) {
428 printf("failed to write trailer block %d \n", uiBlock);
429 bFailure = true;
430 }
431 } else {
472 // The first block 0x00 is read only, skip this
473 if (uiBlock == 0 && !write_block_zero && !magic2)
474 continue;
475
476 // Make sure a earlier write did not fail
477 if (!bFailure) {
478 // Try to write the data block
479 if (bFormatCard && uiBlock)
480
481 memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
482 else
483 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
484 // do not write a block 0 with incorrect BCC - card will be made invalid!
485 if (uiBlock == 0) {
486 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
487 printf("!\nError: incorrect BCC in MFD file!\n");
488 printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
489 return false;
490 }
491 }
492 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
493 bFailure = true;
494 printf("Failure to write to data block %i\n", uiBlock);
495 }
496
497 } else {
498 printf("Failure during write process.\n");
499 }
500 }
501 }
502 // Show if the write went well for each block
503 print_success_or_failure(bFailure, &uiWriteBlocks);
504 if ((! bTolerateFailures) && bFailure)
505 return false;
506 }
507
508 //Write Block 0 if necessary
509 if (write_block_zero || magic2 || magic3) {
510 for (uiBlock = 0; uiBlock < 4; uiBlock++) {
511
432512 // The first block 0x00 is read only, skip this
433 if (uiBlock == 0 && ! write_block_zero && ! magic2)
434 continue;
435
513 if (uiBlock == 0) {
514 //If the card is not magic, we're gonna skip over
515 if (write_block_zero || magic2 || magic3) {
516 //NOP
517 } else {
518 continue;
519 }
520 }
521
522 if (is_first_block(uiBlock)) {
523 if (bFailure) {
524 // When a failure occured we need to redo the anti-collision
525 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
526 printf("!\nError: tag was removed\n");
527 return false;
528 }
529 bFailure = false;
530 }
531
532 fflush(stdout);
533 // Try to authenticate for the current sector
534 // If we are are writing to a chinese magic card, we've already unlocked
535 // If we're writing to a One Time Write, we need to authenticate
536 // If we're writing something else, we'll need to authenticate
537 if ((write_block_zero && magic3) || !write_block_zero) {
538 if (!authenticate(uiBlock) && !bTolerateFailures) {
539 printf("!\nError: authentication failed for block %02x\n", uiBlock);
540 return false;
541 }
542 }
543 }
436544
437545 // Make sure a earlier write did not fail
438546 if (!bFailure) {
439547 // Try to write the data block
440548 if (bFormatCard && uiBlock)
441 memset(mp.mpd.abtData, 0x00, 16);
549 memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
442550 else
443 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16);
551 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
444552 // do not write a block 0 with incorrect BCC - card will be made invalid!
445553 if (uiBlock == 0) {
446554 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
449557 return false;
450558 }
451559 }
452 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp))
560 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
453561 bFailure = true;
454 }
455 }
456 // Show if the write went well for each block
457 print_success_or_failure(bFailure, &uiWriteBlocks);
458 if ((! bTolerateFailures) && bFailure)
459 return false;
460 }
562 printf("Failure to write to data block %i\n", uiBlock);
563 }
564
565 } else {
566 printf("Failure during write process.\n");
567 }
568
569 // Show if the write went well for each block
570 print_success_or_failure(bFailure, &uiWriteBlocks);
571 if ((! bTolerateFailures) && bFailure)
572 return false;
573
574 }
575
576 }
577
461578 printf("|\n");
462579 printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
463580 fflush(stdout);
475592 print_usage(const char *pcProgramName)
476593 {
477594 printf("Usage: ");
478 printf("%s f|r|R|w|W a|b <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
595 printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
479596 printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");
480597 printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
481598 printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
482599 printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
483600 printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
484601 printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
602 printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
485603 printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
486604 printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
487605 printf(" f - Force using the keyfile even if UID does not match (optional)\n");
606
488607 printf("Examples: \n\n");
489608 printf(" Read card to file, using key A:\n\n");
490 printf(" %s r a mycard.mfd\n\n", pcProgramName);
609 printf(" %s r a u mycard.mfd\n\n", pcProgramName);
491610 printf(" Write file to blank card, using key A:\n\n");
492 printf(" %s w a mycard.mfd\n\n", pcProgramName);
611 printf(" %s w a u mycard.mfd\n\n", pcProgramName);
493612 printf(" Write new data and/or keys to previously written card, using key A:\n\n");
494 printf(" %s w a newdata.mfd mycard.mfd\n\n", pcProgramName);
613 printf(" %s w a u newdata.mfd mycard.mfd\n\n", pcProgramName);
495614 printf(" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n");
496 printf(" %s f A dummy.mfd keyfile.mfd f\n", pcProgramName);
497 printf(" %s f B dummy.mfd keyfile.mfd f\n\n", pcProgramName);
615 printf(" %s f A u dummy.mfd keyfile.mfd f\n", pcProgramName);
616 printf(" %s f B u dummy.mfd keyfile.mfd f\n\n", pcProgramName);
617 printf(" Read card to file, using key A and uid 0x01 0xab 0x23 0xcd:\n\n");
618 printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName);
619 }
620
621
622 static bool is_directwrite(void)
623 {
624 printf("Checking if Badge is DirectWrite...\n");
625
626 // Set default keys
627 memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key));
628 memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
629 memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key));
630
631 // Temporarly override bUseKeyFile
632 bool orig_bUseKeyFile = bUseKeyFile;
633 bUseKeyFile = false;
634 // Try to authenticate for the current sector
635 if (!authenticate(0)) {
636 printf("!\nError: authentication failed for block 0x%02x\n", 0);
637 bUseKeyFile = orig_bUseKeyFile;
638 return false;
639 }
640 // restore bUseKeyFile
641 bUseKeyFile = orig_bUseKeyFile;
642
643 // Try to read block 0
644 uint8_t original_b0[16];
645 if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
646 memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData));
647 printf(" Original Block 0: ");
648 for (int i = 0; i < 16; i++) {
649 printf("%02x", original_b0[i]);
650 }
651 printf("\n");
652 printf(" Original UID: %02x%02x%02x%02x\n",
653 original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
654 } else {
655 printf("!\nError: unable to read block 0x%02x\n", 0);
656 return false;
657 }
658
659 printf(" Attempt to write Block 0 ...\n");
660 memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
661 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
662 printf("Failure to write to data block %i\n", 0);
663 return false;
664 }
665 printf(" Block 0 written successfully\n");
666
667 return true;
498668 }
499669
500670 int
502672 {
503673 action_t atAction = ACTION_USAGE;
504674 uint8_t *pbtUID;
675 uint8_t _tag_uid[4];
676 uint8_t *tag_uid = _tag_uid;
677
505678 int unlock = 0;
506679
507680 if (argc < 2) {
510683 }
511684 const char *command = argv[1];
512685
686 if (argc < 5) {
687 print_usage(argv[0]);
688 exit(EXIT_FAILURE);
689 }
513690 if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
514 if (argc < 4) {
515 print_usage(argv[0]);
516 exit(EXIT_FAILURE);
517 }
518691 atAction = ACTION_READ;
519692 if (strcmp(command, "R") == 0)
520693 unlock = 1;
521694 bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
522695 bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
523 bUseKeyFile = (argc > 4);
524 bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
696 bUseKeyFile = (argc > 5);
697 bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
525698 } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
526 if (argc < 4) {
527 print_usage(argv[0]);
528 exit(EXIT_FAILURE);
529 }
530699 atAction = ACTION_WRITE;
531700 if (strcmp(command, "W") == 0)
532701 unlock = 1;
533702 bFormatCard = (strcmp(command, "f") == 0);
534703 bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
535704 bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
536 bUseKeyFile = (argc > 4);
537 bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
705 bUseKeyFile = (argc > 5);
706 bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
707 }
708 if (argv[3][0] == 'U') {
709 unsigned long int _uid;
710
711 if (strlen(argv[3]) != 9) {
712 printf("Error, illegal tag specification, use U01ab23cd for example.\n");
713 print_usage(argv[0]);
714 exit(EXIT_FAILURE);
715 }
716 _uid = strtoul(argv[3] + 1, NULL, 16);
717 tag_uid[0] = (_uid & 0xff000000UL) >> 24;
718 tag_uid[1] = (_uid & 0x00ff0000UL) >> 16;
719 tag_uid[2] = (_uid & 0x0000ff00UL) >> 8;
720 tag_uid[3] = (_uid & 0x000000ffUL);
721 printf("Attempting to use specific UID: 0x%2x 0x%2x 0x%2x 0x%2x\n",
722 tag_uid[0], tag_uid[1], tag_uid[2], tag_uid[3]);
723 } else {
724 tag_uid = NULL;
538725 }
539726
540727 if (atAction == ACTION_USAGE) {
543730 }
544731 // We don't know yet the card size so let's read only the UID from the keyfile for the moment
545732 if (bUseKeyFile) {
546 FILE *pfKeys = fopen(argv[4], "rb");
733 FILE *pfKeys = fopen(argv[5], "rb");
547734 if (pfKeys == NULL) {
548 printf("Could not open keys file: %s\n", argv[4]);
735 printf("Could not open keys file: %s\n", argv[5]);
549736 exit(EXIT_FAILURE);
550737 }
551738 if (fread(&mtKeys, 1, 4, pfKeys) != 4) {
552 printf("Could not read UID from key file: %s\n", argv[4]);
739 printf("Could not read UID from key file: %s\n", argv[5]);
553740 fclose(pfKeys);
554741 exit(EXIT_FAILURE);
555742 }
594781 printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
595782
596783 // Try to find a MIFARE Classic tag
597 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
784 int tags;
785
786 tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
787 if (tags <= 0) {
598788 printf("Error: no tag was found\n");
599789 nfc_close(pnd);
600790 nfc_exit(context);
617807 fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
618808 printf("Got card with UID starting as: %02x%02x%02x%02x\n",
619809 pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]);
620 if (! bForceKeyFile) {
810 if (!bForceKeyFile) {
621811 printf("Aborting!\n");
622812 nfc_close(pnd);
623813 nfc_exit(context);
629819 print_nfc_target(&nt, false);
630820
631821 // Guessing size
632 if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02)
822 if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02 || nt.nti.nai.btSak == 0x18)
633823 // 4K
634824 uiBlocks = 0xff;
635 else if ((nt.nti.nai.btSak & 0x01) == 0x01)
825 else if (nt.nti.nai.btSak == 0x09)
636826 // 320b
637827 uiBlocks = 0x13;
638828 else
641831 // Testing RATS
642832 int res;
643833 if ((res = get_rats()) > 0) {
834 printf("RATS support: yes\n");
644835 if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
645836 && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
646837 && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
652843 && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
653844 magic2 = true;
654845 }
655 }
656 printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16);
846 } else
847 printf("RATS support: no\n");
848 printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block)));
849
850 //If size is 4k check for direct-write card
851 if (uiBlocks == 0xff) {
852 if (is_directwrite()) {
853 printf("Card is DirectWrite\n");
854 magic3 = true;
855 unlock = 0;
856 } else {
857 printf("Card is not DirectWrite\n");
858 }
859 }
860
861 //Check to see if we have a One Time Write badge (magic3)
862 if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 &&
863 pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
864 printf("Card appears to be a One Time Write Card..\n");
865 magic3 = true;
866 unlock = 0;
867 }
868
657869
658870 if (bUseKeyFile) {
659 FILE *pfKeys = fopen(argv[4], "rb");
871 FILE *pfKeys = fopen(argv[5], "rb");
660872 if (pfKeys == NULL) {
661 printf("Could not open keys file: %s\n", argv[4]);
873 printf("Could not open keys file: %s\n", argv[5]);
662874 exit(EXIT_FAILURE);
663875 }
664876 if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
665 printf("Could not read keys file: %s\n", argv[4]);
877 printf("Could not read keys file: %s\n", argv[5]);
666878 fclose(pfKeys);
667879 exit(EXIT_FAILURE);
668880 }
672884 if (atAction == ACTION_READ) {
673885 memset(&mtDump, 0x00, sizeof(mtDump));
674886 } else {
675 FILE *pfDump = fopen(argv[3], "rb");
887 FILE *pfDump = fopen(argv[4], "rb");
676888
677889 if (pfDump == NULL) {
678 printf("Could not open dump file: %s\n", argv[3]);
890 printf("Could not open dump file: %s\n", argv[4]);
679891 exit(EXIT_FAILURE);
680892
681893 }
682894
683895 if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
684 printf("Could not read dump file: %s\n", argv[3]);
896 printf("Could not read dump file: %s\n", argv[4]);
685897 fclose(pfDump);
686898 exit(EXIT_FAILURE);
687899 }
691903
692904 if (atAction == ACTION_READ) {
693905 if (read_card(unlock)) {
694 printf("Writing data to file: %s ...", argv[3]);
906 printf("Writing data to file: %s ...", argv[4]);
695907 fflush(stdout);
696 FILE *pfDump = fopen(argv[3], "wb");
908 FILE *pfDump = fopen(argv[4], "wb");
697909 if (pfDump == NULL) {
698 printf("Could not open dump file: %s\n", argv[3]);
910 printf("Could not open dump file: %s\n", argv[4]);
699911 nfc_close(pnd);
700912 nfc_exit(context);
701913 exit(EXIT_FAILURE);
702914 }
703915 if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) {
704 printf("\nCould not write to file: %s\n", argv[3]);
916 printf("\nCould not write to file: %s\n", argv[4]);
705917 fclose(pfDump);
706918 nfc_close(pnd);
707919 nfc_exit(context);
3838 .B libnfc
3939 issue tracker at:
4040 .br
41 .BR http://code.google.com/p/libnfc/issues
41 .BR https://github.com/nfc-tools/libnfc/issues
4242 .SH LICENCE
4343 .B libnfc
4444 is licensed under the GNU Lesser General Public License (LGPL), version 3.
44 * Copyright (C) 2009 Roel Verdult
55 * Copyright (C) 2009-2013 Romuald Conty
66 * Copyright (C) 2010-2012 Romain Tartière
7 * Copyright (C) 2010-2013 Philippe Teuwen
7 * Copyright (C) 2010-2017 Philippe Teuwen
88 * Copyright (C) 2012-2013 Ludovic Rousseau
99 * See AUTHORS file for a more comprehensive list of contributors.
1010 * Additional contributors of this file:
11 * Copyright (C) 2013 Adam Laurie
11 * Copyright (C) 2013-2018 Adam Laurie
12 * Copyright (C) 2018-2019 Daniele Bruneo
1213 *
1314 * Redistribution and use in source and binary forms, with or without
1415 * modification, are permitted provided that the following conditions are met:
5758 #include "nfc-utils.h"
5859 #include "mifare.h"
5960
61 #define MAX_TARGET_COUNT 16
62 #define MAX_UID_LEN 10
63
64 #define EV1_NONE 0
65 #define EV1_UL11 1
66 #define EV1_UL21 2
67
68 #define NTAG_NONE 0
69 #define NTAG_213 1
70 #define NTAG_215 2
71 #define NTAG_216 3
72
6073 static nfc_device *pnd;
6174 static nfc_target nt;
6275 static mifare_param mp;
63 static mifareul_tag mtDump;
64 static uint32_t uiBlocks = 0xF;
76 static maxtag mtDump; // use the largest tag type for internal storage
77 static uint32_t uiBlocks = 0x10;
78 static uint32_t uiReadPages = 0;
79 static uint8_t iPWD[4] = { 0x0 };
80 static uint8_t iPACK[2] = { 0x0 };
81 static uint8_t iEV1Type = EV1_NONE;
82 static uint8_t iNTAGType = NTAG_NONE;
83
84 // special unlock command
85 uint8_t abtUnlock1[1] = { 0x40 };
86 uint8_t abtUnlock2[1] = { 0x43 };
87
88 // EV1 commands
89 uint8_t abtEV1[3] = { 0x60, 0x00, 0x00 };
90 uint8_t abtPWAuth[7] = { 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
91
92 //Halt command
93 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
94
95 #define MAX_FRAME_LEN 264
96
97 static uint8_t abtRx[MAX_FRAME_LEN];
98 static int szRxBits;
99 static int szRx;
65100
66101 static const nfc_modulation nmMifare = {
67102 .nmt = NMT_ISO14443A,
69104 };
70105
71106 static void
72 print_success_or_failure(bool bFailure, uint32_t *uiCounter)
73 {
74 printf("%c", (bFailure) ? 'x' : '.');
75 if (uiCounter)
76 *uiCounter += (bFailure) ? 0 : 1;
107 print_success_or_failure(bool bFailure, uint32_t *uiOkCounter, uint32_t *uiFailedCounter)
108 {
109 printf("%c", (bFailure) ? 'f' : '.');
110 if (uiOkCounter)
111 *uiOkCounter += (bFailure) ? 0 : 1;
112 if (uiFailedCounter)
113 *uiFailedCounter += (bFailure) ? 1 : 0;
77114 }
78115
79116 static bool
81118 {
82119 uint32_t page;
83120 bool bFailure = false;
84 uint32_t uiReadedPages = 0;
85
86 printf("Reading %d pages |", uiBlocks + 1);
87
88 for (page = 0; page <= uiBlocks; page += 4) {
121 uint32_t uiFailedPages = 0;
122
123 printf("Reading %d pages |", uiBlocks);
124
125 for (page = 0; page < uiBlocks; page += 4) {
89126 // Try to read out the data block
90127 if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) {
91 memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16);
128 memcpy(mtDump.ul[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16);
92129 } else {
93130 bFailure = true;
131 }
132 for (uint8_t i = 0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) {
133 print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages);
134 }
135 }
136 printf("|\n");
137 printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks, uiFailedPages);
138 fflush(stdout);
139
140 // copy EV1 secrets to dump data
141 switch (iEV1Type) {
142 case EV1_UL11:
143 memcpy(mtDump.ul[4].mbc11.pwd, iPWD, 4);
144 memcpy(mtDump.ul[4].mbc11.pack, iPACK, 2);
94145 break;
95 }
96
97 print_success_or_failure(bFailure, &uiReadedPages);
98 print_success_or_failure(bFailure, &uiReadedPages);
99 print_success_or_failure(bFailure, &uiReadedPages);
100 print_success_or_failure(bFailure, &uiReadedPages);
101 }
102 printf("|\n");
103 printf("Done, %d of %d pages readed.\n", uiReadedPages, uiBlocks + 1);
104 fflush(stdout);
146 case EV1_UL21:
147 memcpy(mtDump.ul[9].mbc21a.pwd, iPWD, 4);
148 memcpy(mtDump.ul[9].mbc21b.pack, iPACK, 2);
149 break;
150 case EV1_NONE:
151 default:
152 break;
153 }
154 // copy NTAG secrets to dump data
155 switch (iNTAGType) {
156 case NTAG_213:
157 memcpy(mtDump.nt[43].mbc21356d.pwd, iPWD, 4);
158 memcpy(mtDump.nt[44].mbc21356e.pack, iPACK, 2);
159 break;
160 case NTAG_215:
161 memcpy(mtDump.nt[133].mbc21356d.pwd, iPWD, 4);
162 memcpy(mtDump.nt[134].mbc21356e.pack, iPACK, 2);
163 break;
164 case NTAG_216:
165 memcpy(mtDump.nt[229].mbc21356d.pwd, iPWD, 4);
166 memcpy(mtDump.nt[230].mbc21356e.pack, iPACK, 2);
167 break;
168 case NTAG_NONE:
169 default:
170 break;
171 }
105172
106173 return (!bFailure);
107174 }
108175
109176 static bool
110 write_card(void)
177 transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
178 {
179 // Transmit the bit frame command, we don't use the arbitrary parity feature
180 if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
181 return false;
182
183 return true;
184 }
185
186
187 static bool
188 transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
189 {
190 if ((szRx = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
191 return false;
192
193 return true;
194 }
195
196 static bool
197 raw_mode_start(void)
198 {
199 // Configure the CRC
200 if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
201 nfc_perror(pnd, "nfc_configure");
202 return false;
203 }
204 // Use raw send/receive methods
205 if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
206 nfc_perror(pnd, "nfc_configure");
207 return false;
208 }
209 return true;
210 }
211
212 static bool
213 raw_mode_end(void)
214 {
215 // reset reader
216 // Configure the CRC
217 if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
218 nfc_perror(pnd, "nfc_device_set_property_bool");
219 return false;
220 }
221 // Switch off raw send/receive methods
222 if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
223 nfc_perror(pnd, "nfc_device_set_property_bool");
224 return false;
225 }
226 return true;
227 }
228
229 static bool
230 get_ev1_version(void)
231 {
232 if (!raw_mode_start())
233 return false;
234 iso14443a_crc_append(abtEV1, 1);
235 if (!transmit_bytes(abtEV1, 3)) {
236 raw_mode_end();
237 return false;
238 }
239 if (!raw_mode_end())
240 return false;
241 if (!szRx)
242 return false;
243 return true;
244 }
245
246 static bool
247 ev1_load_pwd(uint8_t target[4], const char *pwd)
248 {
249 unsigned int tmp[4];
250 if (sscanf(pwd, "%2x%2x%2x%2x", &tmp[0], &tmp[1], &tmp[2], &tmp[3]) != 4)
251 return false;
252 target[0] = tmp[0];
253 target[1] = tmp[1];
254 target[2] = tmp[2];
255 target[3] = tmp[3];
256 return true;
257 }
258
259 static bool
260 ev1_pwd_auth(uint8_t *pwd)
261 {
262 if (!raw_mode_start())
263 return false;
264 memcpy(&abtPWAuth[1], pwd, 4);
265 iso14443a_crc_append(abtPWAuth, 5);
266 if (!transmit_bytes(abtPWAuth, 7))
267 return false;
268 if (!raw_mode_end())
269 return false;
270 return true;
271 }
272
273 static bool
274 unlock_card(void)
275 {
276 if (!raw_mode_start())
277 return false;
278 iso14443a_crc_append(abtHalt, 2);
279 transmit_bytes(abtHalt, 4);
280 // now send unlock
281 if (!transmit_bits(abtUnlock1, 7)) {
282 return false;
283 }
284 if (!transmit_bytes(abtUnlock2, 1)) {
285 return false;
286 }
287
288 if (!raw_mode_end())
289 return false;
290 return true;
291 }
292
293 static bool check_magic(void)
294 {
295 bool directWrite = true;
296 // Try to read pages 0, 1, 2
297 uint8_t original_b0[12];
298 printf("Checking if UL badge is DirectWrite...\n");
299 if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
300 memcpy(original_b0, mp.mpd.abtData, 12);
301 printf(" Original Block 0 (Pages 0-2): ");
302 for (int i = 0; i < 12; i++) {
303 printf("%02x", original_b0[i]);
304 }
305 printf("\n");
306 printf(" Original UID: %02x%02x%02x%02x%02x%02x%02x\n",
307 original_b0[0], original_b0[1], original_b0[2], original_b0[4], original_b0[5], original_b0[6], original_b0[7]);
308 } else {
309 printf("!\nError: unable to read block 0x%02x\n", 0);
310 directWrite = false;
311 }
312 printf(" Attempt to write Block 0 (pages 0-2) ...\n");
313 for (uint32_t page = 0; page <= 2; page++) {
314 printf(" Writing Page %i:", page);
315 memcpy(mp.mpd.abtData, original_b0 + page * 4, 4);
316 for (int i = 0; i < 4; i++) {
317 printf(" %02x", mp.mpd.abtData[i]);
318 }
319 printf("\n");
320 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) {
321 printf(" Failure writing Page %i\n", page);
322 directWrite = false;
323 break;
324 }
325 }
326 if (directWrite) {
327 printf(" Block 0 written successfully\n");
328 printf("Card is DirectWrite\n");
329 return true;
330 } else {
331 printf("Card is not DirectWrite\n");
332 return unlock_card();
333 }
334
335 }
336
337 static bool
338 write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid)
111339 {
112340 uint32_t uiBlock = 0;
113341 bool bFailure = false;
114 uint32_t uiWritenPages = 0;
342 uint32_t uiWrittenPages = 0;
115343 uint32_t uiSkippedPages = 0;
344 uint32_t uiFailedPages = 0;
116345
117346 char buffer[BUFSIZ];
118 bool write_otp;
119 bool write_lock;
120 bool write_uid;
121
122 printf("Write OTP bytes ? [yN] ");
123 if (!fgets(buffer, BUFSIZ, stdin)) {
124 ERR("Unable to read standard input.");
125 }
126 write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
127 printf("Write Lock bytes ? [yN] ");
128 if (!fgets(buffer, BUFSIZ, stdin)) {
129 ERR("Unable to read standard input.");
130 }
131 write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
132 printf("Write UID bytes (only for special writeable UID cards) ? [yN] ");
133 if (!fgets(buffer, BUFSIZ, stdin)) {
134 ERR("Unable to read standard input.");
135 }
136 write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
137
138 printf("Writing %d pages |", uiBlocks + 1);
347
348 if (!write_otp) {
349 printf("Write OTP/Capability Bytes ? [yN] ");
350 if (!fgets(buffer, BUFSIZ, stdin)) {
351 ERR("Unable to read standard input.");
352 }
353 write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
354 }
355
356 // Lock Bytes are OTP if set, so warn
357 if (!write_lock) {
358 printf("Write Lock Bytes (Warning: OTP if set) ? [yN] ");
359 if (!fgets(buffer, BUFSIZ, stdin)) {
360 ERR("Unable to read standard input.");
361 }
362 write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
363 }
364
365 // NTAG and MF0UL21 have additional lock bytes
366 if (!write_dyn_lock && (iNTAGType != NTAG_NONE || iEV1Type == EV1_UL21)) {
367 printf("Write Dynamic Lock Bytes ? [yN] ");
368 if (!fgets(buffer, BUFSIZ, stdin)) {
369 ERR("Unable to read standard input.");
370 }
371 write_dyn_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
372 }
373
374 if (!write_uid) {
375 printf("Write UID bytes (only for special writeable UID cards) ? [yN] ");
376 if (!fgets(buffer, BUFSIZ, stdin)) {
377 ERR("Unable to read standard input.");
378 }
379 write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
380 }
381
139382 /* We may need to skip 2 first pages. */
140383 if (!write_uid) {
384 printf("Writing %d pages |", uiBlocks);
141385 printf("ss");
142386 uiSkippedPages = 2;
143 }
144
145 for (int page = uiSkippedPages; page <= 0xF; page++) {
146 if ((page == 0x2) && (!write_lock)) {
387 } else {
388 if (!check_magic()) {
389 printf("\nUnable to unlock card - are you sure the card is magic?\n");
390 return false;
391 }
392 printf("Writing %d pages |", uiBlocks);
393 }
394
395 for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) {
396 if ((!write_lock) && page == 0x2) {
147397 printf("s");
148398 uiSkippedPages++;
149399 continue;
150400 }
401 // OTP/Capability blocks
151402 if ((page == 0x3) && (!write_otp)) {
152403 printf("s");
153404 uiSkippedPages++;
154405 continue;
155406 }
156 // Show if the readout went well
407 // NTAG and MF0UL21 have Dynamic Lock Bytes
408 if (((iEV1Type == EV1_UL21 && page == 0x24) || \
409 (iNTAGType == NTAG_213 && page == 0x28) || \
410 (iNTAGType == NTAG_215 && page == 0x82) || \
411 (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_dyn_lock)) {
412 printf("s");
413 uiSkippedPages++;
414 continue;
415 }
416 // Check if the previous readout went well
157417 if (bFailure) {
158418 // When a failure occured we need to redo the anti-collision
159419 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
167427 // page (4 bytes). The Ultralight-specific Write command only
168428 // writes one page at a time.
169429 uiBlock = page / 4;
170 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16);
430 memcpy(mp.mpd.abtData, mtDump.ul[uiBlock].mbd.abtData + ((page % 4) * 4), 4);
431 memset(mp.mpd.abtData + 4, 0, 12);
171432 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp))
172433 bFailure = true;
173
174 print_success_or_failure(bFailure, &uiWritenPages);
434 print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages);
175435 }
176436 printf("|\n");
177 printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages);
178
179 return true;
437 printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks, uiSkippedPages, uiFailedPages);
438
439 return true;
440 }
441
442 static int list_passive_targets(nfc_device *_pnd)
443 {
444 int res = 0;
445
446 nfc_target ant[MAX_TARGET_COUNT];
447
448 if (nfc_initiator_init(_pnd) < 0) {
449 return -EXIT_FAILURE;
450 }
451
452 if ((res = nfc_initiator_list_passive_targets(_pnd, nmMifare, ant, MAX_TARGET_COUNT)) >= 0) {
453 int i;
454
455 if (res > 0)
456 printf("%d ISO14443A passive target(s) found:\n", res);
457
458 for (i = 0; i < res; i++) {
459 size_t szPos;
460
461 printf("\t");
462 for (szPos = 0; szPos < ant[i].nti.nai.szUidLen; szPos++) {
463 printf("%02x", ant[i].nti.nai.abtUid[szPos]);
464 }
465 printf("\n");
466 }
467
468 }
469
470 return 0;
471 }
472
473 static size_t str_to_uid(const char *str, uint8_t *uid)
474 {
475 uint8_t i;
476
477 memset(uid, 0x0, MAX_UID_LEN);
478 i = 0;
479 while ((*str != '\0') && ((i >> 1) < MAX_UID_LEN)) {
480 char nibble[2] = { 0x00, '\n' }; /* for strtol */
481
482 nibble[0] = *str++;
483 if (isxdigit(nibble[0])) {
484 if (isupper(nibble[0]))
485 nibble[0] = tolower(nibble[0]);
486 uid[i >> 1] |= strtol(nibble, NULL, 16) << ((i % 2) ? 0 : 4) & ((i % 2) ? 0x0f : 0xf0);
487 i++;
488 }
489 }
490 return i >> 1;
491 }
492
493 static void
494 print_usage(const char *argv[])
495 {
496 printf("Usage: %s r|w <dump.mfd> [OPTIONS]\n", argv[0]);
497 printf("Arguments:\n");
498 printf("\tr|w - Perform read or write\n");
499 printf("\t<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
500 printf("Options:\n");
501 printf("\t--otp - Don't prompt for OTP Bytes writing (Assume yes)\n");
502 printf("\t--lock - Don't prompt for Lock Bytes (OTP) writing (Assume yes)\n");
503 printf("\t--dynlock - Don't prompt for Dynamic Lock Bytes writing (Assume yes)\n");
504 printf("\t--uid - Don't prompt for UID writing (Assume yes)\n");
505 printf("\t--full - Assume full card write (UID + OTP + Lockbytes + Dynamic Lockbytes)\n");
506 printf("\t--with-uid <UID> - Specify UID to read/write from\n");
507 printf("\t--pw <PWD> - Specify 8 HEX digit PASSWORD for EV1\n");
508 printf("\t--partial - Allow source data size to be other than tag capacity\n");
180509 }
181510
182511 int
183512 main(int argc, const char *argv[])
184513 {
185 bool bReadAction;
514 int iAction = 0;
515 size_t iDumpSize = sizeof(mifareul_tag);
516 uint8_t iUID[MAX_UID_LEN] = { 0x0 };
517 size_t szUID = 0;
518 bool bOTP = false;
519 bool bLock = false;
520 bool bDynLock = false;
521 bool bUID = false;
522 bool bPWD = false;
523 bool bPart = false;
524 bool bFilename = false;
186525 FILE *pfDump;
187526
188 if (argc < 3) {
189 printf("\n");
190 printf("%s r|w <dump.mfd>\n", argv[0]);
191 printf("\n");
192 printf("r|w - Perform read from or write to card\n");
193 printf("<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
194 printf("\n");
527 if (argc == 0) {
528 print_usage(argv);
195529 exit(EXIT_FAILURE);
196530 }
197531
198532 DBG("\nChecking arguments and settings\n");
199533
200 bReadAction = tolower((int)((unsigned char) * (argv[1])) == 'r');
201
202 if (bReadAction) {
203 memset(&mtDump, 0x00, sizeof(mtDump));
204 } else {
205 pfDump = fopen(argv[2], "rb");
206
207 if (pfDump == NULL) {
208 ERR("Could not open dump file: %s\n", argv[2]);
209 exit(EXIT_FAILURE);
210 }
211
212 if (fread(&mtDump, 1, sizeof(mtDump), pfDump) != sizeof(mtDump)) {
213 ERR("Could not read from dump file: %s\n", argv[2]);
214 fclose(pfDump);
215 exit(EXIT_FAILURE);
216 }
217 fclose(pfDump);
218 }
219 DBG("Successfully opened the dump file\n");
534 // Get commandline options
535 for (int arg = 1; arg < argc; arg++) {
536 if (0 == strcmp(argv[arg], "r")) {
537 iAction = 1;
538 } else if (0 == strcmp(argv[arg], "w")) {
539 iAction = 2;
540 } else if (0 == strcmp(argv[arg], "--with-uid")) {
541 if (arg + 1 == argc) {
542 ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4");
543 exit(EXIT_FAILURE);
544 }
545 szUID = str_to_uid(argv[++arg], iUID);
546 } else if (0 == strcmp(argv[arg], "--full")) {
547 bOTP = true;
548 bLock = true;
549 bDynLock = true;
550 bUID = true;
551 } else if (0 == strcmp(argv[arg], "--otp")) {
552 bOTP = true;
553 } else if (0 == strcmp(argv[arg], "--lock")) {
554 bLock = true;
555 } else if (0 == strcmp(argv[arg], "--dynlock")) {
556 bDynLock = true;
557 } else if (0 == strcmp(argv[arg], "--uid")) {
558 bUID = true;
559 } else if (0 == strcmp(argv[arg], "--check-magic")) {
560 iAction = 3;
561 } else if (0 == strcmp(argv[arg], "--partial")) {
562 bPart = true;
563 } else if (0 == strcmp(argv[arg], "--pw")) {
564 bPWD = true;
565 if (arg + 1 == argc || strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) {
566 ERR("Please supply a PASSWORD of 8 HEX digits");
567 exit(EXIT_FAILURE);
568 }
569 } else {
570 //Skip validation of the filename
571 if (arg != 2) {
572 ERR("%s is not a supported option.", argv[arg]);
573 print_usage(argv);
574 exit(EXIT_FAILURE);
575 } else {
576 bFilename = true;
577 }
578 }
579 }
580 if (iAction != 3 && !bFilename) {
581 ERR("Please supply a Mifare Dump filename");
582 exit(EXIT_FAILURE);
583 }
220584
221585 nfc_context *context;
222586 nfc_init(&context);
232596 nfc_exit(context);
233597 exit(EXIT_FAILURE);
234598 }
599 printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
600
601 if (list_passive_targets(pnd)) {
602 nfc_perror(pnd, "nfc_device_set_property_bool");
603 nfc_close(pnd);
604 nfc_exit(context);
605 exit(EXIT_FAILURE);
606 }
235607
236608 if (nfc_initiator_init(pnd) < 0) {
237609 nfc_perror(pnd, "nfc_initiator_init");
248620 exit(EXIT_FAILURE);
249621 }
250622
251 printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
252
253623 // Try to find a MIFARE Ultralight tag
254 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
624 if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) {
255625 ERR("no tag was found\n");
256626 nfc_close(pnd);
257627 nfc_exit(context);
258628 exit(EXIT_FAILURE);
259629 }
630
260631 // Test if we are dealing with a MIFARE compatible tag
261
262632 if (nt.nti.nai.abtAtqa[1] != 0x44) {
263633 ERR("tag is not a MIFARE Ultralight card\n");
264634 nfc_close(pnd);
266636 exit(EXIT_FAILURE);
267637 }
268638 // Get the info from the current tag
269 printf("Found MIFARE Ultralight card with UID: ");
639 printf("Using MIFARE Ultralight card with UID: ");
270640 size_t szPos;
271641 for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) {
272642 printf("%02x", nt.nti.nai.abtUid[szPos]);
273643 }
274644 printf("\n");
275645
276 if (bReadAction) {
277 if (read_card()) {
278 printf("Writing data to file: %s ... ", argv[2]);
279 fflush(stdout);
280 pfDump = fopen(argv[2], "wb");
281 if (pfDump == NULL) {
282 printf("Could not open file: %s\n", argv[2]);
283 nfc_close(pnd);
284 nfc_exit(context);
285 exit(EXIT_FAILURE);
286 }
287 if (fwrite(&mtDump, 1, sizeof(mtDump), pfDump) != sizeof(mtDump)) {
288 printf("Could not write to file: %s\n", argv[2]);
289 fclose(pfDump);
290 nfc_close(pnd);
291 nfc_exit(context);
292 exit(EXIT_FAILURE);
293 }
646 // test if tag is EV1 or NTAG
647 if (get_ev1_version()) {
648 if (!bPWD)
649 printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n");
650 if (abtRx[6] == 0x0b || abtRx[6] == 0x00) {
651 printf("EV1 type: MF0UL11 (48 bytes)\n");
652 uiBlocks = 20; // total number of 4 byte 'pages'
653 iDumpSize = uiBlocks * 4;
654 iEV1Type = EV1_UL11;
655 } else if (abtRx[6] == 0x0e) {
656 printf("EV1 type: MF0UL21 (128 user bytes)\n");
657 uiBlocks = 41;
658 iDumpSize = uiBlocks * 4;
659 iEV1Type = EV1_UL21;
660 } else if (abtRx[6] == 0x0f) {
661 printf("NTAG Type: NTAG213 (144 user bytes)\n");
662 uiBlocks = 45;
663 iDumpSize = uiBlocks * 4;
664 iNTAGType = NTAG_213;
665 } else if (abtRx[6] == 0x11) {
666 printf("NTAG Type: NTAG215 (504 user bytes)\n");
667 uiBlocks = 135;
668 iDumpSize = uiBlocks * 4;
669 iNTAGType = NTAG_215;
670 } else if (abtRx[6] == 0x13) {
671 printf("NTAG Type: NTAG216 (888 user bytes)\n");
672 uiBlocks = 231;
673 iDumpSize = uiBlocks * 4;
674 iNTAGType = NTAG_216;
675 } else {
676 printf("unknown! (0x%02x)\n", abtRx[6]);
677 exit(EXIT_FAILURE);
678 }
679 } else {
680 // re-init non EV1 tag
681 if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) {
682 ERR("no tag was found\n");
683 nfc_close(pnd);
684 nfc_exit(context);
685 exit(EXIT_FAILURE);
686 }
687 }
688
689 // EV1 login required
690 if (bPWD) {
691 printf("Authing with PWD: %02x%02x%02x%02x ", iPWD[0], iPWD[1], iPWD[2], iPWD[3]);
692 if (!ev1_pwd_auth(iPWD)) {
693 printf("\n");
694 ERR("AUTH failed!\n");
695 exit(EXIT_FAILURE);
696 } else {
697 printf("Success - PACK: %02x%02x\n", abtRx[0], abtRx[1]);
698 memcpy(iPACK, abtRx, 2);
699 }
700 }
701
702 if (iAction == 1) {
703 memset(&mtDump, 0x00, sizeof(mtDump));
704 } else if (iAction == 2) {
705 pfDump = fopen(argv[2], "rb");
706
707 if (pfDump == NULL) {
708 ERR("Could not open dump file: %s\n", argv[2]);
709 exit(EXIT_FAILURE);
710 }
711
712 size_t szDump;
713 if (((szDump = fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) {
714 ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], (unsigned long)szDump, (unsigned long)iDumpSize);
294715 fclose(pfDump);
295 printf("Done.\n");
296 }
716 exit(EXIT_FAILURE);
717 }
718 if (szDump != iDumpSize)
719 printf("Performing partial write\n");
720 fclose(pfDump);
721 DBG("Successfully opened the dump file\n");
722 } else if (iAction == 3) {
723 DBG("Switching to Check Magic Mode\n");
297724 } else {
298 write_card();
725 ERR("Unable to determine operating mode");
726 exit(EXIT_FAILURE);
727 }
728
729 if (iAction == 1) {
730 bool bRF = read_card();
731 printf("Writing data to file: %s ... ", argv[2]);
732 fflush(stdout);
733 pfDump = fopen(argv[2], "wb");
734 if (pfDump == NULL) {
735 printf("Could not open file: %s\n", argv[2]);
736 nfc_close(pnd);
737 nfc_exit(context);
738 exit(EXIT_FAILURE);
739 }
740 if (fwrite(&mtDump, 1, uiReadPages * 4, pfDump) != uiReadPages * 4) {
741 printf("Could not write to file: %s\n", argv[2]);
742 fclose(pfDump);
743 nfc_close(pnd);
744 nfc_exit(context);
745 exit(EXIT_FAILURE);
746 }
747 fclose(pfDump);
748 printf("Done.\n");
749 if (!bRF)
750 printf("Warning! Read failed - partial data written to file!\n");
751 } else if (iAction == 2) {
752 write_card(bOTP, bLock, bDynLock, bUID);
753 } else if (iAction == 3) {
754 if (!check_magic()) {
755 printf("Card is not magic\n");
756 nfc_close(pnd);
757 nfc_exit(context);
758 exit(EXIT_FAILURE);
759 } else {
760 printf("Card is magic\n");
761 }
299762 }
300763
301764 nfc_close(pnd);
2929 .B libnfc
3030 issue tracker at:
3131 .br
32 .BR http://code.google.com/p/libnfc/issues
32 .BR https://github.com/nfc-tools/libnfc/issues
3333 .SH LICENCE
3434 .B libnfc
3535 is licensed under the GNU Lesser General Public License (LGPL), version 3.
177177 case 'h':
178178 print_usage(argv[0]);
179179 exit(EXIT_SUCCESS);
180 break;
181180 case 'q':
182181 quiet = true;
183182 break;
3333 Commands are read from file descriptor 3
3434 Responses are sent to file descriptor 4
3535
36 \fB-s\fP
37 Swap roles of found devices
38 Usually the first found device is used as target (emulator) and the second
39 as initiator (reader). Using this option these roles are inversed.
40
3641 \fB-n\fP \fIN\fP
3742 Adds a waiting time of \fIN\fP seconds (integer) in the loop
3843
6469 .B libnfc
6570 issue tracker at:
6671 .br
67 .BR http://code.google.com/p/libnfc/issues
72 .BR https://github.com/nfc-tools/libnfc/issues
6873 .SH LICENCE
6974 .B libnfc
7075 is licensed under the GNU Lesser General Public License (LGPL), version 3.
9898 printf("\t-q\tQuiet mode. Suppress printing of relayed data (improves timing).\n");
9999 printf("\t-t\tTarget mode only (the one on reader side). Data expected from FD3 to FD4.\n");
100100 printf("\t-i\tInitiator mode only (the one on tag side). Data expected from FD3 to FD4.\n");
101 printf("\t-s\tSwap roles of found devices.\n");
101102 printf("\t-n N\tAdds a waiting time of N seconds (integer) in the relay to mimic long distance.\n");
102103 }
103104
225226 nfc_exit(context);
226227 exit(EXIT_FAILURE);
227228 }
228 if ((fd4 = fdopen(4, "r")) == NULL) {
229 if ((fd4 = fdopen(4, "w")) == NULL) {
229230 ERR("Could not open file descriptor 4");
230231 nfc_exit(context);
231232 exit(EXIT_FAILURE);
3838 .B libnfc
3939 issue tracker at:
4040 .br
41 .BR http://code.google.com/p/libnfc/issues
41 .BR https://github.com/nfc-tools/libnfc/issues
4242 .SH LICENCE
4343 .B libnfc
4444 is licensed under the GNU Lesser General Public License (LGPL), version 3.