Compare commits
No commits in common. "master" and "libnfc-1.7.2" have entirely different histories.
master
...
libnfc-1.7
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,8 +7,6 @@
|
|||||||
*.lo
|
*.lo
|
||||||
*.o
|
*.o
|
||||||
*~
|
*~
|
||||||
.vs/
|
|
||||||
CMakeSettings.json
|
|
||||||
Doxyfile
|
Doxyfile
|
||||||
INSTALL
|
INSTALL
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
|
|||||||
91
.travis.yml
91
.travis.yml
@ -1,81 +1,20 @@
|
|||||||
language: c
|
language: c
|
||||||
|
|
||||||
matrix:
|
compiler:
|
||||||
include:
|
- clang
|
||||||
- os: windows
|
- gcc
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
before_install:
|
|
||||||
- mkdir build && cd build && wget "https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/libusb-win32-bin-1.2.6.0.zip" && 7z x libusb-win32-bin-1.2.6.0.zip -o"$PROGRAMFILES" && mv "$PROGRAMFILES/libusb-win32-bin-1.2.6.0" "$PROGRAMFILES/libusb-win32"
|
|
||||||
install:
|
|
||||||
choco install doxygen.install ninja
|
|
||||||
script:
|
|
||||||
cmake -GNinja .. && cmake --build .
|
|
||||||
|
|
||||||
- os: linux
|
env:
|
||||||
dist: bionic
|
- BLD=cmake
|
||||||
compiler:
|
- BLD=autoconf
|
||||||
- clang
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
- cmake
|
|
||||||
script:
|
|
||||||
- mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
|
|
||||||
|
|
||||||
- os: linux
|
addons:
|
||||||
dist: bionic
|
apt:
|
||||||
compiler:
|
packages:
|
||||||
- clang
|
- libusb-dev
|
||||||
addons:
|
- doxygen
|
||||||
apt:
|
- cmake
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
script:
|
|
||||||
- autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
|
|
||||||
|
|
||||||
- os: linux
|
script:
|
||||||
dist: bionic
|
- if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi
|
||||||
compiler:
|
- if [ $BLD == cmake ]; then mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install; fi
|
||||||
- gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
- cmake
|
|
||||||
script:
|
|
||||||
- mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: bionic
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libusb-dev
|
|
||||||
- doxygen
|
|
||||||
script:
|
|
||||||
- autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
|
|
||||||
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode12
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
before_install:
|
|
||||||
- brew install doxygen libusb-compat
|
|
||||||
script:
|
|
||||||
- mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install
|
|
||||||
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode12
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
before_install:
|
|
||||||
- brew install doxygen libusb-compat m4
|
|
||||||
script:
|
|
||||||
- autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install
|
|
||||||
|
|||||||
@ -7,8 +7,8 @@ endif ()
|
|||||||
project (libnfc C)
|
project (libnfc C)
|
||||||
|
|
||||||
SET(VERSION_MAJOR "1")
|
SET(VERSION_MAJOR "1")
|
||||||
SET(VERSION_MINOR "8")
|
SET(VERSION_MINOR "7")
|
||||||
SET(VERSION_PATCH "0")
|
SET(VERSION_PATCH "2")
|
||||||
|
|
||||||
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||||
|
|
||||||
@ -18,12 +18,9 @@ SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
|||||||
|
|
||||||
# config.h
|
# config.h
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(LIBNFC_SYSCONFDIR "./config" CACHE PATH "libnfc configuration directory")
|
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
SET(LIBNFC_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/config" CACHE PATH "libnfc configuration directory")
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32)
|
||||||
IF(NOT MINGW)
|
|
||||||
SET(CMAKE_C_FLAGS "-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE ${CMAKE_C_FLAGS}")
|
|
||||||
ENDIF(NOT MINGW)
|
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
SET(_XOPEN_SOURCE 600)
|
SET(_XOPEN_SOURCE 600)
|
||||||
SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
|
SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
|
||||||
@ -141,12 +138,9 @@ IF(NOT WIN32)
|
|||||||
IF(LIBNFC_DRIVER_PN53X_USB)
|
IF(LIBNFC_DRIVER_PN53X_USB)
|
||||||
SET(PKG_REQ ${PKG_REQ} "libusb")
|
SET(PKG_REQ ${PKG_REQ} "libusb")
|
||||||
ENDIF(LIBNFC_DRIVER_PN53X_USB)
|
ENDIF(LIBNFC_DRIVER_PN53X_USB)
|
||||||
IF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
SET(PKG_REQ ${PKG_REQ} "libusb")
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
IF(LIBNFC_DRIVER_PCSC)
|
IF(LIBNFC_DRIVER_PCSC)
|
||||||
SET(PKG_REQ ${PKG_REQ} "libpcsclite")
|
SET(PKG_REQ ${PKG_REQ} "libpcsclite")
|
||||||
ENDIF(LIBNFC_DRIVER_PCSC)
|
ENDIF(LIBNFC_DRIVER_ACR122)
|
||||||
IF(LIBNFC_DRIVER_ACR122_PCSC)
|
IF(LIBNFC_DRIVER_ACR122_PCSC)
|
||||||
SET(PKG_REQ ${PKG_REQ} "libpcsclite")
|
SET(PKG_REQ ${PKG_REQ} "libpcsclite")
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
|
ENDIF(LIBNFC_DRIVER_ACR122_PCSC)
|
||||||
@ -158,7 +152,7 @@ ENDIF(NOT WIN32)
|
|||||||
|
|
||||||
INCLUDE(LibnfcDrivers)
|
INCLUDE(LibnfcDrivers)
|
||||||
|
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
IF(UNIX AND NOT APPLE)
|
||||||
IF(I2C_REQUIRED)
|
IF(I2C_REQUIRED)
|
||||||
# Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html
|
# Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html
|
||||||
INCLUDE (CheckFunctionExists)
|
INCLUDE (CheckFunctionExists)
|
||||||
@ -172,7 +166,7 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||||||
ENDIF (HAVE_CLOCK_GETTIME_IN_RT)
|
ENDIF (HAVE_CLOCK_GETTIME_IN_RT)
|
||||||
ENDIF (NOT HAVE_CLOCK_GETTIME)
|
ENDIF (NOT HAVE_CLOCK_GETTIME)
|
||||||
ENDIF(I2C_REQUIRED)
|
ENDIF(I2C_REQUIRED)
|
||||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
ENDIF(UNIX AND NOT APPLE)
|
||||||
|
|
||||||
IF(PCSC_INCLUDE_DIRS)
|
IF(PCSC_INCLUDE_DIRS)
|
||||||
INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS})
|
INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS})
|
||||||
@ -207,8 +201,7 @@ IF(WIN32)
|
|||||||
SET(RC_COMMENT "${PACKAGE_NAME} library")
|
SET(RC_COMMENT "${PACKAGE_NAME} library")
|
||||||
SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}")
|
SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}")
|
||||||
SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll)
|
SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll)
|
||||||
# RC_FILE_TYPE: VFT_DLL
|
SET(RC_FILE_TYPE VFT_DLL)
|
||||||
SET(RC_FILE_TYPE 0x00000002L)
|
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/windows/libnfc.rc @ONLY)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/windows/libnfc.rc @ONLY)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
|
|||||||
12
ChangeLog
12
ChangeLog
@ -1,14 +1,4 @@
|
|||||||
May 22, 2020 - 1.8.0
|
May 21, 2020 - 1.7.2
|
||||||
--------------------
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
- Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Bump revision due to changes in API introduced in v1.7.2
|
|
||||||
- Bump library version to 6.0.0
|
|
||||||
|
|
||||||
May 21, 2020 - 1.7.2 (avoid using it, incompatible with 1.7.1)
|
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
Fixes:
|
Fixes:
|
||||||
|
|||||||
2486
Doxyfile.in
2486
Doxyfile.in
File diff suppressed because it is too large
Load Diff
@ -2,13 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
|
|||||||
|
|
||||||
AM_CFLAGS = $(LIBNFC_CFLAGS)
|
AM_CFLAGS = $(LIBNFC_CFLAGS)
|
||||||
|
|
||||||
SUBDIRS = libnfc utils
|
SUBDIRS = libnfc utils examples include contrib cmake test
|
||||||
|
|
||||||
if EXAMPLE_ENABLED
|
|
||||||
SUBDIRS += examples
|
|
||||||
endif
|
|
||||||
|
|
||||||
SUBDIRS += include contrib cmake test
|
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = libnfc.pc
|
pkgconfig_DATA = libnfc.pc
|
||||||
|
|||||||
6
NEWS.md
6
NEWS.md
@ -1,9 +1,3 @@
|
|||||||
New in 1.8.0:
|
|
||||||
|
|
||||||
API Changes:
|
|
||||||
- Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
|
|
||||||
- Bump library version to 6.0.0
|
|
||||||
|
|
||||||
New in 1.7.2:
|
New in 1.7.2:
|
||||||
|
|
||||||
Drivers:
|
Drivers:
|
||||||
|
|||||||
46
README.md
46
README.md
@ -40,7 +40,7 @@ Some NFC drivers depend on third party software:
|
|||||||
|
|
||||||
* acr122_pcsc:
|
* acr122_pcsc:
|
||||||
|
|
||||||
- pcsc-lite https://pcsclite.apdu.fr/
|
- pcsc-lite http://pcsclite.alioth.debian.org/
|
||||||
- pcsc:
|
- pcsc:
|
||||||
|
|
||||||
- Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test.
|
- Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test.
|
||||||
@ -48,29 +48,12 @@ Some NFC drivers depend on third party software:
|
|||||||
The regression test suite depends on the cutter framework:
|
The regression test suite depends on the cutter framework:
|
||||||
http://cutter.sf.net
|
http://cutter.sf.net
|
||||||
|
|
||||||
Building
|
|
||||||
========
|
|
||||||
|
|
||||||
Note: If working directly from a git clone of the repository, some of the files need to be generated first. To do this run
|
|
||||||
`autoreconf -vis`
|
|
||||||
|
|
||||||
Alternatively use a .tar.bz2 version of a packaged release (which already contains ./configure):
|
|
||||||
https://github.com/nfc-tools/libnfc/releases/
|
|
||||||
|
|
||||||
The build should be as simple as running these commands:
|
|
||||||
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
|
|
||||||
|
|
||||||
To build with specific driver(s), see option `--with-drivers=...` detailed in `./configure --help`.
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
make install
|
See the file `INSTALL` for configure, build and install details.
|
||||||
|
|
||||||
You may need to grant permissions to your user to drive your device.
|
Additionnally, you may need to grant permissions to your user to drive your device.
|
||||||
Under GNU/Linux systems, if you use udev, you could use the provided udev rules.
|
Under GNU/Linux systems, if you use udev, you could use the provided udev rules.
|
||||||
e.g. under Debian, Ubuntu, etc.
|
e.g. under Debian, Ubuntu, etc.
|
||||||
|
|
||||||
@ -102,17 +85,6 @@ file per device in a nfc/devices.d directory:
|
|||||||
printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf
|
printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf
|
||||||
printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf
|
printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf
|
||||||
|
|
||||||
Environment Variables
|
|
||||||
=====================
|
|
||||||
You can override certain configuration options at runtime using the following environment variables:
|
|
||||||
+ `LIBNFC_DEFAULT_DEVICE=<connstring>`: `LIBNFC_DEFAULT_DEVICE=pn532_uart:/dev/ttyACM0` will use pn532 on /dev/ttyACM0 as default device
|
|
||||||
+ `LIBNFC_DEVICE=<connstring>` will ignore all devices in the config files and use only the one defined in the variable
|
|
||||||
+ `LIBNFC_AUTO_SCAN=<true|false>` overrides `allow_autoscan` option in the config file
|
|
||||||
+ `LIBNFC_INTRUSIVE_SCAN=<true|false>` overrides `allow_intrusive_scan` option in the config file
|
|
||||||
+ `LIBNFC_LOG_LEVEL=<0|1|2|3>` overrides `log_level` option in the config file
|
|
||||||
|
|
||||||
To obtain the connstring of a recognized device, you can use `nfc-scan-device`: `LIBNFC_AUTO_SCAN=true nfc-scan-device` will show the names & connstrings of all found devices.
|
|
||||||
|
|
||||||
How to report bugs
|
How to report bugs
|
||||||
==================
|
==================
|
||||||
|
|
||||||
@ -168,6 +140,18 @@ Patches can be posted to https://github.com/nfc-tools/libnfc/issues
|
|||||||
If the patch fixes a bug, it is usually a good idea to include
|
If the patch fixes a bug, it is usually a good idea to include
|
||||||
all the information described in "How to Report Bugs".
|
all the information described in "How to Report Bugs".
|
||||||
|
|
||||||
|
Building
|
||||||
|
========
|
||||||
|
|
||||||
|
It should be as simple as running these two commands:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
|
||||||
|
To build with specific driver(s), see option `--with-drivers=...` detailed in `./configure --help`.
|
||||||
|
|
||||||
|
Note: if you're using directly the development repository and not the release sources, you will have to execute firstly `autoreconf -vis`.
|
||||||
|
|
||||||
Troubleshooting
|
Troubleshooting
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|||||||
@ -26,15 +26,9 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
|
|||||||
|
|
||||||
IF(NOT LIBUSB_FOUND)
|
IF(NOT LIBUSB_FOUND)
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
IF(MINGW)
|
FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramFiles}/LibUSB-Win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
|
||||||
FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
|
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramFiles}/LibUSB-Win32/lib/gcc")
|
||||||
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/lib/gcc")
|
SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramFiles}/LibUSB-Win32/bin/x86/")
|
||||||
SET(LIBUSB_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/bin/x86/")
|
|
||||||
ELSE(MINGW)
|
|
||||||
FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramW6432}/libusb-win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
|
|
||||||
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64")
|
|
||||||
SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramW6432}/libusb-win32/bin/amd64/")
|
|
||||||
ENDIF(MINGW)
|
|
||||||
# Must fix up variable to avoid backslashes during packaging
|
# Must fix up variable to avoid backslashes during packaging
|
||||||
STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR})
|
STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR})
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
|
|||||||
@ -3,13 +3,13 @@ SET(LIBNFC_DRIVER_ACR122_PCSC OFF CACHE BOOL "Enable ACR122 support (Depends on
|
|||||||
SET(LIBNFC_DRIVER_ACR122_USB ON CACHE BOOL "Enable ACR122 support (Direct USB connection)")
|
SET(LIBNFC_DRIVER_ACR122_USB ON CACHE BOOL "Enable ACR122 support (Direct USB connection)")
|
||||||
SET(LIBNFC_DRIVER_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)")
|
SET(LIBNFC_DRIVER_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)")
|
||||||
SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)")
|
SET(LIBNFC_DRIVER_ARYGON ON CACHE BOOL "Enable ARYGON support (Use serial port)")
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
IF(WIN32)
|
||||||
SET(LIBNFC_DRIVER_PN532_I2C ON CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
|
|
||||||
SET(LIBNFC_DRIVER_PN532_SPI ON CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
|
|
||||||
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
SET(LIBNFC_DRIVER_PN532_I2C OFF CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
|
SET(LIBNFC_DRIVER_PN532_I2C OFF CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
|
||||||
SET(LIBNFC_DRIVER_PN532_SPI OFF CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
|
SET(LIBNFC_DRIVER_PN532_SPI OFF CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
|
||||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
ELSE(WIN32)
|
||||||
|
SET(LIBNFC_DRIVER_PN532_I2C ON CACHE BOOL "Enable PN532 I2C support (Use I2C bus)")
|
||||||
|
SET(LIBNFC_DRIVER_PN532_SPI ON CACHE BOOL "Enable PN532 SPI support (Use SPI bus)")
|
||||||
|
ENDIF(WIN32)
|
||||||
SET(LIBNFC_DRIVER_PN532_UART ON CACHE BOOL "Enable PN532 UART support (Use serial port)")
|
SET(LIBNFC_DRIVER_PN532_UART ON CACHE BOOL "Enable PN532 UART support (Use serial port)")
|
||||||
SET(LIBNFC_DRIVER_PN53X_USB ON CACHE BOOL "Enable PN531 and PN531 USB support (Depends on libusb)")
|
SET(LIBNFC_DRIVER_PN53X_USB ON CACHE BOOL "Enable PN531 and PN531 USB support (Depends on libusb)")
|
||||||
|
|
||||||
@ -68,11 +68,4 @@ IF(LIBNFC_DRIVER_PN53X_USB)
|
|||||||
SET(USB_REQUIRED TRUE)
|
SET(USB_REQUIRED TRUE)
|
||||||
ENDIF(LIBNFC_DRIVER_PN53X_USB)
|
ENDIF(LIBNFC_DRIVER_PN53X_USB)
|
||||||
|
|
||||||
IF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
FIND_PACKAGE(LIBUSB REQUIRED)
|
|
||||||
ADD_DEFINITIONS("-DDRIVER_ACR122_USB_ENABLED")
|
|
||||||
SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/acr122_usb")
|
|
||||||
SET(USB_REQUIRED TRUE)
|
|
||||||
ENDIF(LIBNFC_DRIVER_ACR122_USB)
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers)
|
||||||
|
|||||||
13
configure.ac
13
configure.ac
@ -1,7 +1,7 @@
|
|||||||
# General init
|
# General init
|
||||||
|
|
||||||
# /!\ Don't forget to update 'CMakeLists.txt' too /!\
|
# /!\ Don't forget to update 'CMakeLists.txt' too /!\
|
||||||
AC_INIT([libnfc],[1.8.0],[nfc-tools@googlegroups.com])
|
AC_INIT([libnfc],[1.7.2],[nfc-tools@googlegroups.com])
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
@ -157,14 +157,6 @@ then
|
|||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(DOC_ENABLED, [test x"$enable_doc" = xyes])
|
AM_CONDITIONAL(DOC_ENABLED, [test x"$enable_doc" = xyes])
|
||||||
|
|
||||||
# Example build (default: yes)
|
|
||||||
AC_ARG_ENABLE([example],AS_HELP_STRING([--enable-example],[Enable example build.]),[enable_example=$enableval],[enable_example="yes"])
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(for example build)
|
|
||||||
AC_MSG_RESULT($enable_example)
|
|
||||||
|
|
||||||
AM_CONDITIONAL(EXAMPLE_ENABLED, [test x"$enable_example" = xyes])
|
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
PKG_CONFIG_REQUIRES=""
|
PKG_CONFIG_REQUIRES=""
|
||||||
|
|
||||||
@ -183,10 +175,7 @@ if test x$ac_cv_with_cutter = xyes -a x$ac_cv_use_cutter = xno; then
|
|||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([WITH_CUTTER], [test "$ac_cv_use_cutter" != "no"])
|
AM_CONDITIONAL([WITH_CUTTER], [test "$ac_cv_use_cutter" != "no"])
|
||||||
|
|
||||||
if test x"$enable_example" = "xyes"
|
|
||||||
then
|
|
||||||
AC_CHECK_READLINE
|
AC_CHECK_READLINE
|
||||||
fi
|
|
||||||
|
|
||||||
# Help us to write great code ;-)
|
# Help us to write great code ;-)
|
||||||
CFLAGS="$CFLAGS -Wall -pedantic -Wextra"
|
CFLAGS="$CFLAGS -Wall -pedantic -Wextra"
|
||||||
|
|||||||
@ -1,870 +0,0 @@
|
|||||||
/*
|
|
||||||
* Dirent interface for Microsoft Visual Studio
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2012 Toni Ronkko
|
|
||||||
* This file is part of dirent. Dirent may be freely distributed
|
|
||||||
* under the MIT license. For all details and documentation, see
|
|
||||||
* https://github.com/tronkko/dirent
|
|
||||||
*/
|
|
||||||
#ifndef DIRENT_H
|
|
||||||
#define DIRENT_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Include windows.h without Windows Sockets 1.1 to prevent conflicts with
|
|
||||||
* Windows Sockets 2.0.
|
|
||||||
*/
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
/* Indicates that d_type field is available in dirent structure */
|
|
||||||
#define _DIRENT_HAVE_D_TYPE
|
|
||||||
|
|
||||||
/* Indicates that d_namlen field is available in dirent structure */
|
|
||||||
#define _DIRENT_HAVE_D_NAMLEN
|
|
||||||
|
|
||||||
/* Entries missing from MSVC 6.0 */
|
|
||||||
#if !defined(FILE_ATTRIBUTE_DEVICE)
|
|
||||||
# define FILE_ATTRIBUTE_DEVICE 0x40
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* File type and permission flags for stat(), general mask */
|
|
||||||
#if !defined(S_IFMT)
|
|
||||||
# define S_IFMT _S_IFMT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Directory bit */
|
|
||||||
#if !defined(S_IFDIR)
|
|
||||||
# define S_IFDIR _S_IFDIR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Character device bit */
|
|
||||||
#if !defined(S_IFCHR)
|
|
||||||
# define S_IFCHR _S_IFCHR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Pipe bit */
|
|
||||||
#if !defined(S_IFFIFO)
|
|
||||||
# define S_IFFIFO _S_IFFIFO
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Regular file bit */
|
|
||||||
#if !defined(S_IFREG)
|
|
||||||
# define S_IFREG _S_IFREG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read permission */
|
|
||||||
#if !defined(S_IREAD)
|
|
||||||
# define S_IREAD _S_IREAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Write permission */
|
|
||||||
#if !defined(S_IWRITE)
|
|
||||||
# define S_IWRITE _S_IWRITE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Execute permission */
|
|
||||||
#if !defined(S_IEXEC)
|
|
||||||
# define S_IEXEC _S_IEXEC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Pipe */
|
|
||||||
#if !defined(S_IFIFO)
|
|
||||||
# define S_IFIFO _S_IFIFO
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Block device */
|
|
||||||
#if !defined(S_IFBLK)
|
|
||||||
# define S_IFBLK 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Link */
|
|
||||||
#if !defined(S_IFLNK)
|
|
||||||
# define S_IFLNK 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Socket */
|
|
||||||
#if !defined(S_IFSOCK)
|
|
||||||
# define S_IFSOCK 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read user permission */
|
|
||||||
#if !defined(S_IRUSR)
|
|
||||||
# define S_IRUSR S_IREAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Write user permission */
|
|
||||||
#if !defined(S_IWUSR)
|
|
||||||
# define S_IWUSR S_IWRITE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Execute user permission */
|
|
||||||
#if !defined(S_IXUSR)
|
|
||||||
# define S_IXUSR 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read group permission */
|
|
||||||
#if !defined(S_IRGRP)
|
|
||||||
# define S_IRGRP 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Write group permission */
|
|
||||||
#if !defined(S_IWGRP)
|
|
||||||
# define S_IWGRP 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Execute group permission */
|
|
||||||
#if !defined(S_IXGRP)
|
|
||||||
# define S_IXGRP 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read others permission */
|
|
||||||
#if !defined(S_IROTH)
|
|
||||||
# define S_IROTH 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Write others permission */
|
|
||||||
#if !defined(S_IWOTH)
|
|
||||||
# define S_IWOTH 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Execute others permission */
|
|
||||||
#if !defined(S_IXOTH)
|
|
||||||
# define S_IXOTH 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Maximum length of file name */
|
|
||||||
#if !defined(PATH_MAX)
|
|
||||||
# define PATH_MAX MAX_PATH
|
|
||||||
#endif
|
|
||||||
#if !defined(FILENAME_MAX)
|
|
||||||
# define FILENAME_MAX MAX_PATH
|
|
||||||
#endif
|
|
||||||
#if !defined(NAME_MAX)
|
|
||||||
# define NAME_MAX FILENAME_MAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* File type flags for d_type */
|
|
||||||
#define DT_UNKNOWN 0
|
|
||||||
#define DT_REG S_IFREG
|
|
||||||
#define DT_DIR S_IFDIR
|
|
||||||
#define DT_FIFO S_IFIFO
|
|
||||||
#define DT_SOCK S_IFSOCK
|
|
||||||
#define DT_CHR S_IFCHR
|
|
||||||
#define DT_BLK S_IFBLK
|
|
||||||
#define DT_LNK S_IFLNK
|
|
||||||
|
|
||||||
/* Macros for converting between st_mode and d_type */
|
|
||||||
#define IFTODT(mode) ((mode) & S_IFMT)
|
|
||||||
#define DTTOIF(type) (type)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* File type macros. Note that block devices, sockets and links cannot be
|
|
||||||
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
|
|
||||||
* only defined for compatibility. These macros should always return false
|
|
||||||
* on Windows.
|
|
||||||
*/
|
|
||||||
#if !defined(S_ISFIFO)
|
|
||||||
# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
|
||||||
#endif
|
|
||||||
#if !defined(S_ISDIR)
|
|
||||||
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
|
||||||
#endif
|
|
||||||
#if !defined(S_ISREG)
|
|
||||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
|
||||||
#endif
|
|
||||||
#if !defined(S_ISLNK)
|
|
||||||
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
|
||||||
#endif
|
|
||||||
#if !defined(S_ISSOCK)
|
|
||||||
# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
|
||||||
#endif
|
|
||||||
#if !defined(S_ISCHR)
|
|
||||||
# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
|
||||||
#endif
|
|
||||||
#if !defined(S_ISBLK)
|
|
||||||
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return the exact length of the file name without zero terminator */
|
|
||||||
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
|
|
||||||
|
|
||||||
/* Return the maximum size of a file name */
|
|
||||||
#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Wide-character version */
|
|
||||||
struct _wdirent {
|
|
||||||
/* Always zero */
|
|
||||||
long d_ino;
|
|
||||||
|
|
||||||
/* File position within stream */
|
|
||||||
long d_off;
|
|
||||||
|
|
||||||
/* Structure size */
|
|
||||||
unsigned short d_reclen;
|
|
||||||
|
|
||||||
/* Length of name without \0 */
|
|
||||||
size_t d_namlen;
|
|
||||||
|
|
||||||
/* File type */
|
|
||||||
int d_type;
|
|
||||||
|
|
||||||
/* File name */
|
|
||||||
wchar_t d_name[PATH_MAX+1];
|
|
||||||
};
|
|
||||||
typedef struct _wdirent _wdirent;
|
|
||||||
|
|
||||||
struct _WDIR {
|
|
||||||
/* Current directory entry */
|
|
||||||
struct _wdirent ent;
|
|
||||||
|
|
||||||
/* Private file data */
|
|
||||||
WIN32_FIND_DATAW data;
|
|
||||||
|
|
||||||
/* True if data is valid */
|
|
||||||
int cached;
|
|
||||||
|
|
||||||
/* Win32 search handle */
|
|
||||||
HANDLE handle;
|
|
||||||
|
|
||||||
/* Initial directory name */
|
|
||||||
wchar_t *patt;
|
|
||||||
};
|
|
||||||
typedef struct _WDIR _WDIR;
|
|
||||||
|
|
||||||
/* Multi-byte character version */
|
|
||||||
struct dirent {
|
|
||||||
/* Always zero */
|
|
||||||
long d_ino;
|
|
||||||
|
|
||||||
/* File position within stream */
|
|
||||||
long d_off;
|
|
||||||
|
|
||||||
/* Structure size */
|
|
||||||
unsigned short d_reclen;
|
|
||||||
|
|
||||||
/* Length of name without \0 */
|
|
||||||
size_t d_namlen;
|
|
||||||
|
|
||||||
/* File type */
|
|
||||||
int d_type;
|
|
||||||
|
|
||||||
/* File name */
|
|
||||||
char d_name[PATH_MAX+1];
|
|
||||||
};
|
|
||||||
typedef struct dirent dirent;
|
|
||||||
|
|
||||||
struct DIR {
|
|
||||||
struct dirent ent;
|
|
||||||
struct _WDIR *wdirp;
|
|
||||||
};
|
|
||||||
typedef struct DIR DIR;
|
|
||||||
|
|
||||||
|
|
||||||
/* Dirent functions */
|
|
||||||
static DIR *opendir (const char *dirname);
|
|
||||||
static _WDIR *_wopendir (const wchar_t *dirname);
|
|
||||||
|
|
||||||
static struct dirent *readdir (DIR *dirp);
|
|
||||||
|
|
||||||
static int readdir_r(
|
|
||||||
DIR *dirp, struct dirent *entry, struct dirent **result);
|
|
||||||
|
|
||||||
static int closedir (DIR *dirp);
|
|
||||||
static int _wclosedir (_WDIR *dirp);
|
|
||||||
|
|
||||||
/* For compatibility with Symbian */
|
|
||||||
#define wdirent _wdirent
|
|
||||||
#define WDIR _WDIR
|
|
||||||
#define wopendir _wopendir
|
|
||||||
#define wreaddir _wreaddir
|
|
||||||
#define wclosedir _wclosedir
|
|
||||||
#define wrewinddir _wrewinddir
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal utility functions */
|
|
||||||
static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
|
|
||||||
static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
|
|
||||||
|
|
||||||
static int dirent_mbstowcs_s(
|
|
||||||
size_t *pReturnValue,
|
|
||||||
wchar_t *wcstr,
|
|
||||||
size_t sizeInWords,
|
|
||||||
const char *mbstr,
|
|
||||||
size_t count);
|
|
||||||
|
|
||||||
static int dirent_wcstombs_s(
|
|
||||||
size_t *pReturnValue,
|
|
||||||
char *mbstr,
|
|
||||||
size_t sizeInBytes,
|
|
||||||
const wchar_t *wcstr,
|
|
||||||
size_t count);
|
|
||||||
|
|
||||||
static void dirent_set_errno (int error);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open directory stream DIRNAME for read and return a pointer to the
|
|
||||||
* internal working area that is used to retrieve individual directory
|
|
||||||
* entries.
|
|
||||||
*/
|
|
||||||
static _WDIR*
|
|
||||||
_wopendir(
|
|
||||||
const wchar_t *dirname)
|
|
||||||
{
|
|
||||||
_WDIR *dirp = NULL;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
/* Must have directory name */
|
|
||||||
if (dirname == NULL || dirname[0] == '\0') {
|
|
||||||
dirent_set_errno (ENOENT);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate new _WDIR structure */
|
|
||||||
dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
|
|
||||||
if (dirp != NULL) {
|
|
||||||
DWORD n;
|
|
||||||
|
|
||||||
/* Reset _WDIR structure */
|
|
||||||
dirp->handle = INVALID_HANDLE_VALUE;
|
|
||||||
dirp->patt = NULL;
|
|
||||||
dirp->cached = 0;
|
|
||||||
|
|
||||||
/* Compute the length of full path plus zero terminator
|
|
||||||
*
|
|
||||||
* Note that on WinRT there's no way to convert relative paths
|
|
||||||
* into absolute paths, so just assume it is an absolute path.
|
|
||||||
*/
|
|
||||||
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
|
||||||
n = wcslen(dirname);
|
|
||||||
# else
|
|
||||||
n = GetFullPathNameW (dirname, 0, NULL, NULL);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/* Allocate room for absolute directory name and search pattern */
|
|
||||||
dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
|
|
||||||
if (dirp->patt) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert relative directory name to an absolute one. This
|
|
||||||
* allows rewinddir() to function correctly even when current
|
|
||||||
* working directory is changed between opendir() and rewinddir().
|
|
||||||
*
|
|
||||||
* Note that on WinRT there's no way to convert relative paths
|
|
||||||
* into absolute paths, so just assume it is an absolute path.
|
|
||||||
*/
|
|
||||||
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
|
||||||
wcsncpy_s(dirp->patt, n+1, dirname, n);
|
|
||||||
# else
|
|
||||||
n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
|
|
||||||
# endif
|
|
||||||
if (n > 0) {
|
|
||||||
wchar_t *p;
|
|
||||||
|
|
||||||
/* Append search pattern \* to the directory name */
|
|
||||||
p = dirp->patt + n;
|
|
||||||
if (dirp->patt < p) {
|
|
||||||
switch (p[-1]) {
|
|
||||||
case '\\':
|
|
||||||
case '/':
|
|
||||||
case ':':
|
|
||||||
/* Directory ends in path separator, e.g. c:\temp\ */
|
|
||||||
/*NOP*/;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Directory name doesn't end in path separator */
|
|
||||||
*p++ = '\\';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*p++ = '*';
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
/* Open directory stream and retrieve the first entry */
|
|
||||||
if (dirent_first (dirp)) {
|
|
||||||
/* Directory stream opened successfully */
|
|
||||||
error = 0;
|
|
||||||
} else {
|
|
||||||
/* Cannot retrieve first entry */
|
|
||||||
error = 1;
|
|
||||||
dirent_set_errno (ENOENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Cannot retrieve full path name */
|
|
||||||
dirent_set_errno (ENOENT);
|
|
||||||
error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Cannot allocate memory for search pattern */
|
|
||||||
error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Cannot allocate _WDIR structure */
|
|
||||||
error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up in case of error */
|
|
||||||
if (error && dirp) {
|
|
||||||
_wclosedir (dirp);
|
|
||||||
dirp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dirp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close directory stream opened by opendir() function. This invalidates the
|
|
||||||
* DIR structure as well as any directory entry read previously by
|
|
||||||
* _wreaddir().
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
_wclosedir(
|
|
||||||
_WDIR *dirp)
|
|
||||||
{
|
|
||||||
int ok;
|
|
||||||
if (dirp) {
|
|
||||||
|
|
||||||
/* Release search handle */
|
|
||||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
|
||||||
FindClose (dirp->handle);
|
|
||||||
dirp->handle = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release search pattern */
|
|
||||||
if (dirp->patt) {
|
|
||||||
free (dirp->patt);
|
|
||||||
dirp->patt = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release directory structure */
|
|
||||||
free (dirp);
|
|
||||||
ok = /*success*/0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Invalid directory stream */
|
|
||||||
dirent_set_errno (EBADF);
|
|
||||||
ok = /*failure*/-1;
|
|
||||||
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get first directory entry (internal) */
|
|
||||||
static WIN32_FIND_DATAW*
|
|
||||||
dirent_first(
|
|
||||||
_WDIR *dirp)
|
|
||||||
{
|
|
||||||
WIN32_FIND_DATAW *datap;
|
|
||||||
|
|
||||||
/* Open directory and retrieve the first entry */
|
|
||||||
dirp->handle = FindFirstFileExW(
|
|
||||||
dirp->patt, FindExInfoStandard, &dirp->data,
|
|
||||||
FindExSearchNameMatch, NULL, 0);
|
|
||||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
|
||||||
|
|
||||||
/* a directory entry is now waiting in memory */
|
|
||||||
datap = &dirp->data;
|
|
||||||
dirp->cached = 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Failed to re-open directory: no directory entry in memory */
|
|
||||||
dirp->cached = 0;
|
|
||||||
datap = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
return datap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get next directory entry (internal).
|
|
||||||
*
|
|
||||||
* Returns
|
|
||||||
*/
|
|
||||||
static WIN32_FIND_DATAW*
|
|
||||||
dirent_next(
|
|
||||||
_WDIR *dirp)
|
|
||||||
{
|
|
||||||
WIN32_FIND_DATAW *p;
|
|
||||||
|
|
||||||
/* Get next directory entry */
|
|
||||||
if (dirp->cached != 0) {
|
|
||||||
|
|
||||||
/* A valid directory entry already in memory */
|
|
||||||
p = &dirp->data;
|
|
||||||
dirp->cached = 0;
|
|
||||||
|
|
||||||
} else if (dirp->handle != INVALID_HANDLE_VALUE) {
|
|
||||||
|
|
||||||
/* Get the next directory entry from stream */
|
|
||||||
if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
|
|
||||||
/* Got a file */
|
|
||||||
p = &dirp->data;
|
|
||||||
} else {
|
|
||||||
/* The very last entry has been processed or an error occurred */
|
|
||||||
FindClose (dirp->handle);
|
|
||||||
dirp->handle = INVALID_HANDLE_VALUE;
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* End of directory stream reached */
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open directory stream using plain old C-string.
|
|
||||||
*/
|
|
||||||
static DIR*
|
|
||||||
opendir(
|
|
||||||
const char *dirname)
|
|
||||||
{
|
|
||||||
struct DIR *dirp;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
/* Must have directory name */
|
|
||||||
if (dirname == NULL || dirname[0] == '\0') {
|
|
||||||
dirent_set_errno (ENOENT);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate memory for DIR structure */
|
|
||||||
dirp = (DIR*) malloc (sizeof (struct DIR));
|
|
||||||
if (dirp) {
|
|
||||||
wchar_t wname[PATH_MAX + 1];
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
/* Convert directory name to wide-character string */
|
|
||||||
error = dirent_mbstowcs_s(
|
|
||||||
&n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
|
|
||||||
if (!error) {
|
|
||||||
|
|
||||||
/* Open directory stream using wide-character name */
|
|
||||||
dirp->wdirp = _wopendir (wname);
|
|
||||||
if (dirp->wdirp) {
|
|
||||||
/* Directory stream opened */
|
|
||||||
error = 0;
|
|
||||||
} else {
|
|
||||||
/* Failed to open directory stream */
|
|
||||||
error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Cannot convert file name to wide-character string. This
|
|
||||||
* occurs if the string contains invalid multi-byte sequences or
|
|
||||||
* the output buffer is too small to contain the resulting
|
|
||||||
* string.
|
|
||||||
*/
|
|
||||||
error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Cannot allocate DIR structure */
|
|
||||||
error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up in case of error */
|
|
||||||
if (error && dirp) {
|
|
||||||
free (dirp);
|
|
||||||
dirp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dirp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read next directory entry.
|
|
||||||
*/
|
|
||||||
static struct dirent*
|
|
||||||
readdir(
|
|
||||||
DIR *dirp)
|
|
||||||
{
|
|
||||||
struct dirent *entry;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read directory entry to buffer. We can safely ignore the return value
|
|
||||||
* as entry will be set to NULL in case of error.
|
|
||||||
*/
|
|
||||||
(void) readdir_r (dirp, &dirp->ent, &entry);
|
|
||||||
|
|
||||||
/* Return pointer to statically allocated directory entry */
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read next directory entry into called-allocated buffer.
|
|
||||||
*
|
|
||||||
* Returns zero on success. If the end of directory stream is reached, then
|
|
||||||
* sets result to NULL and returns zero.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
readdir_r(
|
|
||||||
DIR *dirp,
|
|
||||||
struct dirent *entry,
|
|
||||||
struct dirent **result)
|
|
||||||
{
|
|
||||||
WIN32_FIND_DATAW *datap;
|
|
||||||
|
|
||||||
/* Read next directory entry */
|
|
||||||
datap = dirent_next (dirp->wdirp);
|
|
||||||
if (datap) {
|
|
||||||
size_t n;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
/* Attempt to convert file name to multi-byte string */
|
|
||||||
error = dirent_wcstombs_s(
|
|
||||||
&n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the file name cannot be represented by a multi-byte string,
|
|
||||||
* then attempt to use old 8+3 file name. This allows traditional
|
|
||||||
* Unix-code to access some file names despite of unicode
|
|
||||||
* characters, although file names may seem unfamiliar to the user.
|
|
||||||
*
|
|
||||||
* Be ware that the code below cannot come up with a short file
|
|
||||||
* name unless the file system provides one. At least
|
|
||||||
* VirtualBox shared folders fail to do this.
|
|
||||||
*/
|
|
||||||
if (error && datap->cAlternateFileName[0] != '\0') {
|
|
||||||
error = dirent_wcstombs_s(
|
|
||||||
&n, entry->d_name, PATH_MAX + 1,
|
|
||||||
datap->cAlternateFileName, PATH_MAX + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
DWORD attr;
|
|
||||||
|
|
||||||
/* Length of file name excluding zero terminator */
|
|
||||||
entry->d_namlen = n - 1;
|
|
||||||
|
|
||||||
/* File attributes */
|
|
||||||
attr = datap->dwFileAttributes;
|
|
||||||
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
|
|
||||||
entry->d_type = DT_CHR;
|
|
||||||
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
|
||||||
entry->d_type = DT_DIR;
|
|
||||||
} else {
|
|
||||||
entry->d_type = DT_REG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset dummy fields */
|
|
||||||
entry->d_ino = 0;
|
|
||||||
entry->d_off = 0;
|
|
||||||
entry->d_reclen = sizeof (struct dirent);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cannot convert file name to multi-byte string so construct
|
|
||||||
* an erroneous directory entry and return that. Note that
|
|
||||||
* we cannot return NULL as that would stop the processing
|
|
||||||
* of directory entries completely.
|
|
||||||
*/
|
|
||||||
entry->d_name[0] = '?';
|
|
||||||
entry->d_name[1] = '\0';
|
|
||||||
entry->d_namlen = 1;
|
|
||||||
entry->d_type = DT_UNKNOWN;
|
|
||||||
entry->d_ino = 0;
|
|
||||||
entry->d_off = -1;
|
|
||||||
entry->d_reclen = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return pointer to directory entry */
|
|
||||||
*result = entry;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* No more directory entries */
|
|
||||||
*result = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return /*OK*/0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close directory stream.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
closedir(
|
|
||||||
DIR *dirp)
|
|
||||||
{
|
|
||||||
int ok;
|
|
||||||
if (dirp) {
|
|
||||||
|
|
||||||
/* Close wide-character directory stream */
|
|
||||||
ok = _wclosedir (dirp->wdirp);
|
|
||||||
dirp->wdirp = NULL;
|
|
||||||
|
|
||||||
/* Release multi-byte character version */
|
|
||||||
free (dirp);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Invalid directory stream */
|
|
||||||
dirent_set_errno (EBADF);
|
|
||||||
ok = /*failure*/-1;
|
|
||||||
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert multi-byte string to wide character string */
|
|
||||||
static int
|
|
||||||
dirent_mbstowcs_s(
|
|
||||||
size_t *pReturnValue,
|
|
||||||
wchar_t *wcstr,
|
|
||||||
size_t sizeInWords,
|
|
||||||
const char *mbstr,
|
|
||||||
size_t count)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
|
||||||
|
|
||||||
/* Microsoft Visual Studio 2005 or later */
|
|
||||||
error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Older Visual Studio or non-Microsoft compiler */
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
/* Convert to wide-character string (or count characters) */
|
|
||||||
n = mbstowcs (wcstr, mbstr, sizeInWords);
|
|
||||||
if (!wcstr || n < count) {
|
|
||||||
|
|
||||||
/* Zero-terminate output buffer */
|
|
||||||
if (wcstr && sizeInWords) {
|
|
||||||
if (n >= sizeInWords) {
|
|
||||||
n = sizeInWords - 1;
|
|
||||||
}
|
|
||||||
wcstr[n] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Length of resulting multi-byte string WITH zero terminator */
|
|
||||||
if (pReturnValue) {
|
|
||||||
*pReturnValue = n + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Success */
|
|
||||||
error = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Could not convert string */
|
|
||||||
error = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert wide-character string to multi-byte string */
|
|
||||||
static int
|
|
||||||
dirent_wcstombs_s(
|
|
||||||
size_t *pReturnValue,
|
|
||||||
char *mbstr,
|
|
||||||
size_t sizeInBytes, /* max size of mbstr */
|
|
||||||
const wchar_t *wcstr,
|
|
||||||
size_t count)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
|
||||||
|
|
||||||
/* Microsoft Visual Studio 2005 or later */
|
|
||||||
error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Older Visual Studio or non-Microsoft compiler */
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
/* Convert to multi-byte string (or count the number of bytes needed) */
|
|
||||||
n = wcstombs (mbstr, wcstr, sizeInBytes);
|
|
||||||
if (!mbstr || n < count) {
|
|
||||||
|
|
||||||
/* Zero-terminate output buffer */
|
|
||||||
if (mbstr && sizeInBytes) {
|
|
||||||
if (n >= sizeInBytes) {
|
|
||||||
n = sizeInBytes - 1;
|
|
||||||
}
|
|
||||||
mbstr[n] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Length of resulting multi-bytes string WITH zero-terminator */
|
|
||||||
if (pReturnValue) {
|
|
||||||
*pReturnValue = n + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Success */
|
|
||||||
error = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Cannot convert string */
|
|
||||||
error = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set errno variable */
|
|
||||||
static void
|
|
||||||
dirent_set_errno(
|
|
||||||
int error)
|
|
||||||
{
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
|
||||||
|
|
||||||
/* Microsoft Visual Studio 2005 and later */
|
|
||||||
_set_errno (error);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Non-Microsoft compiler or older Microsoft compiler */
|
|
||||||
errno = error;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /*DIRENT_H*/
|
|
||||||
|
|
||||||
@ -1,106 +0,0 @@
|
|||||||
#include "getopt.h" // make sure you construct the header file as dictated above
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1987, 1993, 1994
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int opterr = 1, /* if error message should be printed */
|
|
||||||
optind = 1, /* index into parent argv vector */
|
|
||||||
optopt, /* character checked for validity */
|
|
||||||
optreset; /* reset getopt */
|
|
||||||
char *optarg; /* argument associated with option */
|
|
||||||
|
|
||||||
#define BADCH (int)'?'
|
|
||||||
#define BADARG (int)':'
|
|
||||||
#define EMSG ""
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getopt --
|
|
||||||
* Parse argc/argv argument vector.
|
|
||||||
*/
|
|
||||||
int getopt(int nargc, char * const nargv[], const char *ostr)
|
|
||||||
{
|
|
||||||
static char *place = EMSG; /* option letter processing */
|
|
||||||
const char *oli; /* option letter list index */
|
|
||||||
|
|
||||||
if (optreset || !*place) { /* update scanning pointer */
|
|
||||||
optreset = 0;
|
|
||||||
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
|
||||||
place = EMSG;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (place[1] && *++place == '-') { /* found "--" */
|
|
||||||
++optind;
|
|
||||||
place = EMSG;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
} /* option letter okay? */
|
|
||||||
if ((optopt = (int)*place++) == (int)':' ||
|
|
||||||
!(oli = strchr(ostr, optopt))) {
|
|
||||||
/*
|
|
||||||
* if the user didn't specify '-' as an option,
|
|
||||||
* assume it means -1.
|
|
||||||
*/
|
|
||||||
if (optopt == (int)'-')
|
|
||||||
return (-1);
|
|
||||||
if (!*place)
|
|
||||||
++optind;
|
|
||||||
if (opterr && *ostr != ':')
|
|
||||||
(void)printf("illegal option -- %c\n", optopt);
|
|
||||||
return (BADCH);
|
|
||||||
}
|
|
||||||
if (*++oli != ':') { /* don't need argument */
|
|
||||||
optarg = NULL;
|
|
||||||
if (!*place)
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
else { /* need an argument */
|
|
||||||
if (*place) /* no white space */
|
|
||||||
optarg = place;
|
|
||||||
else if (nargc <= ++optind) { /* no arg */
|
|
||||||
place = EMSG;
|
|
||||||
if (*ostr == ':')
|
|
||||||
return (BADARG);
|
|
||||||
if (opterr)
|
|
||||||
(void)printf("option requires an argument -- %c\n", optopt);
|
|
||||||
return (BADCH);
|
|
||||||
}
|
|
||||||
else /* white space */
|
|
||||||
optarg = nargv[optind];
|
|
||||||
place = EMSG;
|
|
||||||
++optind;
|
|
||||||
}
|
|
||||||
return (optopt); /* dump back option letter */
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#ifndef GETOPT_H
|
|
||||||
|
|
||||||
#define GETOPT_H
|
|
||||||
|
|
||||||
extern int opterr; /* if error message should be printed */
|
|
||||||
extern int optind; /* index into parent argv vector */
|
|
||||||
extern int optopt; /* character checked for validity */
|
|
||||||
extern int optreset; /* reset getopt */
|
|
||||||
extern char *optarg; /* argument associated with option */
|
|
||||||
|
|
||||||
int getopt(int nargc, char * const nargv[], const char *ostr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -183,7 +183,7 @@ uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, i
|
|||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Timeouts are set to %lu ms", timeout_ms);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Timeouts are set to %lu ms", timeout_ms);
|
||||||
|
|
||||||
// TODO Enhance the reception method
|
// TODO Enhance the reception method
|
||||||
// - According to MSDN, it could be better to implement nfc_abort_command() mechanism using Cancello()
|
// - According to MSDN, it could be better to implement nfc_abort_command() mecanism using Cancello()
|
||||||
volatile bool *abort_flag_p = (volatile bool *)abort_p;
|
volatile bool *abort_flag_p = (volatile bool *)abort_p;
|
||||||
do {
|
do {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ReadFile");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ReadFile");
|
||||||
|
|||||||
@ -39,7 +39,6 @@ EXPORTS
|
|||||||
nfc_device_get_supported_baud_rate_target_mode
|
nfc_device_get_supported_baud_rate_target_mode
|
||||||
nfc_device_set_property_int
|
nfc_device_set_property_int
|
||||||
nfc_device_set_property_bool
|
nfc_device_set_property_bool
|
||||||
nfc_emulate_target
|
|
||||||
iso14443a_crc
|
iso14443a_crc
|
||||||
iso14443a_crc_append
|
iso14443a_crc_append
|
||||||
iso14443b_crc
|
iso14443b_crc
|
||||||
@ -51,7 +50,3 @@ EXPORTS
|
|||||||
str_nfc_modulation_type
|
str_nfc_modulation_type
|
||||||
str_nfc_baud_rate
|
str_nfc_baud_rate
|
||||||
str_nfc_target
|
str_nfc_target
|
||||||
pn53x_transceive
|
|
||||||
pn532_SAMConfiguration
|
|
||||||
pn53x_read_register
|
|
||||||
pn53x_write_register
|
|
||||||
|
|||||||
@ -1,57 +0,0 @@
|
|||||||
LIBRARY nfc
|
|
||||||
VERSION 1.7
|
|
||||||
|
|
||||||
EXPORTS
|
|
||||||
nfc_init
|
|
||||||
nfc_exit
|
|
||||||
nfc_register_driver
|
|
||||||
nfc_open
|
|
||||||
nfc_close
|
|
||||||
nfc_abort_command
|
|
||||||
nfc_list_devices
|
|
||||||
nfc_idle
|
|
||||||
nfc_initiator_init
|
|
||||||
nfc_initiator_init_secure_element
|
|
||||||
nfc_initiator_select_passive_target
|
|
||||||
nfc_initiator_list_passive_targets
|
|
||||||
nfc_initiator_poll_target
|
|
||||||
nfc_initiator_select_dep_target
|
|
||||||
nfc_initiator_poll_dep_target
|
|
||||||
nfc_initiator_deselect_target
|
|
||||||
nfc_initiator_transceive_bytes
|
|
||||||
nfc_initiator_transceive_bits
|
|
||||||
nfc_initiator_transceive_bytes_timed
|
|
||||||
nfc_initiator_transceive_bits_timed
|
|
||||||
nfc_initiator_target_is_present
|
|
||||||
nfc_target_init
|
|
||||||
nfc_target_send_bytes
|
|
||||||
nfc_target_receive_bytes
|
|
||||||
nfc_target_send_bits
|
|
||||||
nfc_target_receive_bits
|
|
||||||
nfc_strerror
|
|
||||||
nfc_strerror_r
|
|
||||||
nfc_perror
|
|
||||||
nfc_device_get_last_error
|
|
||||||
nfc_device_get_name
|
|
||||||
nfc_device_get_connstring
|
|
||||||
nfc_device_get_supported_modulation
|
|
||||||
nfc_device_get_supported_baud_rate
|
|
||||||
nfc_device_get_supported_baud_rate_target_mode
|
|
||||||
nfc_device_set_property_int
|
|
||||||
nfc_device_set_property_bool
|
|
||||||
nfc_emulate_target
|
|
||||||
iso14443a_crc
|
|
||||||
iso14443a_crc_append
|
|
||||||
iso14443b_crc
|
|
||||||
iso14443b_crc_append
|
|
||||||
iso14443a_locate_historical_bytes
|
|
||||||
nfc_free
|
|
||||||
nfc_version
|
|
||||||
nfc_device_get_information_about
|
|
||||||
str_nfc_modulation_type
|
|
||||||
str_nfc_baud_rate
|
|
||||||
str_nfc_target
|
|
||||||
pn53x_transceive
|
|
||||||
pn532_SAMConfiguration
|
|
||||||
pn53x_read_register
|
|
||||||
pn53x_write_register
|
|
||||||
@ -1,9 +1,15 @@
|
|||||||
|
#include "windows.h"
|
||||||
|
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
||||||
PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
FILEFLAGS 0x0L
|
#ifdef _DEBUG
|
||||||
FILEOS 0x00040004L
|
FILEFLAGS VS_FF_DEBUG|VS_FF_PRERELEASE
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT_WINDOWS32
|
||||||
FILETYPE @RC_FILE_TYPE@
|
FILETYPE @RC_FILE_TYPE@
|
||||||
FILESUBTYPE 0x0L
|
FILESUBTYPE 0x0L
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|||||||
@ -48,9 +48,7 @@
|
|||||||
# define ENOTSUP WSAEOPNOTSUPP
|
# define ENOTSUP WSAEOPNOTSUPP
|
||||||
# define ECONNABORTED WSAECONNABORTED
|
# define ECONNABORTED WSAECONNABORTED
|
||||||
# else
|
# else
|
||||||
#ifndef _MSC_VER
|
|
||||||
# define snprintf sprintf_s
|
# define snprintf sprintf_s
|
||||||
#endif
|
|
||||||
# define strdup _strdup
|
# define strdup _strdup
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ SET(EXAMPLES-SOURCES
|
|||||||
nfc-mfsetuid
|
nfc-mfsetuid
|
||||||
nfc-poll
|
nfc-poll
|
||||||
nfc-relay
|
nfc-relay
|
||||||
nfc-st25tb
|
|
||||||
pn53x-diagnose
|
pn53x-diagnose
|
||||||
pn53x-sam
|
pn53x-sam
|
||||||
pn53x-tamashell
|
pn53x-tamashell
|
||||||
@ -24,15 +23,9 @@ FOREACH(source ${EXAMPLES-SOURCES})
|
|||||||
SET(RC_COMMENT "${PACKAGE_NAME} example")
|
SET(RC_COMMENT "${PACKAGE_NAME} example")
|
||||||
SET(RC_INTERNAL_NAME ${source})
|
SET(RC_INTERNAL_NAME ${source})
|
||||||
SET(RC_ORIGINAL_NAME ${source}.exe)
|
SET(RC_ORIGINAL_NAME ${source}.exe)
|
||||||
# RC_FILE_TYPE: VFT_APP
|
SET(RC_FILE_TYPE VFT_APP)
|
||||||
SET(RC_FILE_TYPE 0x00000001L)
|
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
|
||||||
LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
|
LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
|
||||||
|
|
||||||
|
|
||||||
IF(${source} MATCHES "nfc-st25tb")
|
|
||||||
LIST(APPEND TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/getopt.c)
|
|
||||||
ENDIF()
|
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
ADD_EXECUTABLE(${source} ${TARGETS})
|
ADD_EXECUTABLE(${source} ${TARGETS})
|
||||||
|
|||||||
@ -10,7 +10,6 @@ bin_PROGRAMS = \
|
|||||||
nfc-mfsetuid \
|
nfc-mfsetuid \
|
||||||
nfc-poll \
|
nfc-poll \
|
||||||
nfc-relay \
|
nfc-relay \
|
||||||
nfc-st25tb \
|
|
||||||
pn53x-diagnose \
|
pn53x-diagnose \
|
||||||
pn53x-sam
|
pn53x-sam
|
||||||
|
|
||||||
@ -64,9 +63,6 @@ nfc_mfsetuid_SOURCES = nfc-mfsetuid.c
|
|||||||
nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
$(top_builddir)/utils/libnfcutils.la
|
||||||
|
|
||||||
nfc_st25tb_SOURCES = nfc-st25tb.c
|
|
||||||
nfc_st25tb_LDADD = $(top_builddir)/libnfc/libnfc.la
|
|
||||||
|
|
||||||
pn53x_diagnose_SOURCES = pn53x-diagnose.c
|
pn53x_diagnose_SOURCES = pn53x-diagnose.c
|
||||||
pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||||
$(top_builddir)/utils/libnfcutils.la
|
$(top_builddir)/utils/libnfcutils.la
|
||||||
|
|||||||
@ -1,600 +0,0 @@
|
|||||||
/*-
|
|
||||||
* Free/Libre Near Field Communication (NFC) library
|
|
||||||
*
|
|
||||||
* Libnfc historical contributors:
|
|
||||||
* Copyright (C) 2009 Roel Verdult
|
|
||||||
* Copyright (C) 2009-2013 Romuald Conty
|
|
||||||
* Copyright (C) 2010-2012 Romain Tartière
|
|
||||||
* Copyright (C) 2010-2013 Philippe Teuwen
|
|
||||||
* Copyright (C) 2012-2013 Ludovic Rousseau
|
|
||||||
* See AUTHORS file for a more comprehensive list of contributors.
|
|
||||||
* Additional contributors of this file:
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* 1) Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2 )Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file nfc-st25tb.c
|
|
||||||
* @brief Tool to operate on ISO-14443-B ST25TB* and legacy SR* cards
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Benjamin DELPY `gentilkiwi`
|
|
||||||
* https://blog.gentilkiwi.com
|
|
||||||
* benjamin@gentilkiwi.com
|
|
||||||
* Licence : https://creativecommons.org/licenses/by/4.0/
|
|
||||||
* Rely on : libnfc - https://github.com/nfc-tools/libnfc
|
|
||||||
*
|
|
||||||
* $ gcc -Wall -lnfc -o nfc-st25tb nfc-st25tb.c
|
|
||||||
* $ ./nfc-st25tb -h
|
|
||||||
*
|
|
||||||
* Tested with
|
|
||||||
* - ST25TB512-AC - (BE/Brussels/STIB ; AliExpress ones)
|
|
||||||
* - ST25TB512-AT - (FR/Lille/Ilevia ; FR/Reims/Citura ; FR/Dijon/Divia ; FR/Strasbourg/CTS)
|
|
||||||
* - SRT512 - legacy - (FR/Bordeaux/TBM)
|
|
||||||
* - SRI512 - legacy - (anonymous vending machine)
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <nfc/nfc.h>
|
|
||||||
|
|
||||||
#if defined(WIN32) /* mingw compiler */
|
|
||||||
#include <getopt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ST25TB_SR_BLOCK_MAX_SIZE ((uint8_t) 4) // for static arrays
|
|
||||||
typedef void(*get_info_specific) (uint8_t * systemArea);
|
|
||||||
|
|
||||||
typedef struct _st_data {
|
|
||||||
uint8_t chipId;
|
|
||||||
bool bIsLegacy;
|
|
||||||
const char *szName;
|
|
||||||
const char *szDatasheetUrl;
|
|
||||||
uint8_t blockSize;
|
|
||||||
uint8_t nbNormalBlock;
|
|
||||||
uint8_t bnSystem;
|
|
||||||
get_info_specific pfnGetInfo;
|
|
||||||
} st_data;
|
|
||||||
|
|
||||||
bool get_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt);
|
|
||||||
bool set_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt);
|
|
||||||
bool set_block_at_confirmed(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt);
|
|
||||||
const st_data * get_info(const nfc_target *pnt, bool bPrintIt);
|
|
||||||
void display_system_info(nfc_device *pnd, const st_data * stdata);
|
|
||||||
void print_hex(const uint8_t *pbtData, const size_t szBytes);
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
nfc_context *context = NULL;
|
|
||||||
nfc_device *pnd = NULL;
|
|
||||||
nfc_target nt = {0};
|
|
||||||
nfc_modulation nm = {NMT_ISO14443B2SR, NBR_106};
|
|
||||||
const st_data * stcurrent;
|
|
||||||
int opt, res;
|
|
||||||
bool bIsBlock = false, bIsRead = false, bIsWrite = false, bIsBadCli = false;
|
|
||||||
uint8_t i, blockNumber = 0, data[ST25TB_SR_BLOCK_MAX_SIZE] = {0xff, 0xff, 0xff, 0xff}; // just in case...
|
|
||||||
size_t cbData = 0;
|
|
||||||
|
|
||||||
while(!bIsBadCli && ((opt = getopt(argc, argv, ":hib:rw:")) != -1))
|
|
||||||
{
|
|
||||||
switch(opt)
|
|
||||||
{
|
|
||||||
case 'i':
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
if(optarg)
|
|
||||||
{
|
|
||||||
bIsBlock = true;
|
|
||||||
blockNumber = strtoul(optarg, NULL, 0);
|
|
||||||
}
|
|
||||||
else bIsBadCli = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
bIsRead = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
if(optarg)
|
|
||||||
{
|
|
||||||
cbData = strlen(optarg);
|
|
||||||
if((cbData == (2*2)) || ((cbData == (4*2))))
|
|
||||||
{
|
|
||||||
cbData >>= 1;
|
|
||||||
if(cbData == 2) // sr176
|
|
||||||
{
|
|
||||||
res = sscanf(optarg, "%02hhx%02hhx", data, data + 1);
|
|
||||||
}
|
|
||||||
else // all others
|
|
||||||
{
|
|
||||||
res = sscanf(optarg, "%02hhx%02hhx%02hhx%02hhx", data, data + 1, data + 2, data + 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(res == (int) cbData)
|
|
||||||
{
|
|
||||||
bIsWrite = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!bIsWrite)
|
|
||||||
{
|
|
||||||
bIsBadCli = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // includes -h
|
|
||||||
bIsBadCli = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!bIsBadCli)
|
|
||||||
{
|
|
||||||
if(bIsBlock && (bIsRead || bIsWrite))
|
|
||||||
{
|
|
||||||
if(bIsRead && bIsWrite)
|
|
||||||
{
|
|
||||||
printf("|mode : read then write\n");
|
|
||||||
}
|
|
||||||
else if(bIsRead)
|
|
||||||
{
|
|
||||||
printf("|mode : read\n");
|
|
||||||
}
|
|
||||||
else if(bIsWrite)
|
|
||||||
{
|
|
||||||
printf("|mode : write\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("|blk num: 0x%02hhx\n", blockNumber);
|
|
||||||
if(bIsWrite)
|
|
||||||
{
|
|
||||||
printf("|data : ");
|
|
||||||
print_hex(data, cbData);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(!bIsRead && !bIsWrite && !bIsBlock)
|
|
||||||
{
|
|
||||||
printf("|mode : info\n");
|
|
||||||
}
|
|
||||||
else bIsBadCli = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!bIsBadCli)
|
|
||||||
{
|
|
||||||
nfc_init(&context);
|
|
||||||
if(context)
|
|
||||||
{
|
|
||||||
pnd = nfc_open(context, NULL);
|
|
||||||
if(pnd)
|
|
||||||
{
|
|
||||||
res = nfc_initiator_init(pnd);
|
|
||||||
if(res == NFC_SUCCESS)
|
|
||||||
{
|
|
||||||
printf("Reader : %s - via %s\n ...wait for card...\n", nfc_device_get_name(pnd), nfc_device_get_connstring(pnd));
|
|
||||||
|
|
||||||
if (nfc_initiator_select_passive_target(pnd, nm, NULL, 0, &nt) > 0)
|
|
||||||
{
|
|
||||||
stcurrent = get_info(&nt, true);
|
|
||||||
if(stcurrent)
|
|
||||||
{
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
if(bIsBlock && (bIsRead || bIsWrite))
|
|
||||||
{
|
|
||||||
if(bIsRead)
|
|
||||||
{
|
|
||||||
get_block_at(pnd, blockNumber, NULL, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bIsWrite)
|
|
||||||
{
|
|
||||||
set_block_at_confirmed(pnd, blockNumber, data, cbData, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(!bIsRead && !bIsWrite && !bIsBlock)
|
|
||||||
{
|
|
||||||
for(i = 0; i < stcurrent->nbNormalBlock; i++)
|
|
||||||
{
|
|
||||||
get_block_at(pnd, i, NULL, 0, true);
|
|
||||||
}
|
|
||||||
display_system_info(pnd, stcurrent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else printf("ERROR - nfc_initiator_init: %i\n", res);
|
|
||||||
|
|
||||||
nfc_close(pnd);
|
|
||||||
}
|
|
||||||
else printf("ERROR - nfc_open\n");
|
|
||||||
|
|
||||||
nfc_exit(context);
|
|
||||||
}
|
|
||||||
else printf("ERROR - nfc_init\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"Usage:\n"
|
|
||||||
" %s [-i]\n"
|
|
||||||
" %s -b N -r\n"
|
|
||||||
" %s -b N [-r] -w ABCD[EF01]\n %s -h\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -i (default) information mode - will try to dump the tag content and display informations\n"
|
|
||||||
" -b N specify block number to operate on (tag dependent), needed for read (-r) and write (-w) modes\n"
|
|
||||||
" -r read mode - will try to read block (specified with -b N parameter)\n"
|
|
||||||
" -w ABCD[EF01] write mode - will try to write specicied data (2 or 4 bytes depending on tag) to block (specified with -b N parameter)\n"
|
|
||||||
" -h this help\n"
|
|
||||||
"Examples:\n"
|
|
||||||
" %s -i\n"
|
|
||||||
" Display all tag informations\n"
|
|
||||||
" %s -b 0x0e -r\n"
|
|
||||||
" Read block 0x0e (14) of the tag\n"
|
|
||||||
" %s -b 0x0d -w 0123abcd\n"
|
|
||||||
" Write block 0x0d (13) of the tag with hexadecimal value '01 23 ab cd'\n"
|
|
||||||
" %s -b 0x0c -r -w 0123abcd\n"
|
|
||||||
" Read, then write block 0x0c (12) of the tag with hexadecimal value '01 23 ab cd'\n"
|
|
||||||
"Warnings:\n"
|
|
||||||
" Be careful with: system area, counters & otp, bytes order.\n"
|
|
||||||
, argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
|
|
||||||
{
|
|
||||||
bool bRet = false;
|
|
||||||
uint8_t tx[2] = {0x08, block}, rx[ST25TB_SR_BLOCK_MAX_SIZE]; // 4 is the maximum, SR176 (only 2) will fit
|
|
||||||
int res;
|
|
||||||
|
|
||||||
res = nfc_initiator_transceive_bytes(pnd, tx, sizeof(tx), rx, sizeof(rx), 0);
|
|
||||||
if((res == 2) || (res == 4))
|
|
||||||
{
|
|
||||||
if(data)
|
|
||||||
{
|
|
||||||
if(cbData == res)
|
|
||||||
{
|
|
||||||
memcpy(data, rx, res);
|
|
||||||
bRet = true;
|
|
||||||
}
|
|
||||||
else printf("ERROR - We got %i bytes for a %hhu buffer size?\n", res, cbData);
|
|
||||||
}
|
|
||||||
else bRet = true;
|
|
||||||
|
|
||||||
if(bPrintIt)
|
|
||||||
{
|
|
||||||
printf("[0x%02hhx] ", block);
|
|
||||||
print_hex(rx, res);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(res > 0)
|
|
||||||
{
|
|
||||||
printf("ERROR - We got %i bytes?\n", res);
|
|
||||||
}
|
|
||||||
else printf("ERROR - nfc_initiator_transceive_bytes(get): %i\n", res);
|
|
||||||
|
|
||||||
return bRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool set_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
|
|
||||||
{
|
|
||||||
bool bRet = false;
|
|
||||||
uint8_t tx[2 + ST25TB_SR_BLOCK_MAX_SIZE] = {0x09, block}; // 4 is the maximum, SR176 (only 2) will fit
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if(cbData <= ST25TB_SR_BLOCK_MAX_SIZE)
|
|
||||||
{
|
|
||||||
memcpy(tx + 2, data, cbData);
|
|
||||||
|
|
||||||
if(bPrintIt)
|
|
||||||
{
|
|
||||||
printf(">0x%02hhx> ", block);
|
|
||||||
print_hex(data, cbData);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = nfc_initiator_transceive_bytes(pnd, tx, 2 + cbData, NULL, 0, 0);
|
|
||||||
if(res == NFC_ERFTRANS) // ? :')
|
|
||||||
{
|
|
||||||
bRet = true;
|
|
||||||
}
|
|
||||||
else printf("ERROR - nfc_initiator_transceive_bytes(set): %i\n", res);
|
|
||||||
}
|
|
||||||
else printf("ERROR - Wanted to write %hhu bytes, but maximum is %hhu\n", cbData, ST25TB_SR_BLOCK_MAX_SIZE);
|
|
||||||
|
|
||||||
return bRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool set_block_at_confirmed(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
|
|
||||||
{
|
|
||||||
bool bRet = false;
|
|
||||||
uint8_t buffer[ST25TB_SR_BLOCK_MAX_SIZE]; // maximum size will be checked in set_block_at
|
|
||||||
|
|
||||||
if(set_block_at(pnd, block, data, cbData, bPrintIt))
|
|
||||||
{
|
|
||||||
if(get_block_at(pnd, block, buffer, cbData, bPrintIt))
|
|
||||||
{
|
|
||||||
if(memcmp(data, buffer, cbData) == 0)
|
|
||||||
{
|
|
||||||
bRet = true;
|
|
||||||
}
|
|
||||||
else if(bPrintIt)
|
|
||||||
{
|
|
||||||
printf("WARNING - not same value readed after write\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_info_st25tb512(uint8_t * systemArea)
|
|
||||||
{
|
|
||||||
uint8_t b, i;
|
|
||||||
|
|
||||||
b = ((*(uint32_t *) systemArea) >> 15) & 1;
|
|
||||||
|
|
||||||
printf(" | ST reserved : ");
|
|
||||||
for(i = 0; i < 15; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ? "not " : "");
|
|
||||||
for(i = 16; i < 32; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
for(i = 16; i < 32; i++)
|
|
||||||
{
|
|
||||||
if(!(((*(uint32_t *) systemArea) >> i) & 1))
|
|
||||||
{
|
|
||||||
printf(" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_info_st25tb2k_4k(uint8_t * systemArea)
|
|
||||||
{
|
|
||||||
uint8_t b, i;
|
|
||||||
|
|
||||||
b = ((*(uint32_t *) systemArea) >> 15) & 1;
|
|
||||||
|
|
||||||
printf(" | ST reserved : ");
|
|
||||||
for(i = 0; i < 15; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_RegU: ", b, b ? "not " : "");
|
|
||||||
for(i = 16; i < 24; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n | OTP_Lock_Reg : ");
|
|
||||||
for(i = 24; i < 32; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
if(!(((*(uint32_t *) systemArea) >> 24) & 1))
|
|
||||||
{
|
|
||||||
printf(" blocks 0x07 and 0x08 are write protected\n");
|
|
||||||
}
|
|
||||||
for(i = 25; i < 32; i++)
|
|
||||||
{
|
|
||||||
if(!(((*(uint32_t *) systemArea) >> i) & 1))
|
|
||||||
{
|
|
||||||
printf(" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_info_sr176_legacy(uint8_t * systemArea)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
printf(" | Fixed Chip_ID: 0x%1x\n | ST reserved : ", systemArea[0] & 0x0f);
|
|
||||||
for(i = 4; i < 8; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n | OTP_Lock_Reg : ");
|
|
||||||
for(i = 8; i < 16; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
for(i = 8; i < 16; i++)
|
|
||||||
{
|
|
||||||
if(((*(uint16_t *) systemArea) >> i) & 1)
|
|
||||||
{
|
|
||||||
printf(" blocks 0x%02hhx and 0x%02hhx are write protected\n", (uint8_t) ((i - 8) * 2), (uint8_t) (((i - 8) * 2) + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_info_sri_srt_512_legacy(uint8_t * systemArea)
|
|
||||||
{
|
|
||||||
uint8_t b, i;
|
|
||||||
|
|
||||||
b = ((*(uint32_t *) systemArea) >> 15) & 1;
|
|
||||||
|
|
||||||
printf(" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
|
|
||||||
for(i = 8; i < 15; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ? "not " : "");
|
|
||||||
for(i = 16; i < 32; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
for(i = 16; i < 32; i++)
|
|
||||||
{
|
|
||||||
if(!(((*(uint32_t *) systemArea) >> i) & 1))
|
|
||||||
{
|
|
||||||
printf(" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_info_sri2k_4k_srix4k_srix512_legacy(uint8_t * systemArea)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
printf(" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
|
|
||||||
for(i = 8; i < 24; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n | OTP_Lock_Reg : ");
|
|
||||||
for(i = 24; i < 32; i++)
|
|
||||||
{
|
|
||||||
printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
if(!(((*(uint32_t *) systemArea) >> 24) & 1))
|
|
||||||
{
|
|
||||||
printf(" blocks 0x07 and 0x08 are write protected\n");
|
|
||||||
}
|
|
||||||
for(i = 25; i < 32; i++)
|
|
||||||
{
|
|
||||||
if(!(((*(uint32_t *) systemArea) >> i) & 1))
|
|
||||||
{
|
|
||||||
printf(" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const st_data STRefs[] = {
|
|
||||||
{0x1b, false, "ST25TB512-AC", "https://www.st.com/resource/en/datasheet/st25tb512-ac.pdf", 4, 16, 255, get_info_st25tb512},
|
|
||||||
{0x33, false, "ST25TB512-AT", "https://www.st.com/resource/en/datasheet/st25tb512-at.pdf", 4, 16, 255, get_info_st25tb512},
|
|
||||||
{0x3f, false, "ST25TB02K", "https://www.st.com/resource/en/datasheet/st25tb02k.pdf", 4, 64, 255, get_info_st25tb2k_4k},
|
|
||||||
{0x1f, false, "ST25TB04K", "https://www.st.com/resource/en/datasheet/st25tb04k.pdf", 4, 128, 255, get_info_st25tb2k_4k},
|
|
||||||
};
|
|
||||||
const st_data STRefs_legacy[] = {
|
|
||||||
{ 0, true, "SRI4K(s)", NULL, 4, 128, 255, NULL},
|
|
||||||
{ 2, true, "SR176", "https://www.st.com/resource/en/datasheet/sr176.pdf", 2, 15, 15, get_info_sr176_legacy},
|
|
||||||
{ 3, true, "SRIX4K", NULL, 4, 128, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
|
|
||||||
{ 4, true, "SRIX512", "https://www.st.com/resource/en/datasheet/srix512.pdf", 4, 16, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
|
|
||||||
{ 6, true, "SRI512", "https://www.st.com/resource/en/datasheet/sri512.pdf", 4, 16, 255, get_info_sri_srt_512_legacy},
|
|
||||||
{ 7, true, "SRI4K", "https://www.st.com/resource/en/datasheet/sri4k.pdf", 4, 128, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
|
|
||||||
{12, true, "SRT512", "https://www.st.com/resource/en/datasheet/srt512.pdf", 4, 16, 255, get_info_sri_srt_512_legacy},
|
|
||||||
{15, true, "SRI2K", "https://www.st.com/resource/en/datasheet/sri2k.pdf", 4, 64, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
|
|
||||||
};
|
|
||||||
|
|
||||||
const st_data * get_info(const nfc_target *pnt, bool bPrintIt)
|
|
||||||
{
|
|
||||||
const st_data *currentData = NULL;
|
|
||||||
const uint8_t *p;
|
|
||||||
uint8_t chipId, i;
|
|
||||||
|
|
||||||
if(pnt->nm.nmt == NMT_ISO14443B2SR)
|
|
||||||
{
|
|
||||||
printf("Target : %s (%s)\nUID : ", str_nfc_modulation_type(pnt->nm.nmt), str_nfc_baud_rate(pnt->nm.nbr));
|
|
||||||
print_hex(pnt->nti.nsi.abtUID, sizeof(pnt->nti.nsi.abtUID));
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
p = pnt->nti.nsi.abtUID;
|
|
||||||
if(p[7] == 0xd0) // ST25TB* / SR*
|
|
||||||
{
|
|
||||||
chipId = p[5];
|
|
||||||
printf("Manuf : 0x%02hhx - %s\n", p[6], (p[6] == 0x02) ? "STMicroelectronics" : "other");
|
|
||||||
|
|
||||||
for(i = 0; i < (sizeof(STRefs) / sizeof(STRefs[0])); i++)
|
|
||||||
{
|
|
||||||
if(chipId == STRefs[i].chipId)
|
|
||||||
{
|
|
||||||
currentData = &STRefs[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!currentData)
|
|
||||||
{
|
|
||||||
chipId >>= 2;
|
|
||||||
for(i = 0; i < (sizeof(STRefs_legacy) / sizeof(STRefs_legacy[0])); i++)
|
|
||||||
{
|
|
||||||
if(chipId == STRefs_legacy[i].chipId)
|
|
||||||
{
|
|
||||||
currentData = &STRefs_legacy[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bPrintIt && currentData)
|
|
||||||
{
|
|
||||||
printf("ChipId : 0x%02hhx - %s%s\nSerial : 0x", currentData->chipId, currentData->szName, currentData->bIsLegacy ? " (legacy)" : "");
|
|
||||||
if(currentData->bIsLegacy)
|
|
||||||
{
|
|
||||||
printf("%1hhx", (uint8_t) (p[5] & 0x03));
|
|
||||||
}
|
|
||||||
printf("%02hhx%02hhx%02hhx%02hhx%02hhx\n|blk sz : %hhu bits\n|nb blks: %hhu\n|sys idx: %hhu\n", p[4], p[3], p[2], p[1], p[0], (uint8_t) (currentData->blockSize * 8), currentData->nbNormalBlock, currentData->bnSystem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else printf("WARNI - Last byte of UID isn\'t 0xd0, but 0x%02hhx (not ST25TB / SR series?)\n", p[7]);
|
|
||||||
}
|
|
||||||
else printf("ERROR - not a NMT_ISO14443B2SR ?\n");
|
|
||||||
|
|
||||||
return currentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void display_system_info(nfc_device *pnd, const st_data * stdata)
|
|
||||||
{
|
|
||||||
uint8_t systemArea[ST25TB_SR_BLOCK_MAX_SIZE];
|
|
||||||
|
|
||||||
if(get_block_at(pnd, stdata->bnSystem, systemArea, stdata->blockSize, true))
|
|
||||||
{
|
|
||||||
if(stdata->pfnGetInfo)
|
|
||||||
{
|
|
||||||
stdata->pfnGetInfo(systemArea);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_hex(const uint8_t *pbtData, const size_t szBytes)
|
|
||||||
{
|
|
||||||
size_t szPos;
|
|
||||||
for (szPos = 0; szPos < szBytes; szPos++)
|
|
||||||
{
|
|
||||||
printf("%02hhx ", pbtData[szPos]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -291,8 +291,8 @@ typedef union {
|
|||||||
nfc_iso14443b2sr_info nsi;
|
nfc_iso14443b2sr_info nsi;
|
||||||
nfc_iso14443b2ct_info nci;
|
nfc_iso14443b2ct_info nci;
|
||||||
nfc_jewel_info nji;
|
nfc_jewel_info nji;
|
||||||
nfc_dep_info ndi;
|
|
||||||
nfc_barcode_info nti; // "t" for Thinfilm, "b" already used
|
nfc_barcode_info nti; // "t" for Thinfilm, "b" already used
|
||||||
|
nfc_dep_info ndi;
|
||||||
nfc_iso14443biclass_info nhi; // hid iclass / picopass - nii already used
|
nfc_iso14443biclass_info nhi; // hid iclass / picopass - nii already used
|
||||||
} nfc_target_info;
|
} nfc_target_info;
|
||||||
|
|
||||||
@ -315,13 +315,13 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
NMT_ISO14443A = 1,
|
NMT_ISO14443A = 1,
|
||||||
NMT_JEWEL,
|
NMT_JEWEL,
|
||||||
|
NMT_BARCODE, // Thinfilm NFC Barcode
|
||||||
NMT_ISO14443B,
|
NMT_ISO14443B,
|
||||||
NMT_ISO14443BI, // pre-ISO14443B aka ISO/IEC 14443 B' or Type B'
|
NMT_ISO14443BI, // pre-ISO14443B aka ISO/IEC 14443 B' or Type B'
|
||||||
NMT_ISO14443B2SR, // ISO14443-2B ST SRx
|
NMT_ISO14443B2SR, // ISO14443-2B ST SRx
|
||||||
NMT_ISO14443B2CT, // ISO14443-2B ASK CTx
|
NMT_ISO14443B2CT, // ISO14443-2B ASK CTx
|
||||||
NMT_FELICA,
|
NMT_FELICA,
|
||||||
NMT_DEP,
|
NMT_DEP,
|
||||||
NMT_BARCODE, // Thinfilm NFC Barcode
|
|
||||||
NMT_ISO14443BICLASS, // HID iClass 14443B mode
|
NMT_ISO14443BICLASS, // HID iClass 14443B mode
|
||||||
NMT_END_ENUM = NMT_ISO14443BICLASS, // dummy for sizing - always should alias last
|
NMT_END_ENUM = NMT_ISO14443BICLASS, // dummy for sizing - always should alias last
|
||||||
} nfc_modulation_type;
|
} nfc_modulation_type;
|
||||||
|
|||||||
@ -5,9 +5,6 @@ IF(WIN32)
|
|||||||
|
|
||||||
# Add in the rc for version information in the dll
|
# Add in the rc for version information in the dll
|
||||||
LIST(APPEND WINDOWS_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/../windows/libnfc.rc)
|
LIST(APPEND WINDOWS_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/../windows/libnfc.rc)
|
||||||
IF (NOT MINGW)
|
|
||||||
LIST(APPEND WINDOWS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc_msvc.def)
|
|
||||||
ENDIF()
|
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
# Library's chips
|
# Library's chips
|
||||||
@ -29,23 +26,23 @@ IF(UART_REQUIRED)
|
|||||||
ENDIF(UART_REQUIRED)
|
ENDIF(UART_REQUIRED)
|
||||||
|
|
||||||
IF(I2C_REQUIRED)
|
IF(I2C_REQUIRED)
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
IF(WIN32)
|
||||||
LIST(APPEND BUSES_SOURCES buses/i2c)
|
# Windows is not supported at the moment
|
||||||
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
# Only Linux is supported at the moment
|
|
||||||
#LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/i2c)
|
#LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/i2c)
|
||||||
MESSAGE( FATAL_ERROR "I2C is only (yet) supported in Linux!" )
|
MESSAGE( FATAL_ERROR "I2C not (yet) supported under Windows!" )
|
||||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
ELSE(WIN32)
|
||||||
|
LIST(APPEND BUSES_SOURCES buses/i2c)
|
||||||
|
ENDIF(WIN32)
|
||||||
ENDIF(I2C_REQUIRED)
|
ENDIF(I2C_REQUIRED)
|
||||||
|
|
||||||
IF(SPI_REQUIRED)
|
IF(SPI_REQUIRED)
|
||||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
IF(WIN32)
|
||||||
LIST(APPEND BUSES_SOURCES buses/spi)
|
# Windows is not supported at the moment
|
||||||
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|
||||||
# Only Linux is supported at the moment
|
|
||||||
#LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/spi)
|
#LIST(APPEND BUSES_SOURCES ../contrib/win32/libnfc/buses/spi)
|
||||||
MESSAGE( FATAL_ERROR "SPI is only (yet) supported in Linux!" )
|
MESSAGE( FATAL_ERROR "SPI not (yet) supported under Windows!" )
|
||||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
ELSE(WIN32)
|
||||||
|
LIST(APPEND BUSES_SOURCES buses/spi)
|
||||||
|
ENDIF(WIN32)
|
||||||
ENDIF(SPI_REQUIRED)
|
ENDIF(SPI_REQUIRED)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses)
|
||||||
@ -66,9 +63,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
|||||||
|
|
||||||
IF(LIBNFC_LOG)
|
IF(LIBNFC_LOG)
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
IF(MINGW)
|
SET(CMAKE_C_FLAGS "-fgnu89-inline ${CMAKE_C_FLAGS}")
|
||||||
SET(CMAKE_C_FLAGS "-fgnu89-inline ${CMAKE_C_FLAGS}")
|
|
||||||
ENDIF(MINGW)
|
|
||||||
LIST(APPEND LIBRARY_SOURCES log ../contrib/win32/libnfc/log-internal)
|
LIST(APPEND LIBRARY_SOURCES log ../contrib/win32/libnfc/log-internal)
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
LIST(APPEND LIBRARY_SOURCES log log-internal)
|
LIST(APPEND LIBRARY_SOURCES log log-internal)
|
||||||
@ -88,21 +83,18 @@ IF(LIBRT_FOUND)
|
|||||||
TARGET_LINK_LIBRARIES(nfc ${LIBRT_LIBRARIES})
|
TARGET_LINK_LIBRARIES(nfc ${LIBRT_LIBRARIES})
|
||||||
ENDIF(LIBRT_FOUND)
|
ENDIF(LIBRT_FOUND)
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 6 VERSION 6.0.0)
|
SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 5 VERSION 5.0.1)
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
# Libraries that are windows specific
|
# Libraries that are windows specific
|
||||||
TARGET_LINK_LIBRARIES(nfc wsock32)
|
TARGET_LINK_LIBRARIES(nfc wsock32)
|
||||||
IF(MINGW)
|
|
||||||
ADD_CUSTOM_COMMAND(
|
ADD_CUSTOM_COMMAND(
|
||||||
OUTPUT libnfc.lib
|
OUTPUT libnfc.lib
|
||||||
COMMAND ${DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll
|
COMMAND ${DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll
|
||||||
DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def
|
DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def
|
||||||
)
|
)
|
||||||
ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib)
|
ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib)
|
||||||
ELSE()
|
|
||||||
ADD_LIBRARY(win32lib ALIAS nfc)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# On Windows the shared (runtime) library should be either in the same
|
# On Windows the shared (runtime) library should be either in the same
|
||||||
# directory as the excutables or in the path, we add it to same directory
|
# directory as the excutables or in the path, we add it to same directory
|
||||||
|
|||||||
@ -22,7 +22,7 @@ libnfc_la_SOURCES = \
|
|||||||
nfc-internal.h \
|
nfc-internal.h \
|
||||||
target-subr.h
|
target-subr.h
|
||||||
|
|
||||||
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'
|
libnfc_la_LDFLAGS = -no-undefined -version-info 5:1:0 -export-symbols-regex '^nfc_|^iso14443a_|^iso14443b_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register'
|
||||||
libnfc_la_CFLAGS = @DRIVERS_CFLAGS@
|
libnfc_la_CFLAGS = @DRIVERS_CFLAGS@
|
||||||
libnfc_la_LIBADD = \
|
libnfc_la_LIBADD = \
|
||||||
$(top_builddir)/libnfc/chips/libnfcchips.la \
|
$(top_builddir)/libnfc/chips/libnfcchips.la \
|
||||||
|
|||||||
@ -33,9 +33,7 @@
|
|||||||
#ifndef __NFC_BUS_UART_H__
|
#ifndef __NFC_BUS_UART_H__
|
||||||
# define __NFC_BUS_UART_H__
|
# define __NFC_BUS_UART_H__
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
|
|||||||
@ -1155,14 +1155,6 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd,
|
|||||||
uint8_t abtRx[1];
|
uint8_t abtRx[1];
|
||||||
uint8_t *pbtInitData = (uint8_t *) "\x0b";
|
uint8_t *pbtInitData = (uint8_t *) "\x0b";
|
||||||
size_t szInitData = 1;
|
size_t szInitData = 1;
|
||||||
|
|
||||||
if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_TxAuto, 0xef, 0x07)) < 0) // Initial RFOn, Tx2 RFAutoEn, Tx1 RFAutoEn
|
|
||||||
return res;
|
|
||||||
if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_CWGsP, 0x3f, 0x3f)) < 0) // Conductance of the P-Driver
|
|
||||||
return res;
|
|
||||||
if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_ModGsP, 0x3f, 0x12)) < 0) // Driver P-output conductance for the time of modulation
|
|
||||||
return res;
|
|
||||||
|
|
||||||
// Getting random Chip_ID
|
// Getting random Chip_ID
|
||||||
if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) {
|
if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) {
|
||||||
if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
|
if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
|
||||||
@ -1216,7 +1208,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd,
|
|||||||
// send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response
|
// send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response
|
||||||
uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL
|
uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL
|
||||||
uint8_t abtAnticol[11];
|
uint8_t abtAnticol[11];
|
||||||
if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout) < 0) {
|
if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout)) < 0) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all");
|
||||||
//if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
|
//if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout
|
||||||
// continue;
|
// continue;
|
||||||
@ -2072,7 +2064,7 @@ static int pn53x_ISO14443A_Barcode_is_present(struct nfc_device *pnd)
|
|||||||
}
|
}
|
||||||
uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
||||||
uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
||||||
if (nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar) < 1) {
|
if ((ret = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 1) {
|
||||||
failures++;
|
failures++;
|
||||||
} else {
|
} else {
|
||||||
nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);
|
nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true);
|
||||||
|
|||||||
@ -195,8 +195,6 @@ conf_parse_file(const char *filename,
|
|||||||
free(key);
|
free(key);
|
||||||
free(value);
|
free(value);
|
||||||
} else {
|
} else {
|
||||||
free(key);
|
|
||||||
free(value);
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,9 +60,7 @@ Thanks to d18c7db and Okko for example code
|
|||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "nfc-internal.h"
|
#include "nfc-internal.h"
|
||||||
@ -598,7 +596,7 @@ read:
|
|||||||
if (timeout == USB_INFINITE_TIMEOUT) {
|
if (timeout == USB_INFINITE_TIMEOUT) {
|
||||||
usb_timeout = USB_TIMEOUT_PER_PASS;
|
usb_timeout = USB_TIMEOUT_PER_PASS;
|
||||||
} else {
|
} else {
|
||||||
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
|
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
|
||||||
remaining_time -= USB_TIMEOUT_PER_PASS;
|
remaining_time -= USB_TIMEOUT_PER_PASS;
|
||||||
if (remaining_time <= 0) {
|
if (remaining_time <= 0) {
|
||||||
pnd->last_error = NFC_ETIMEOUT;
|
pnd->last_error = NFC_ETIMEOUT;
|
||||||
@ -612,7 +610,6 @@ read:
|
|||||||
|
|
||||||
uint8_t attempted_response = RDR_to_PC_DataBlock;
|
uint8_t attempted_response = RDR_to_PC_DataBlock;
|
||||||
size_t len;
|
size_t len;
|
||||||
int error, status;
|
|
||||||
|
|
||||||
if (res == NFC_ETIMEOUT) {
|
if (res == NFC_ETIMEOUT) {
|
||||||
if (DRIVER_DATA(pnd)->abort_flag) {
|
if (DRIVER_DATA(pnd)->abort_flag) {
|
||||||
@ -624,7 +621,7 @@ read:
|
|||||||
goto read;
|
goto read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (res < 10) {
|
if (res < 12) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Invalid RDR_to_PC_DataBlock frame");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Invalid RDR_to_PC_DataBlock frame");
|
||||||
// try to interrupt current device state
|
// try to interrupt current device state
|
||||||
acr122_usb_ack(pnd);
|
acr122_usb_ack(pnd);
|
||||||
@ -639,16 +636,6 @@ read:
|
|||||||
offset++;
|
offset++;
|
||||||
|
|
||||||
len = abtRxBuf[offset++];
|
len = abtRxBuf[offset++];
|
||||||
status = abtRxBuf[7];
|
|
||||||
error = abtRxBuf[8];
|
|
||||||
if (len == 0 && error == 0xFE) { // ICC_MUTE; XXX check for more errors
|
|
||||||
// Do not check status; my ACR122U seemingly has status=0 in this case,
|
|
||||||
// even though the spec says it should have had bmCommandStatus=1
|
|
||||||
// and bmICCStatus=1.
|
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Command timed out");
|
|
||||||
pnd->last_error = NFC_ETIMEOUT;
|
|
||||||
return pnd->last_error;
|
|
||||||
}
|
|
||||||
if (!((len > 1) && (abtRxBuf[10] == 0xd5))) { // In case we didn't get an immediate answer:
|
if (!((len > 1) && (abtRxBuf[10] == 0xd5))) { // In case we didn't get an immediate answer:
|
||||||
if (len != 2) {
|
if (len != 2) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Wrong reply");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Wrong reply");
|
||||||
@ -677,7 +664,7 @@ read:
|
|||||||
goto read; // FIXME May cause some trouble on Touchatag, right ?
|
goto read; // FIXME May cause some trouble on Touchatag, right ?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (res < 10) {
|
if (res < 12) {
|
||||||
// try to interrupt current device state
|
// try to interrupt current device state
|
||||||
acr122_usb_ack(pnd);
|
acr122_usb_ack(pnd);
|
||||||
pnd->last_error = NFC_EIO;
|
pnd->last_error = NFC_EIO;
|
||||||
|
|||||||
@ -527,7 +527,7 @@ acr122s_close(nfc_device *pnd)
|
|||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// Release file descriptors used for abort mechanism
|
// Release file descriptors used for abort mecanism
|
||||||
close(DRIVER_DATA(pnd)->abort_fds[0]);
|
close(DRIVER_DATA(pnd)->abort_fds[0]);
|
||||||
close(DRIVER_DATA(pnd)->abort_fds[1]);
|
close(DRIVER_DATA(pnd)->abort_fds[1]);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -158,7 +158,7 @@ arygon_scan(const nfc_context *context, nfc_connstring connstrings[], const size
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// pipe-based abort mechanism
|
// pipe-based abort mecanism
|
||||||
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
pn53x_data_free(pnd);
|
pn53x_data_free(pnd);
|
||||||
@ -211,7 +211,7 @@ arygon_close_step2(nfc_device *pnd)
|
|||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// Release file descriptors used for abort mechanism
|
// Release file descriptors used for abort mecanism
|
||||||
close(DRIVER_DATA(pnd)->iAbortFds[0]);
|
close(DRIVER_DATA(pnd)->iAbortFds[0]);
|
||||||
close(DRIVER_DATA(pnd)->iAbortFds[1]);
|
close(DRIVER_DATA(pnd)->iAbortFds[1]);
|
||||||
#endif
|
#endif
|
||||||
@ -304,7 +304,7 @@ arygon_open(const nfc_context *context, const nfc_connstring connstring)
|
|||||||
pnd->driver = &arygon_driver;
|
pnd->driver = &arygon_driver;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// pipe-based abort mechanism
|
// pipe-based abort mecanism
|
||||||
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
pn53x_data_free(pnd);
|
pn53x_data_free(pnd);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* Copyright (C) 2019 Frank Morgner
|
* Copyright (C) 2019 Frank Morgner
|
||||||
* See AUTHORS file for a more comprehensive list of contributors.
|
* See AUTHORS file for a more comprehensive list of contributors.
|
||||||
* Additional contributors of this file:
|
* Additional contributors of this file:
|
||||||
* Copyright (C) 2020 Feitian Technologies
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
@ -34,7 +34,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
@ -73,11 +72,6 @@
|
|||||||
#include <winscard.h>
|
#include <winscard.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#define usleep(x) Sleep((x + 999) / 1000)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PCSC_DRIVER_NAME "pcsc"
|
#define PCSC_DRIVER_NAME "pcsc"
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
@ -109,7 +103,7 @@ static int _iSCardContextRefCount = 0;
|
|||||||
const nfc_baud_rate pcsc_supported_brs[] = {NBR_106, NBR_424, 0};
|
const nfc_baud_rate pcsc_supported_brs[] = {NBR_106, NBR_424, 0};
|
||||||
const nfc_modulation_type pcsc_supported_mts[] = {NMT_ISO14443A, NMT_ISO14443B, 0};
|
const nfc_modulation_type pcsc_supported_mts[] = {NMT_ISO14443A, NMT_ISO14443B, 0};
|
||||||
|
|
||||||
static SCARDCONTEXT *
|
SCARDCONTEXT *
|
||||||
pcsc_get_scardcontext(void)
|
pcsc_get_scardcontext(void)
|
||||||
{
|
{
|
||||||
if (_iSCardContextRefCount == 0) {
|
if (_iSCardContextRefCount == 0) {
|
||||||
@ -121,7 +115,7 @@ pcsc_get_scardcontext(void)
|
|||||||
return &_SCardContext;
|
return &_SCardContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
pcsc_free_scardcontext(void)
|
pcsc_free_scardcontext(void)
|
||||||
{
|
{
|
||||||
if (_iSCardContextRefCount) {
|
if (_iSCardContextRefCount) {
|
||||||
@ -138,20 +132,14 @@ pcsc_free_scardcontext(void)
|
|||||||
|
|
||||||
bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd);
|
bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd);
|
||||||
|
|
||||||
static int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len, uint8_t *rx, size_t *rx_len)
|
int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len, uint8_t *rx, size_t *rx_len)
|
||||||
{
|
{
|
||||||
struct pcsc_data *data = pnd->driver_data;
|
struct pcsc_data *data = pnd->driver_data;
|
||||||
DWORD dw_rx_len = *rx_len;
|
DWORD dw_rx_len = *rx_len;
|
||||||
//in libfreefare, tx_len = 1, and it leads to 0x80100008 error, with PC/SC reader, the input tx_len at least two bytes for the SW value
|
//in libfreefare, tx_len = 1, and it leads to 0x80100008 error, with PC/SC reader, the input tx_len at least two bytes for the SW value
|
||||||
//so if found the reader is Feitian reader, we set to 2
|
//so if found the reader is Feitian reader, we set to 2
|
||||||
if (is_pcsc_reader_vendor_feitian(pnd))
|
if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) {
|
||||||
{
|
dw_rx_len = 2;
|
||||||
if (dw_rx_len == 1)
|
|
||||||
{
|
|
||||||
dw_rx_len = 2;
|
|
||||||
} else {
|
|
||||||
dw_rx_len += 2;//in libfreefare, some data length send not include sw1 and sw2, so add it.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len);
|
LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len);
|
||||||
@ -169,7 +157,7 @@ static int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t *atr, size_t *atr_len)
|
int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t *atr, size_t *atr_len)
|
||||||
{
|
{
|
||||||
struct pcsc_data *data = pnd->driver_data;
|
struct pcsc_data *data = pnd->driver_data;
|
||||||
DWORD dw_atr_len = *atr_len, reader_len, state, protocol;
|
DWORD dw_atr_len = *atr_len, reader_len, state, protocol;
|
||||||
@ -187,7 +175,7 @@ static int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protocol, DWORD disposition)
|
int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protocol, DWORD disposition)
|
||||||
{
|
{
|
||||||
struct pcsc_data *data = pnd->driver_data;
|
struct pcsc_data *data = pnd->driver_data;
|
||||||
|
|
||||||
@ -203,7 +191,7 @@ static int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protoc
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t pcsc_get_icc_type(const struct nfc_device *pnd)
|
uint8_t pcsc_get_icc_type(const struct nfc_device *pnd)
|
||||||
{
|
{
|
||||||
struct pcsc_data *data = pnd->driver_data;
|
struct pcsc_data *data = pnd->driver_data;
|
||||||
uint8_t it = 0;
|
uint8_t it = 0;
|
||||||
@ -212,7 +200,7 @@ static uint8_t pcsc_get_icc_type(const struct nfc_device *pnd)
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_pcsc_reader_vendor(const struct nfc_device *pnd, const char *target_vendor_name)
|
bool is_pcsc_reader_vendor(const struct nfc_device *pnd, const char *target_vendor_name)
|
||||||
{
|
{
|
||||||
bool isTarget = false;
|
bool isTarget = false;
|
||||||
if (pnd == NULL || strlen(pnd->name) == 0) {
|
if (pnd == NULL || strlen(pnd->name) == 0) {
|
||||||
@ -228,7 +216,7 @@ bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get atqa by send apdu
|
//get atqa by send apdu
|
||||||
static int pcsc_get_atqa(struct nfc_device *pnd, uint8_t *atqa, size_t atqa_len)
|
int pcsc_get_atqa(struct nfc_device *pnd, uint8_t *atqa, size_t atqa_len)
|
||||||
{
|
{
|
||||||
const uint8_t get_data[] = {0xFF, 0xCA, 0x03, 0x00, 0x00};
|
const uint8_t get_data[] = {0xFF, 0xCA, 0x03, 0x00, 0x00};
|
||||||
uint8_t resp[256 + 2];
|
uint8_t resp[256 + 2];
|
||||||
@ -254,7 +242,7 @@ static int pcsc_get_atqa(struct nfc_device *pnd, uint8_t *atqa, size_t atqa_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get ats by send apdu
|
//get ats by send apdu
|
||||||
static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
|
int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
|
||||||
{
|
{
|
||||||
const uint8_t get_data[] = {0xFF, 0xCA, 0x01, 0x00, 0x00};
|
const uint8_t get_data[] = {0xFF, 0xCA, 0x01, 0x00, 0x00};
|
||||||
uint8_t resp[256 + 2];
|
uint8_t resp[256 + 2];
|
||||||
@ -264,7 +252,7 @@ static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
|
|||||||
if (pnd->last_error != NFC_SUCCESS)
|
if (pnd->last_error != NFC_SUCCESS)
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
|
|
||||||
if (resp_len <= 2) {
|
if (resp_len < 2) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS");
|
||||||
pnd->last_error = NFC_EDEVNOTSUPP;
|
pnd->last_error = NFC_EDEVNOTSUPP;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
@ -275,12 +263,13 @@ static int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len)
|
|||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(ats, resp + 1, resp_len - 2 - 1);//data expect TL and SW1SW2
|
//memcpy(ats, resp + 1, resp_len - 2 - 1);
|
||||||
|
memcpy(ats, resp + 1, resp[0] - 1);
|
||||||
return resp_len - 2 - 1;
|
return resp_len - 2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get sak by send apdu
|
//get sak by send apdu
|
||||||
static int pcsc_get_sak(struct nfc_device *pnd, uint8_t *sak, size_t sak_len)
|
int pcsc_get_sak(struct nfc_device *pnd, uint8_t *sak, size_t sak_len)
|
||||||
{
|
{
|
||||||
const uint8_t get_data[] = {0xFF, 0xCA, 0x02, 0x00, 0x00};
|
const uint8_t get_data[] = {0xFF, 0xCA, 0x02, 0x00, 0x00};
|
||||||
uint8_t resp[256 + 2];
|
uint8_t resp[256 + 2];
|
||||||
@ -305,7 +294,7 @@ static int pcsc_get_sak(struct nfc_device *pnd, uint8_t *sak, size_t sak_len)
|
|||||||
return resp_len - 2;
|
return resp_len - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len)
|
int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len)
|
||||||
{
|
{
|
||||||
const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
|
const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
|
||||||
uint8_t resp[256 + 2];
|
uint8_t resp[256 + 2];
|
||||||
@ -330,7 +319,7 @@ static int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len)
|
|||||||
return resp_len - 2;
|
return resp_len - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
if (NULL != pnt) {
|
if (NULL != pnt) {
|
||||||
switch (nmt) {
|
switch (nmt) {
|
||||||
@ -352,23 +341,17 @@ static int pcsc_props_to_target(struct nfc_device *pnd, uint8_t it, const uint8_
|
|||||||
if (is_pcsc_reader_vendor_feitian(pnd)) {
|
if (is_pcsc_reader_vendor_feitian(pnd)) {
|
||||||
uint8_t atqa[2];
|
uint8_t atqa[2];
|
||||||
pcsc_get_atqa(pnd, atqa, sizeof(atqa));
|
pcsc_get_atqa(pnd, atqa, sizeof(atqa));
|
||||||
//ATQA Coding of NXP Contactless Card ICs
|
//memcpy(pnt->nti.nai.abtAtqa,atqa,2);
|
||||||
if(atqa[0] == 0x00 || atqa[0] == 0x03)
|
pnt->nti.nai.abtAtqa[0] = atqa[1];
|
||||||
{
|
pnt->nti.nai.abtAtqa[1] = atqa[0];
|
||||||
memcpy(pnt->nti.nai.abtAtqa,atqa,2);
|
|
||||||
}else {
|
|
||||||
pnt->nti.nai.abtAtqa[0] = atqa[1];
|
|
||||||
pnt->nti.nai.abtAtqa[1] = atqa[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t sak[1];
|
uint8_t sak[1];
|
||||||
pcsc_get_sak(pnd, sak, sizeof(sak));
|
pcsc_get_sak(pnd, sak, sizeof(sak));
|
||||||
pnt->nti.nai.btSak = sak[0];
|
pnt->nti.nai.btSak = sak[0];
|
||||||
uint8_t ats[256];
|
uint8_t ats[256];
|
||||||
int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats));
|
int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats));
|
||||||
ats_len = (ats_len > 0 ? ats_len : 0);//The reader may not support to get ATS
|
|
||||||
memcpy(pnt->nti.nai.abtAts, ats, ats_len);
|
memcpy(pnt->nti.nai.abtAts, ats, ats_len);
|
||||||
pnt->nti.nai.szAtsLen = ats_len;
|
//memcpy(pnt->nti.nai.abtAts + ats_len, patr + 4, (uint8_t)(szatr - 5));
|
||||||
|
pnt->nti.nai.szAtsLen = ats_len;// + szatr - 5;
|
||||||
} else {
|
} else {
|
||||||
/* SAK_ISO14443_4_COMPLIANT */
|
/* SAK_ISO14443_4_COMPLIANT */
|
||||||
pnt->nti.nai.btSak = 0x20;
|
pnt->nti.nai.btSak = 0x20;
|
||||||
@ -538,7 +521,7 @@ pcsc_open(const nfc_context *context, const nfc_connstring connstring)
|
|||||||
// Test if context succeeded
|
// Test if context succeeded
|
||||||
if (!(pscc = pcsc_get_scardcontext()))
|
if (!(pscc = pcsc_get_scardcontext()))
|
||||||
goto error;
|
goto error;
|
||||||
DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0 | 1, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
|
DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol));
|
||||||
if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) {
|
if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) {
|
||||||
// We can not connect to this device.
|
// We can not connect to this device.
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed");
|
||||||
@ -729,19 +712,19 @@ static const char *stringify_error(const LONG pcscError)
|
|||||||
return strError;
|
return strError;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
const char *
|
||||||
pcsc_strerror(const struct nfc_device *pnd)
|
pcsc_strerror(const struct nfc_device *pnd)
|
||||||
{
|
{
|
||||||
return stringify_error(DRIVER_DATA(pnd)->last_error);
|
return stringify_error(DRIVER_DATA(pnd)->last_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_initiator_init(struct nfc_device *pnd)
|
int pcsc_initiator_init(struct nfc_device *pnd)
|
||||||
{
|
{
|
||||||
(void) pnd;
|
(void) pnd;
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
uint8_t atr[MAX_ATR_SIZE];
|
uint8_t atr[MAX_ATR_SIZE];
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
@ -777,15 +760,13 @@ static int pcsc_initiator_select_passive_target(struct nfc_device *pnd, const n
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
int pcsc_initiator_deselect_target(struct nfc_device *pnd)
|
||||||
static int pcsc_initiator_deselect_target(struct nfc_device *pnd)
|
|
||||||
{
|
{
|
||||||
pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD);
|
pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD);
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
size_t resp_len = szRx;
|
size_t resp_len = szRx;
|
||||||
|
|
||||||
@ -814,21 +795,6 @@ static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t
|
|||||||
memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
|
memcpy(apdu_data + 5, pbtTx + 2, szTx - 2);
|
||||||
send_size = 5 + szTx - 2;
|
send_size = 5 + szTx - 2;
|
||||||
} else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A) { //Auth command
|
} else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A) { //Auth command
|
||||||
//load pin first
|
|
||||||
{
|
|
||||||
apdu_data[0] = 0xFF;
|
|
||||||
apdu_data[1] = 0x82;
|
|
||||||
apdu_data[2] = 0x00;
|
|
||||||
apdu_data[3] = 0x01;
|
|
||||||
apdu_data[4] = 0x06;
|
|
||||||
memcpy(apdu_data + 5, pbtTx + 2, 6);
|
|
||||||
send_size = 11;
|
|
||||||
pnd->last_error = pcsc_transmit(pnd, apdu_data, send_size, resp, &resp_len);
|
|
||||||
memset(apdu_data, 0, sizeof(apdu_data));
|
|
||||||
memset(resp, 0, sizeof(resp));
|
|
||||||
usleep(500000);//delay 500ms
|
|
||||||
}
|
|
||||||
// then auth
|
|
||||||
apdu_data[0] = 0xFF;
|
apdu_data[0] = 0xFF;
|
||||||
apdu_data[1] = 0x86;
|
apdu_data[1] = 0x86;
|
||||||
apdu_data[2] = 0x00;
|
apdu_data[2] = 0x00;
|
||||||
@ -882,7 +848,7 @@ static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t
|
|||||||
return resp_len;
|
return resp_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
|
int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
|
||||||
{
|
{
|
||||||
uint8_t atr[MAX_ATR_SIZE];
|
uint8_t atr[MAX_ATR_SIZE];
|
||||||
int target_present;
|
int target_present;
|
||||||
@ -908,7 +874,7 @@ static int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_ta
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable)
|
int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable)
|
||||||
{
|
{
|
||||||
(void) pnd;
|
(void) pnd;
|
||||||
switch (property) {
|
switch (property) {
|
||||||
@ -916,9 +882,6 @@ static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_prope
|
|||||||
// ignore
|
// ignore
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
case NP_AUTO_ISO14443_4:
|
case NP_AUTO_ISO14443_4:
|
||||||
if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
|
|
||||||
return NFC_SUCCESS;
|
|
||||||
break;
|
|
||||||
case NP_EASY_FRAMING:
|
case NP_EASY_FRAMING:
|
||||||
if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
|
if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd)))
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
@ -947,7 +910,7 @@ static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_prope
|
|||||||
return NFC_EDEVNOTSUPP;
|
return NFC_EDEVNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcsc_get_supported_modulation(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
|
int pcsc_get_supported_modulation(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
|
||||||
{
|
{
|
||||||
(void) pnd;
|
(void) pnd;
|
||||||
if (mode == N_TARGET || NULL == supported_mt)
|
if (mode == N_TARGET || NULL == supported_mt)
|
||||||
@ -956,7 +919,7 @@ static int pcsc_get_supported_modulation(struct nfc_device *pnd, const nfc_mode
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
(void) pnd;
|
(void) pnd;
|
||||||
(void) nmt;
|
(void) nmt;
|
||||||
@ -966,18 +929,13 @@ static int pcsc_get_supported_baud_rate(struct nfc_device *pnd, const nfc_mode m
|
|||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
pcsc_get_information_about(nfc_device *pnd, char **pbuf)
|
pcsc_get_information_about(nfc_device *pnd, char **pbuf)
|
||||||
{
|
{
|
||||||
struct pcsc_data *data = pnd->driver_data;
|
struct pcsc_data *data = pnd->driver_data;
|
||||||
LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL;
|
LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL;
|
||||||
#ifdef __APPLE__
|
|
||||||
DWORD name_len = 0, version_len = 0,
|
|
||||||
type_len = 0, serial_len = 0;
|
|
||||||
#else
|
|
||||||
DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE,
|
DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE,
|
||||||
type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE;
|
type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE;
|
||||||
#endif
|
|
||||||
int res = NFC_SUCCESS;
|
int res = NFC_SUCCESS;
|
||||||
SCARDCONTEXT *pscc;
|
SCARDCONTEXT *pscc;
|
||||||
|
|
||||||
|
|||||||
@ -136,7 +136,7 @@ pn532_uart_scan(const nfc_context *context, nfc_connstring connstrings[], const
|
|||||||
CHIP_DATA(pnd)->power_mode = LOWVBAT;
|
CHIP_DATA(pnd)->power_mode = LOWVBAT;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// pipe-based abort mechanism
|
// pipe-based abort mecanism
|
||||||
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
pn53x_data_free(pnd);
|
pn53x_data_free(pnd);
|
||||||
@ -191,7 +191,7 @@ pn532_uart_close(nfc_device *pnd)
|
|||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// Release file descriptors used for abort mechanism
|
// Release file descriptors used for abort mecanism
|
||||||
close(DRIVER_DATA(pnd)->iAbortFds[0]);
|
close(DRIVER_DATA(pnd)->iAbortFds[0]);
|
||||||
close(DRIVER_DATA(pnd)->iAbortFds[1]);
|
close(DRIVER_DATA(pnd)->iAbortFds[1]);
|
||||||
#endif
|
#endif
|
||||||
@ -277,7 +277,7 @@ pn532_uart_open(const nfc_context *context, const nfc_connstring connstring)
|
|||||||
pnd->driver = &pn532_uart_driver;
|
pnd->driver = &pn532_uart_driver;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// pipe-based abort mechanism
|
// pipe-based abort mecanism
|
||||||
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
|
||||||
uart_close(DRIVER_DATA(pnd)->port);
|
uart_close(DRIVER_DATA(pnd)->port);
|
||||||
pn53x_data_free(pnd);
|
pn53x_data_free(pnd);
|
||||||
|
|||||||
@ -43,9 +43,7 @@ Thanks to d18c7db and Okko for example code
|
|||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "nfc-internal.h"
|
#include "nfc-internal.h"
|
||||||
@ -623,7 +621,7 @@ read:
|
|||||||
if (timeout == USB_INFINITE_TIMEOUT) {
|
if (timeout == USB_INFINITE_TIMEOUT) {
|
||||||
usb_timeout = USB_TIMEOUT_PER_PASS;
|
usb_timeout = USB_TIMEOUT_PER_PASS;
|
||||||
} else {
|
} else {
|
||||||
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
|
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
|
||||||
remaining_time -= USB_TIMEOUT_PER_PASS;
|
remaining_time -= USB_TIMEOUT_PER_PASS;
|
||||||
if (remaining_time <= 0) {
|
if (remaining_time <= 0) {
|
||||||
pnd->last_error = NFC_ETIMEOUT;
|
pnd->last_error = NFC_ETIMEOUT;
|
||||||
@ -819,7 +817,7 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const
|
|||||||
if (NP_ACTIVATE_FIELD == property) {
|
if (NP_ACTIVATE_FIELD == property) {
|
||||||
/* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
|
/* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Switch progressive field %s", bEnable ? "On" : "Off");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Switch progressive field %s", bEnable ? "On" : "Off");
|
||||||
if (pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31)) < 0)
|
if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31))) < 0)
|
||||||
return NFC_ECHIP;
|
return NFC_ECHIP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -34,9 +34,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nfc/nfc.h"
|
#include "nfc/nfc.h"
|
||||||
|
|
||||||
|
|||||||
12
libnfc/nfc.c
12
libnfc/nfc.c
@ -565,30 +565,24 @@ nfc_initiator_select_passive_target(nfc_device *pnd,
|
|||||||
nfc_target *pnt)
|
nfc_target *pnt)
|
||||||
{
|
{
|
||||||
uint8_t *abtInit = NULL;
|
uint8_t *abtInit = NULL;
|
||||||
uint8_t maxAbt = MAX(12, szInitData);
|
uint8_t abtTmpInit[MAX(12, szInitData)];
|
||||||
uint8_t *abtTmpInit = malloc(sizeof(uint8_t) * maxAbt);
|
|
||||||
size_t szInit = 0;
|
size_t szInit = 0;
|
||||||
int res;
|
int res;
|
||||||
if ((res = nfc_device_validate_modulation(pnd, N_INITIATOR, &nm)) != NFC_SUCCESS) {
|
if ((res = nfc_device_validate_modulation(pnd, N_INITIATOR, &nm)) != NFC_SUCCESS)
|
||||||
free(abtTmpInit);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
if (szInitData == 0) {
|
if (szInitData == 0) {
|
||||||
// Provide default values, if any
|
// Provide default values, if any
|
||||||
prepare_initiator_data(nm, &abtInit, &szInit);
|
prepare_initiator_data(nm, &abtInit, &szInit);
|
||||||
free(abtTmpInit);
|
|
||||||
} else if (nm.nmt == NMT_ISO14443A) {
|
} else if (nm.nmt == NMT_ISO14443A) {
|
||||||
abtInit = abtTmpInit;
|
abtInit = abtTmpInit;
|
||||||
iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit);
|
iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit);
|
||||||
} else {
|
} else {
|
||||||
abtInit = abtTmpInit;
|
abtInit = abtTmpInit;
|
||||||
memcpy(abtInit, pbtInitData, szInitData);
|
memcpy(abtInit, pbtInitData, szInitData);
|
||||||
free(abtTmpInit);
|
|
||||||
szInit = szInitData;
|
szInit = szInitData;
|
||||||
}
|
}
|
||||||
HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt);
|
|
||||||
|
|
||||||
free(abtTmpInit);
|
HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @ingroup initiator
|
/** @ingroup initiator
|
||||||
|
|||||||
@ -23,8 +23,7 @@ FOREACH(source ${UTILS-SOURCES})
|
|||||||
SET(RC_COMMENT "${PACKAGE_NAME} utility")
|
SET(RC_COMMENT "${PACKAGE_NAME} utility")
|
||||||
SET(RC_INTERNAL_NAME ${source})
|
SET(RC_INTERNAL_NAME ${source})
|
||||||
SET(RC_ORIGINAL_NAME ${source}.exe)
|
SET(RC_ORIGINAL_NAME ${source}.exe)
|
||||||
# RC_FILE_TYPE: VFT_APP
|
SET(RC_FILE_TYPE VFT_APP)
|
||||||
SET(RC_FILE_TYPE 0x00000001L)
|
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
|
||||||
LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
|
LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
@ -42,9 +41,6 @@ FOREACH(source ${UTILS-SOURCES})
|
|||||||
LIST(APPEND TARGETS ../contrib/win32/stdlib)
|
LIST(APPEND TARGETS ../contrib/win32/stdlib)
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32)
|
||||||
ENDIF(${source} MATCHES "nfc-scan-device")
|
ENDIF(${source} MATCHES "nfc-scan-device")
|
||||||
IF(${source} MATCHES "nfc-read-forum-tag3")
|
|
||||||
LIST(APPEND TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/getopt.c)
|
|
||||||
ENDIF()
|
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
ADD_EXECUTABLE(${source} ${TARGETS})
|
ADD_EXECUTABLE(${source} ${TARGETS})
|
||||||
|
|||||||
@ -97,6 +97,10 @@ main(int argc, const char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Display libnfc version
|
||||||
|
acLibnfcVersion = nfc_version();
|
||||||
|
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
// Get commandline options
|
// Get commandline options
|
||||||
for (arg = 1; arg < argc; arg++) {
|
for (arg = 1; arg < argc; arg++) {
|
||||||
if (0 == strcmp(argv[arg], "-h")) {
|
if (0 == strcmp(argv[arg], "-h")) {
|
||||||
@ -113,7 +117,7 @@ main(int argc, const char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
// Force TypeB for all derivatives of B
|
// Force TypeB for all derivatives of B
|
||||||
if (mask & 0xd0)
|
if (mask & 0xf0)
|
||||||
mask |= 0x08;
|
mask |= 0x08;
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR("%s is not supported option.", argv[arg]);
|
||||||
@ -122,13 +126,6 @@ main(int argc, const char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display libnfc version
|
|
||||||
if (verbose) {
|
|
||||||
acLibnfcVersion = nfc_version();
|
|
||||||
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Lazy way to open an NFC device */
|
/* Lazy way to open an NFC device */
|
||||||
#if 0
|
#if 0
|
||||||
pnd = nfc_open(context, NULL);
|
pnd = nfc_open(context, NULL);
|
||||||
|
|||||||
@ -54,12 +54,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
@ -76,7 +70,8 @@ static bool bUseKeyFile;
|
|||||||
static bool bForceKeyFile;
|
static bool bForceKeyFile;
|
||||||
static bool bTolerateFailures;
|
static bool bTolerateFailures;
|
||||||
static bool bFormatCard;
|
static bool bFormatCard;
|
||||||
static bool dWrite = false;
|
static bool magic2 = false;
|
||||||
|
static bool magic3 = false;
|
||||||
static bool unlocked = false;
|
static bool unlocked = false;
|
||||||
static uint8_t uiBlocks;
|
static uint8_t uiBlocks;
|
||||||
static uint8_t keys[] = {
|
static uint8_t keys[] = {
|
||||||
@ -216,6 +211,15 @@ authenticate(uint32_t uiBlock)
|
|||||||
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
|
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
} else if (magic3) {
|
||||||
|
//If it's a One Time Write card, we're gonna authenticate with the default keys
|
||||||
|
memcpy(mp.mpa.abtKey, default_key, sizeof(default_key));
|
||||||
|
|
||||||
|
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// If formatting or not using key file, try to guess the right key
|
// If formatting or not using key file, try to guess the right key
|
||||||
} else if (bFormatCard || !bUseKeyFile) {
|
} else if (bFormatCard || !bUseKeyFile) {
|
||||||
for (size_t key_index = 0; key_index < num_keys; key_index++) {
|
for (size_t key_index = 0; key_index < num_keys; key_index++) {
|
||||||
@ -238,7 +242,7 @@ authenticate(uint32_t uiBlock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
unlock_card(bool write)
|
unlock_card(void)
|
||||||
{
|
{
|
||||||
// Configure the CRC
|
// Configure the CRC
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
|
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
|
||||||
@ -256,10 +260,6 @@ unlock_card(bool write)
|
|||||||
// now send unlock
|
// now send unlock
|
||||||
if (!transmit_bits(abtUnlock1, 7)) {
|
if (!transmit_bits(abtUnlock1, 7)) {
|
||||||
printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
|
printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
|
||||||
dWrite = true;
|
|
||||||
if (write) {
|
|
||||||
printf("Trying to rewrite block 0 on a direct write tag.\n");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (transmit_bytes(abtUnlock2, 1)) {
|
if (transmit_bytes(abtUnlock2, 1)) {
|
||||||
printf("Card unlocked\n");
|
printf("Card unlocked\n");
|
||||||
@ -270,15 +270,6 @@ unlock_card(bool write)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset reader
|
// reset reader
|
||||||
if (!unlocked) {
|
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
|
|
||||||
printf("Error: tag was removed\n");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Configure the CRC
|
// Configure the CRC
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
|
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror(pnd, "nfc_device_set_property_bool");
|
||||||
@ -325,19 +316,23 @@ get_rats(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
read_card(bool read_unlocked)
|
read_card(int read_unlocked)
|
||||||
{
|
{
|
||||||
int32_t iBlock;
|
int32_t iBlock;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
uint32_t uiReadBlocks = 0;
|
uint32_t uiReadBlocks = 0;
|
||||||
|
|
||||||
if (read_unlocked) {
|
if (read_unlocked) {
|
||||||
unlock_card(false);
|
|
||||||
//If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
|
//If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
|
||||||
//need to use the R mode. We'll trigger a warning and let them proceed.
|
//need to use the R mode. We'll trigger a warning and let them proceed.
|
||||||
if (dWrite) {
|
if (magic2) {
|
||||||
printf("Note: This card can't do an unlocked read (R) \n");
|
printf("Note: This card does not require an unlocked read (R) \n");
|
||||||
read_unlocked = 0;
|
read_unlocked = 0;
|
||||||
|
} else {
|
||||||
|
//If User has requested an unlocked read, but we're unable to unlock the card, we'll error out.
|
||||||
|
if (!unlock_card()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,11 +362,18 @@ read_card(bool read_unlocked)
|
|||||||
if (read_unlocked) {
|
if (read_unlocked) {
|
||||||
memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
|
memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
|
||||||
} else {
|
} else {
|
||||||
// Copy the keys over from our key dump and store the retrieved access bits
|
//If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL
|
||||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
|
if (magic3) {
|
||||||
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key));
|
||||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
|
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key));
|
||||||
|
} else {
|
||||||
|
// Copy the keys over from our key dump and store the retrieved access bits
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
|
printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
|
||||||
bFailure = true;
|
bFailure = true;
|
||||||
@ -401,7 +403,7 @@ read_card(bool read_unlocked)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
write_card(bool write_block_zero)
|
write_card(int write_block_zero)
|
||||||
{
|
{
|
||||||
uint32_t uiBlock;
|
uint32_t uiBlock;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
@ -409,18 +411,24 @@ write_card(bool write_block_zero)
|
|||||||
|
|
||||||
//Determine if we have to unlock the card
|
//Determine if we have to unlock the card
|
||||||
if (write_block_zero) {
|
if (write_block_zero) {
|
||||||
unlock_card(true);
|
//If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
|
||||||
|
//need to use the W mode. We'll trigger a warning and let them proceed.
|
||||||
|
if (magic2) {
|
||||||
|
printf("Note: This card does not require an unlocked write (W) \n");
|
||||||
|
write_block_zero = 0;
|
||||||
|
} else {
|
||||||
|
//If User has requested an unlocked write, but we're unable to unlock the card, we'll error out.
|
||||||
|
if (!unlock_card()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Writing %d blocks |", uiBlocks + write_block_zero);
|
printf("Writing %d blocks |", uiBlocks + 1);
|
||||||
// Completely write the card, but skipping block 0 if we don't need to write on it
|
// Completely write the card, end to start, but skipping block 0
|
||||||
for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
|
for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
|
||||||
//Determine if we have to write block 0
|
|
||||||
if (!write_block_zero && uiBlock == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Authenticate everytime we reach the first sector of a new block
|
// Authenticate everytime we reach the first sector of a new block
|
||||||
if (uiBlock == 1 || is_first_block(uiBlock)) {
|
if (is_first_block(uiBlock)) {
|
||||||
if (bFailure) {
|
if (bFailure) {
|
||||||
// When a failure occured we need to redo the anti-collision
|
// When a failure occured we need to redo the anti-collision
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
||||||
@ -434,15 +442,14 @@ write_card(bool write_block_zero)
|
|||||||
|
|
||||||
// Try to authenticate for the current sector
|
// Try to authenticate for the current sector
|
||||||
// If we are are writing to a chinese magic card, we've already unlocked
|
// If we are are writing to a chinese magic card, we've already unlocked
|
||||||
// If we're writing to a direct write card, we need to authenticate
|
// If we're writing to a One Time Write card, we need to authenticate
|
||||||
// If we're writing something else, we'll need to authenticate
|
// If we're writing something else, we'll need to authenticate
|
||||||
if ((write_block_zero && dWrite) || !write_block_zero) {
|
if ((write_block_zero && magic3) || !write_block_zero) {
|
||||||
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
||||||
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (is_trailer_block(uiBlock)) {
|
if (is_trailer_block(uiBlock)) {
|
||||||
if (bFormatCard) {
|
if (bFormatCard) {
|
||||||
@ -463,6 +470,10 @@ write_card(bool write_block_zero)
|
|||||||
bFailure = true;
|
bFailure = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// The first block 0x00 is read only, skip this
|
||||||
|
if (uiBlock == 0 && !write_block_zero && !magic2)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Make sure a earlier write did not fail
|
// Make sure a earlier write did not fail
|
||||||
if (!bFailure) {
|
if (!bFailure) {
|
||||||
// Try to write the data block
|
// Try to write the data block
|
||||||
@ -473,7 +484,7 @@ write_card(bool write_block_zero)
|
|||||||
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
||||||
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
||||||
if (uiBlock == 0) {
|
if (uiBlock == 0) {
|
||||||
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) {
|
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
|
||||||
printf("!\nError: incorrect BCC in MFD file!\n");
|
printf("!\nError: incorrect BCC in MFD file!\n");
|
||||||
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
||||||
return false;
|
return false;
|
||||||
@ -483,29 +494,88 @@ write_card(bool write_block_zero)
|
|||||||
bFailure = true;
|
bFailure = true;
|
||||||
printf("Failure to write to data block %i\n", uiBlock);
|
printf("Failure to write to data block %i\n", uiBlock);
|
||||||
}
|
}
|
||||||
if (uiBlock == 0 && dWrite) {
|
|
||||||
if (nfc_initiator_init(pnd) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_initiator_init");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
};
|
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
|
||||||
printf("!\nError: tag was removed\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
printf("Failure during write process.\n");
|
printf("Failure during write process.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//}
|
}
|
||||||
// Show if the write went well for each block
|
// Show if the write went well for each block
|
||||||
print_success_or_failure(bFailure, &uiWriteBlocks);
|
print_success_or_failure(bFailure, &uiWriteBlocks);
|
||||||
if ((! bTolerateFailures) && bFailure)
|
if ((! bTolerateFailures) && bFailure)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Write Block 0 if necessary
|
||||||
|
if (write_block_zero || magic2 || magic3) {
|
||||||
|
for (uiBlock = 0; uiBlock < 4; uiBlock++) {
|
||||||
|
|
||||||
|
// The first block 0x00 is read only, skip this
|
||||||
|
if (uiBlock == 0) {
|
||||||
|
//If the card is not magic, we're gonna skip over
|
||||||
|
if (write_block_zero || magic2 || magic3) {
|
||||||
|
//NOP
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_first_block(uiBlock)) {
|
||||||
|
if (bFailure) {
|
||||||
|
// When a failure occured we need to redo the anti-collision
|
||||||
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
||||||
|
printf("!\nError: tag was removed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bFailure = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
// If we are are writing to a chinese magic card, we've already unlocked
|
||||||
|
// If we're writing to a One Time Write, we need to authenticate
|
||||||
|
// If we're writing something else, we'll need to authenticate
|
||||||
|
if ((write_block_zero && magic3) || !write_block_zero) {
|
||||||
|
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
||||||
|
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure a earlier write did not fail
|
||||||
|
if (!bFailure) {
|
||||||
|
// Try to write the data block
|
||||||
|
if (bFormatCard && uiBlock)
|
||||||
|
memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
|
||||||
|
else
|
||||||
|
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
||||||
|
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
||||||
|
if (uiBlock == 0) {
|
||||||
|
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
|
||||||
|
printf("!\nError: incorrect BCC in MFD file!\n");
|
||||||
|
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
|
||||||
|
bFailure = true;
|
||||||
|
printf("Failure to write to data block %i\n", uiBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("Failure during write process.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show if the write went well for each block
|
||||||
|
print_success_or_failure(bFailure, &uiWriteBlocks);
|
||||||
|
if ((! bTolerateFailures) && bFailure)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
printf("|\n");
|
printf("|\n");
|
||||||
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -523,24 +593,18 @@ static void
|
|||||||
print_usage(const char *pcProgramName)
|
print_usage(const char *pcProgramName)
|
||||||
{
|
{
|
||||||
printf("Usage: ");
|
printf("Usage: ");
|
||||||
#ifndef _WIN32
|
|
||||||
printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f] [v]]\n", pcProgramName);
|
|
||||||
#else
|
|
||||||
printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
|
printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
|
||||||
#endif
|
printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");
|
||||||
printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or block 0 write to (W) card\n");
|
|
||||||
printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
|
printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
|
||||||
printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
|
printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
|
||||||
printf(" *** note that block 0 write will attempt to overwrite block 0 including UID\n");
|
printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
|
||||||
printf(" *** block 0 write only works with special Mifare cards (Chinese clones)\n");
|
printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
|
||||||
printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
|
printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
|
||||||
printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
|
printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
|
||||||
printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
|
printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
|
||||||
printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
|
printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
|
||||||
printf(" f - Force using the keyfile even if UID does not match (optional)\n");
|
printf(" f - Force using the keyfile even if UID does not match (optional)\n");
|
||||||
#ifndef _WIN32
|
|
||||||
printf(" v - Sends libnfc log output to console (optional)\n");
|
|
||||||
#endif
|
|
||||||
printf("Examples: \n\n");
|
printf("Examples: \n\n");
|
||||||
printf(" Read card to file, using key A:\n\n");
|
printf(" Read card to file, using key A:\n\n");
|
||||||
printf(" %s r a u mycard.mfd\n\n", pcProgramName);
|
printf(" %s r a u mycard.mfd\n\n", pcProgramName);
|
||||||
@ -556,6 +620,54 @@ print_usage(const char *pcProgramName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool is_directwrite()
|
||||||
|
{
|
||||||
|
printf("Checking if Badge is DirectWrite...\n");
|
||||||
|
|
||||||
|
// Set default keys
|
||||||
|
memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key));
|
||||||
|
memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
|
||||||
|
memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key));
|
||||||
|
|
||||||
|
// Temporarly override bUseKeyFile
|
||||||
|
bool orig_bUseKeyFile = bUseKeyFile;
|
||||||
|
bUseKeyFile = false;
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (!authenticate(0)) {
|
||||||
|
printf("!\nError: authentication failed for block 0x%02x\n", 0);
|
||||||
|
bUseKeyFile = orig_bUseKeyFile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// restore bUseKeyFile
|
||||||
|
bUseKeyFile = orig_bUseKeyFile;
|
||||||
|
|
||||||
|
// Try to read block 0
|
||||||
|
uint8_t original_b0[16];
|
||||||
|
if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
|
||||||
|
memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData));
|
||||||
|
printf(" Original Block 0: ");
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
printf("%02x", original_b0[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf(" Original UID: %02x%02x%02x%02x\n",
|
||||||
|
original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
|
||||||
|
} else {
|
||||||
|
printf("!\nError: unable to read block 0x%02x\n", 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" Attempt to write Block 0 ...\n");
|
||||||
|
memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
|
||||||
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
|
||||||
|
printf("Failure to write to data block %i\n", 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
printf(" Block 0 written successfully\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
@ -564,7 +676,7 @@ main(int argc, const char *argv[])
|
|||||||
uint8_t _tag_uid[4];
|
uint8_t _tag_uid[4];
|
||||||
uint8_t *tag_uid = _tag_uid;
|
uint8_t *tag_uid = _tag_uid;
|
||||||
|
|
||||||
bool unlock = false;
|
int unlock = 0;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
@ -579,19 +691,19 @@ main(int argc, const char *argv[])
|
|||||||
if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
|
if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
|
||||||
atAction = ACTION_READ;
|
atAction = ACTION_READ;
|
||||||
if (strcmp(command, "R") == 0)
|
if (strcmp(command, "R") == 0)
|
||||||
unlock = true;
|
unlock = 1;
|
||||||
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
|
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
|
||||||
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
|
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
|
||||||
bUseKeyFile = (argc > 5) && strcmp(argv[5], "v");
|
bUseKeyFile = (argc > 5);
|
||||||
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
|
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
|
||||||
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
|
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
|
||||||
atAction = ACTION_WRITE;
|
atAction = ACTION_WRITE;
|
||||||
if (strcmp(command, "W") == 0)
|
if (strcmp(command, "W") == 0)
|
||||||
unlock = true;
|
unlock = 1;
|
||||||
bFormatCard = (strcmp(command, "f") == 0);
|
bFormatCard = (strcmp(command, "f") == 0);
|
||||||
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
|
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
|
||||||
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
|
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
|
||||||
bUseKeyFile = (argc > 5) && strcmp(argv[5], "v");
|
bUseKeyFile = (argc > 5);
|
||||||
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
|
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
|
||||||
}
|
}
|
||||||
if (argv[3][0] == 'U') {
|
if (argv[3][0] == 'U') {
|
||||||
@ -613,21 +725,6 @@ main(int argc, const char *argv[])
|
|||||||
tag_uid = NULL;
|
tag_uid = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
// Send noise from lib to /dev/null
|
|
||||||
bool verbose = false;
|
|
||||||
if (argv[7]) {
|
|
||||||
if (strcmp(argv[7], "v") == 0) verbose = true;
|
|
||||||
} else {
|
|
||||||
if ((strcmp(argv[6], "v")) || (strcmp(argv[5], "v")) == 0) verbose = true;
|
|
||||||
}
|
|
||||||
if (!verbose) {
|
|
||||||
int fd = open("/dev/null", O_WRONLY);
|
|
||||||
dup2(fd, 2);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (atAction == ACTION_USAGE) {
|
if (atAction == ACTION_USAGE) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -667,14 +764,6 @@ main(int argc, const char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Drop the field for a while, so can be reset
|
|
||||||
if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, true) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool activate field");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
|
if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror(pnd, "nfc_device_set_property_bool");
|
||||||
@ -690,24 +779,11 @@ main(int argc, const char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the CRC and Parity settings
|
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool crc");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true) < 0) {
|
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool parity");
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
|
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
|
||||||
|
|
||||||
// Try to find a MIFARE Classic tag
|
// Try to find a MIFARE Classic tag
|
||||||
int tags;
|
int tags;
|
||||||
|
|
||||||
tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
|
tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
|
||||||
if (tags <= 0) {
|
if (tags <= 0) {
|
||||||
printf("Error: no tag was found\n");
|
printf("Error: no tag was found\n");
|
||||||
@ -716,8 +792,7 @@ main(int argc, const char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
// Test if we are dealing with a MIFARE compatible tag
|
// Test if we are dealing with a MIFARE compatible tag
|
||||||
if (((nt.nti.nai.btSak & 0x08) == 0) && (nt.nti.nai.btSak != 0x01)) {
|
if ((nt.nti.nai.btSak & 0x08) == 0) {
|
||||||
// if ((nt.nti.nai.btSak & 0x08) == 0) {
|
|
||||||
printf("Warning: tag is probably not a MFC!\n");
|
printf("Warning: tag is probably not a MFC!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,10 +839,35 @@ main(int argc, const char *argv[])
|
|||||||
// MIFARE Plus 2K
|
// MIFARE Plus 2K
|
||||||
uiBlocks = 0x7f;
|
uiBlocks = 0x7f;
|
||||||
}
|
}
|
||||||
|
// Chinese magic emulation card, ATS=0978009102:dabc1910
|
||||||
|
if ((res == 9) && (abtRx[5] == 0xda) && (abtRx[6] == 0xbc)
|
||||||
|
&& (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
|
||||||
|
magic2 = true;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
printf("RATS support: no\n");
|
printf("RATS support: no\n");
|
||||||
printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block)));
|
printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block)));
|
||||||
|
|
||||||
|
//If size is 4k check for direct-write card
|
||||||
|
if (uiBlocks == 0xff) {
|
||||||
|
if (is_directwrite()) {
|
||||||
|
printf("Card is DirectWrite\n");
|
||||||
|
magic3 = true;
|
||||||
|
unlock = 0;
|
||||||
|
} else {
|
||||||
|
printf("Card is not DirectWrite\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check to see if we have a One Time Write badge (magic3)
|
||||||
|
if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 &&
|
||||||
|
pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
|
||||||
|
printf("Card appears to be a One Time Write Card..\n");
|
||||||
|
magic3 = true;
|
||||||
|
unlock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (bUseKeyFile) {
|
if (bUseKeyFile) {
|
||||||
FILE *pfKeys = fopen(argv[5], "rb");
|
FILE *pfKeys = fopen(argv[5], "rb");
|
||||||
if (pfKeys == NULL) {
|
if (pfKeys == NULL) {
|
||||||
@ -822,17 +922,9 @@ main(int argc, const char *argv[])
|
|||||||
}
|
}
|
||||||
printf("Done.\n");
|
printf("Done.\n");
|
||||||
fclose(pfDump);
|
fclose(pfDump);
|
||||||
} else {
|
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
} else if (atAction == ACTION_WRITE) {
|
} else if (atAction == ACTION_WRITE) {
|
||||||
if (!write_card(unlock)) {
|
write_card(unlock);
|
||||||
nfc_close(pnd);
|
|
||||||
nfc_exit(context);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_close(pnd);
|
nfc_close(pnd);
|
||||||
|
|||||||
@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
#include "nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
#if defined(WIN32) /* mingw compiler */
|
#if defined(WIN32) && defined(__GNUC__) /* mingw compiler */
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user