moving win32 binaries
This commit is contained in:
parent
767cf2b324
commit
bbae6dcee5
27 changed files with 1550 additions and 1310 deletions
146
README.TXT
146
README.TXT
|
@ -2,145 +2,23 @@
|
||||||
Public platform independent Near Field Communication (NFC) library
|
Public platform independent Near Field Communication (NFC) library
|
||||||
Copyright (C) 2009, Roel Verdult
|
Copyright (C) 2009, Roel Verdult
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
------------------------------------------------------------------------
|
||||||
it under the terms of the GNU General Public License as published by
|
Welcome to the developers community of libnfc.
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Since it is hard to keep all information up to date
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
we decided to only maintain the online documentation.
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Please visit the official website for more info:
|
||||||
GNU General Public License for more details.
|
http://www.libnfc.org
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
If you have questions, remarks, bug-reports, we encourage you to
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
post this in the developers community:
|
||||||
|
http://www.libnfc.org/community
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
Welcome to the community of libnfc (website: http://www.libnfc.org).
|
Proprietary Notes:
|
||||||
|
|
||||||
libnfc version 1.0.0
|
FeliCa is s registered trademark of Sony Corporation. MIFARE is a
|
||||||
|
|
||||||
Index:
|
|
||||||
1. Introduction
|
|
||||||
2. Hardware
|
|
||||||
3. Compilation
|
|
||||||
4. Examples
|
|
||||||
5. Todo
|
|
||||||
6. Contact
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
Since the RFID market is spoiled by proprietary hard and software
|
|
||||||
we want to contribute constructively by distributing a free library
|
|
||||||
which can be used in RFID/NFC applications.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
2. Hardware
|
|
||||||
|
|
||||||
To communicate with NFC targets/tags you need a USB device which is
|
|
||||||
called a "RFID Reader". The cheapest hardware around that can carries
|
|
||||||
a fully NFC complied chip is the ACR122 from the company ACS, Advanced
|
|
||||||
Card Systems Limited (website: http://www.acs.com.hk/acr122.php).
|
|
||||||
This reader uses the PN532 chipset from NXP Semiconductors. The reader
|
|
||||||
costs around the €60 and is available in different webshops all over
|
|
||||||
the world. The NFC reader used in the "tikitag" project is exactly the
|
|
||||||
same reader as the ACR122 but with a different logo. This reader is
|
|
||||||
available for only €35,- (website: http://www.tikitag.com). We would
|
|
||||||
recommend to use one of these readers, since we tested both of them.
|
|
||||||
|
|
||||||
Other NFC readers, like the SCL3710 from SCM Microsystems (website:
|
|
||||||
http://www.scmmicro.com/scl3710/) are not supported yet. They use the
|
|
||||||
same chipset, so the instruction set is completely the same. This means
|
|
||||||
that with little effort these readers could be added to be part of the
|
|
||||||
NFC library. We would be very pleased if someone is willing to add this
|
|
||||||
support to libnfc.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
3. Compilation
|
|
||||||
|
|
||||||
If you use linux, please make sure you have libpcsc-lite installed.
|
|
||||||
For Ubuntu this means you have to install the following packages:
|
|
||||||
$sudo apt-get install pcscd
|
|
||||||
$sudo apt-get install libpcsclite-dev
|
|
||||||
When these are installed, just run "make" and you are ready to go.
|
|
||||||
|
|
||||||
MacOSX users have to edit the "Makefile" file in the main directory.
|
|
||||||
Uncomment the following lines:
|
|
||||||
#LIB_TYPE=...
|
|
||||||
#LIB_FLAGS=...
|
|
||||||
#PCSC_HEADERS=...
|
|
||||||
#PCSC_LIB=...
|
|
||||||
Run "make" and you it should work like a charm.
|
|
||||||
|
|
||||||
Windows users can use the binairy files located in the "win32bin"
|
|
||||||
directory. Or they can open the VS2005 solution which can be found
|
|
||||||
in the "win32" directory. Compilation should work "out of the box".
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
4. Examples
|
|
||||||
|
|
||||||
There are 6 example tools coming with this library. They can be used
|
|
||||||
as a reference during development of your software. All tools try to
|
|
||||||
demonstrate a different feature. Below there is short description of
|
|
||||||
the tools and their purpose.
|
|
||||||
|
|
||||||
anticol - Anti-collision demonstration tool for ISO14443A tags using
|
|
||||||
self constructed REQA/WUPA and SELECT frames.
|
|
||||||
|
|
||||||
list - List passive tags tool for ISO14443A tags using the commands
|
|
||||||
available in the instruction set of the hardware chip.
|
|
||||||
|
|
||||||
simulate - With this example you can turn your reader into a NFC target.
|
|
||||||
For testing purposes it simulates a ISO14443A tag with a UID
|
|
||||||
that consists of 0xDEADBEAF. The frames are delayed because
|
|
||||||
of the USB communication, so not all readers will recognize
|
|
||||||
the tag. The "Omnikey 5121" though has no problems with this
|
|
||||||
small delay.
|
|
||||||
|
|
||||||
relay - This tool allows the user to use 2 readers. One will similate
|
|
||||||
a ISO14443A tag, while the 2nd reader will stay a reader.
|
|
||||||
The original tag can be placed on the 2nd reader and the
|
|
||||||
simulated tag can be placed on top of the original reader.
|
|
||||||
All communication is relayed now and showed on the screen.
|
|
||||||
NOTE: relaying frames is time-consuming, not all readers
|
|
||||||
allow slow responds from the (simulated) tag. Though, one of
|
|
||||||
the most used RFID readers, the "Omnikey 5121" has no problem
|
|
||||||
and can perfectly be used for demonstrating this features.
|
|
||||||
|
|
||||||
mfread - With this tool a complete MIFARE card can be readout and stored
|
|
||||||
in a MIFARE dump file (*.mfd).
|
|
||||||
|
|
||||||
mfwrite - With this tool a complete MIFARE card can be restored from a
|
|
||||||
a MIFARE dump file (*.mfd) back to the tag.
|
|
||||||
|
|
||||||
A MIFARE dump file (*.mfd) is a plain 4KB image of a mifare tag. This
|
|
||||||
image should contain the data, keys and access bits on their usual position.
|
|
||||||
A Dump file is always 4KB, even when a 1KB tag is dumped. From the first
|
|
||||||
block, the manufacturer data, can be determined if you are dealing with
|
|
||||||
a 1KB or a 4KB tag. This is stored in the ATQA part of block0 (byte 6/7).
|
|
||||||
More info can be found in the MIFARE functional specification from NXP.
|
|
||||||
(Website: http://www.nxp.com/products/identification/mifare/classic)
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
5. Todo
|
|
||||||
|
|
||||||
Support more communication protocols. Sony Felica, ISO14443B and Innovision
|
|
||||||
Jewel Topaz tags are supported by the chipset, but they are not used by
|
|
||||||
this library. It would be very useful if we could add support for these
|
|
||||||
tags in this library.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
6. Contact
|
|
||||||
|
|
||||||
Please visit the website (http://www.libnfc.org) and place your questions
|
|
||||||
in the community forum there. We are sure a member of the community will
|
|
||||||
help you out.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
Proprietary notes:
|
|
||||||
|
|
||||||
Note: FeliCa is s registered trademark of Sony Corporation. MIFARE is a
|
|
||||||
trademark of NXP Semiconductors. Jewel Topaz is a trademark of Innovision
|
trademark of NXP Semiconductors. Jewel Topaz is a trademark of Innovision
|
||||||
Research & Technology. All other trademarks are the property of their
|
Research & Technology. All other trademarks are the property of their
|
||||||
respective owners.
|
respective owners.
|
||||||
|
|
||||||
|
|
108
anticol.c
108
anticol.c
|
@ -23,91 +23,100 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "libnfc.h"
|
#include "libnfc.h"
|
||||||
|
|
||||||
static byte abtRecv[MAX_FRAME_LEN];
|
#define SAK_FLAG_ATS_SUPPORTED 0x20
|
||||||
static ui32 uiRecvLen;
|
|
||||||
|
static byte abtRx[MAX_FRAME_LEN];
|
||||||
|
static ui32 uiRxBits;
|
||||||
|
static ui32 uiRxLen;
|
||||||
static byte abtUid[10];
|
static byte abtUid[10];
|
||||||
static ui32 uiUidLen = 4;
|
static ui32 uiUidLen = 4;
|
||||||
static dev_id di;
|
static dev_info* pdi;
|
||||||
|
|
||||||
// ISO14443A Anti-Collision Commands
|
// ISO14443A Anti-Collision Commands
|
||||||
byte abtWupa [1] = { 0x52 };
|
byte abtReqa [1] = { 0x26 };
|
||||||
byte abtSelectAll [2] = { 0x93,0x20 };
|
byte abtSelectAll [2] = { 0x93,0x20 };
|
||||||
byte abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
byte abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
byte abtRats [4] = { 0xe0,0x50,0xbc,0xa5 };
|
byte abtRats [4] = { 0xe0,0x50,0xbc,0xa5 };
|
||||||
byte abtHalt [4] = { 0x50,0x00,0x57,0xcd };
|
byte abtHalt [4] = { 0x50,0x00,0x57,0xcd };
|
||||||
|
|
||||||
bool transmit_7bits(const byte btTx)
|
bool transmit_bits(const byte* pbtTx, const ui32 uiTxBits)
|
||||||
{
|
{
|
||||||
bool bResult;
|
// Show transmitted command
|
||||||
printf("R: %02x\n",btTx);
|
printf("R: "); print_hex_bits(pbtTx,uiTxBits);
|
||||||
uiRecvLen = MAX_FRAME_LEN;
|
|
||||||
bResult = nfc_reader_transceive_7bits(di,btTx,abtRecv,&uiRecvLen);
|
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
||||||
if (bResult)
|
if (!nfc_reader_transceive_bits(pdi,pbtTx,uiTxBits,null,abtRx,&uiRxBits,null)) return false;
|
||||||
{
|
|
||||||
printf("T: ");
|
// Show received answer
|
||||||
print_hex(abtRecv,uiRecvLen);
|
printf("T: "); print_hex_bits(abtRx,uiRxBits);
|
||||||
}
|
|
||||||
return bResult;
|
// Succesful transfer
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool transmit_bytes(const byte* pbtTx, const ui32 uiTxLen)
|
bool transmit_bytes(const byte* pbtTx, const ui32 uiTxLen)
|
||||||
{
|
{
|
||||||
bool bResult;
|
// Show transmitted command
|
||||||
printf("R: ");
|
printf("R: "); print_hex(pbtTx,uiTxLen);
|
||||||
print_hex(pbtTx,uiTxLen);
|
|
||||||
uiRecvLen = MAX_FRAME_LEN;
|
// Transmit the command bytes
|
||||||
bResult = nfc_reader_transceive_bytes(di,pbtTx,uiTxLen,abtRecv,&uiRecvLen);
|
if (!nfc_reader_transceive_bytes(pdi,pbtTx,uiTxLen,abtRx,&uiRxLen)) return false;
|
||||||
if (bResult)
|
|
||||||
{
|
// Show received answer
|
||||||
printf("T: ");
|
printf("T: "); print_hex(abtRx,uiRxLen);
|
||||||
print_hex(abtRecv,uiRecvLen);
|
|
||||||
}
|
// Succesful transfer
|
||||||
return bResult;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
di = acr122_connect(0);
|
pdi = nfc_connect();
|
||||||
|
|
||||||
if (di == INVALID_DEVICE_ID)
|
if (!pdi)
|
||||||
{
|
{
|
||||||
printf("Error connecting NFC reader\n");
|
printf("Error connecting NFC reader\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
nfc_reader_init(di);
|
nfc_reader_init(pdi);
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Drop the field for a while
|
||||||
nfc_configure_list_passive_infinite(di,false);
|
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||||
|
|
||||||
// Drop the field so the tag will be reset
|
// Configure the CRC and Parity settings
|
||||||
nfc_configure_field(di,false);
|
nfc_configure(pdi,DCO_HANDLE_CRC,false);
|
||||||
|
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||||
|
|
||||||
// Configure the communication channel, we use our own CRC
|
// Enable field so more power consuming cards can power themselves up
|
||||||
nfc_configure_handle_crc(di,false);
|
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||||
nfc_configure_handle_parity(di,true);
|
|
||||||
|
|
||||||
// Enable the field so the more power consuming tags will respond
|
printf("\nConnected to NFC reader: %s\n\n",pdi->acName);
|
||||||
nfc_configure_field(di,true);
|
|
||||||
|
|
||||||
printf("\nConnected to NFC reader\n\n");
|
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
||||||
|
if (!transmit_bits(abtReqa,7))
|
||||||
if (!transmit_7bits(*abtWupa))
|
|
||||||
{
|
{
|
||||||
printf("Error: No tag available\n");
|
printf("Error: No tag available\n");
|
||||||
|
nfc_disconnect(pdi);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anti-collision
|
// Anti-collision
|
||||||
transmit_bytes(abtSelectAll,2);
|
transmit_bytes(abtSelectAll,2);
|
||||||
|
|
||||||
// Save the UID
|
// Save the UID
|
||||||
memcpy(abtUid,abtRecv,4);
|
memcpy(abtUid,abtRx,4);
|
||||||
memcpy(abtSelectTag+2,abtRecv,5);
|
memcpy(abtSelectTag+2,abtRx,5);
|
||||||
append_iso14443a_crc(abtSelectTag,7);
|
append_iso14443a_crc(abtSelectTag,7);
|
||||||
transmit_bytes(abtSelectTag,9);
|
transmit_bytes(abtSelectTag,9);
|
||||||
|
|
||||||
if (abtUid[0] == 0x88)
|
// Test if we are dealing with a 4 bytes uid
|
||||||
|
if (abtUid[0]!= 0x88)
|
||||||
{
|
{
|
||||||
|
uiUidLen = 4;
|
||||||
|
} else {
|
||||||
|
// We have to do the anti-collision for cascade level 2
|
||||||
abtSelectAll[0] = 0x95;
|
abtSelectAll[0] = 0x95;
|
||||||
abtSelectTag[0] = 0x95;
|
abtSelectTag[0] = 0x95;
|
||||||
|
|
||||||
|
@ -115,18 +124,15 @@ int main(int argc, const char* argv[])
|
||||||
transmit_bytes(abtSelectAll,2);
|
transmit_bytes(abtSelectAll,2);
|
||||||
|
|
||||||
// Save the UID
|
// Save the UID
|
||||||
memcpy(abtUid+4,abtRecv,4);
|
memcpy(abtUid+4,abtRx,4);
|
||||||
memcpy(abtSelectTag+2,abtRecv,5);
|
memcpy(abtSelectTag+2,abtRx,5);
|
||||||
append_iso14443a_crc(abtSelectTag,7);
|
append_iso14443a_crc(abtSelectTag,7);
|
||||||
transmit_bytes(abtSelectTag,9);
|
transmit_bytes(abtSelectTag,9);
|
||||||
uiUidLen = 7;
|
uiUidLen = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request ATS, this only applies to tags that support ISO 14443A-4
|
// Request ATS, this only applies to tags that support ISO 14443A-4
|
||||||
if (abtRecv[0] & 0x20)
|
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) transmit_bytes(abtRats,4);
|
||||||
{
|
|
||||||
transmit_bytes(abtRats,4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done, halt the tag now
|
// Done, halt the tag now
|
||||||
transmit_bytes(abtHalt,4);
|
transmit_bytes(abtHalt,4);
|
||||||
|
@ -138,5 +144,7 @@ int main(int argc, const char* argv[])
|
||||||
} else {
|
} else {
|
||||||
printf("%014llx\n",swap_endian64(abtUid)&0x00ffffffffffffffull);
|
printf("%014llx\n",swap_endian64(abtUid)&0x00ffffffffffffffull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nfc_disconnect(pdi);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
28
bitutils.c
28
bitutils.c
|
@ -116,7 +116,7 @@ ui32 swap_endian32(const void* pui32)
|
||||||
ui64 swap_endian64(const void* pui64)
|
ui64 swap_endian64(const void* pui64)
|
||||||
{
|
{
|
||||||
ui64 ui64N = *((ui64*)pui64);
|
ui64 ui64N = *((ui64*)pui64);
|
||||||
return (((ui64N&0xFF)<<56)+((ui64N&0xFF00)<<40)+((ui64N&0xFF0000)<<24)+((ui64N&0xFF000000)<<8)+((ui64N&0xFF00000000)>>8)+((ui64N&0xFF0000000000)>>24)+((ui64N&0xFF000000000000)>>40)+((ui64N&0xFF00000000000000)>>56));
|
return (((ui64N&0xFF)<<56)+((ui64N&0xFF00)<<40)+((ui64N&0xFF0000)<<24)+((ui64N&0xFF000000)<<8)+((ui64N&0xFF00000000ull)>>8)+((ui64N&0xFF0000000000ull)>>24)+((ui64N&0xFF000000000000ull)>>40)+((ui64N&0xFF00000000000000ull)>>56));
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_iso14443a_crc(byte* pbtData, ui32 uiLen)
|
void append_iso14443a_crc(byte* pbtData, ui32 uiLen)
|
||||||
|
@ -135,16 +135,33 @@ void append_iso14443a_crc(byte* pbtData, ui32 uiLen)
|
||||||
*pbtData = (byte) ((wCrc >> 8) & 0xFF);
|
*pbtData = (byte) ((wCrc >> 8) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_hex(const byte* pbtData, const ui32 uiLen)
|
void print_hex(const byte* pbtData, const ui32 uiBytes)
|
||||||
{
|
{
|
||||||
ui32 uiPos;
|
ui32 uiPos;
|
||||||
for (uiPos=0; uiPos < uiLen; uiPos++)
|
|
||||||
|
for (uiPos=0; uiPos < uiBytes; uiPos++)
|
||||||
{
|
{
|
||||||
printf("%02x ",pbtData[uiPos]);
|
printf("%02x ",pbtData[uiPos]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_hex_bits(const byte* pbtData, const ui32 uiBits)
|
||||||
|
{
|
||||||
|
ui32 uiPos;
|
||||||
|
ui32 uiBytes = uiBits/8;
|
||||||
|
|
||||||
|
for (uiPos=0; uiPos < uiBytes; uiPos++)
|
||||||
|
{
|
||||||
|
printf("%02x ",pbtData[uiPos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the rest bits, these cannot have no parity bit
|
||||||
|
if (uiBits%8 != 0) printf("%02x",pbtData[uiBytes]);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPar)
|
void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPar)
|
||||||
{
|
{
|
||||||
ui32 uiPos;
|
ui32 uiPos;
|
||||||
|
@ -162,10 +179,7 @@ void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPa
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the rest bits, these cannot have no parity bit
|
// Print the rest bits, these cannot have no parity bit
|
||||||
if (uiBits%8 != 0)
|
if (uiBits%8 != 0) printf("%02x",pbtData[uiBytes]);
|
||||||
{
|
|
||||||
printf("%02x",pbtData[uiBytes]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
19
bitutils.h
19
bitutils.h
|
@ -23,24 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
#define INNER_XOR8(n) {\
|
|
||||||
n ^= (n >> 4); \
|
|
||||||
n ^= (n >> 2); \
|
|
||||||
n ^= (n >> 1); \
|
|
||||||
n &= 0x01; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INNER_XOR32(n) {\
|
|
||||||
n ^= (n >> 16); \
|
|
||||||
n ^= (n >> 8); \
|
|
||||||
INNER_XOR8(n); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INNER_XOR64(n) {\
|
|
||||||
n ^= (n >> 32); \
|
|
||||||
INNER_XOR32(n); \
|
|
||||||
}
|
|
||||||
|
|
||||||
byte oddparity(const byte bt);
|
byte oddparity(const byte bt);
|
||||||
void oddparity_bytes(const byte* pbtData, const ui32 uiLen, byte* pbtPar);
|
void oddparity_bytes(const byte* pbtData, const ui32 uiLen, byte* pbtPar);
|
||||||
|
|
||||||
|
@ -55,6 +37,7 @@ ui64 swap_endian64(const void* pui64);
|
||||||
void append_iso14443a_crc(byte* pbtData, ui32 uiLen);
|
void append_iso14443a_crc(byte* pbtData, ui32 uiLen);
|
||||||
|
|
||||||
void print_hex(const byte* pbtData, const ui32 uiLen);
|
void print_hex(const byte* pbtData, const ui32 uiLen);
|
||||||
|
void print_hex_bits(const byte* pbtData, const ui32 uiBits);
|
||||||
void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPar);
|
void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPar);
|
||||||
|
|
||||||
#endif // _LIBNFC_BITUTILS_H_
|
#endif // _LIBNFC_BITUTILS_H_
|
||||||
|
|
17
defines.h
17
defines.h
|
@ -21,6 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#ifndef _LIBNFC_DEFINES_H_
|
#ifndef _LIBNFC_DEFINES_H_
|
||||||
#define _LIBNFC_DEFINES_H_
|
#define _LIBNFC_DEFINES_H_
|
||||||
|
|
||||||
|
// #define _LIBNFC_VERBOSE_
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
typedef unsigned char ui8;
|
typedef unsigned char ui8;
|
||||||
typedef unsigned short ui16;
|
typedef unsigned short ui16;
|
||||||
|
@ -33,13 +35,16 @@ typedef int i32;
|
||||||
|
|
||||||
#define null 0
|
#define null 0
|
||||||
|
|
||||||
typedef void* dev_id; // Device Id
|
typedef void* dev_spec; // Device connection specification
|
||||||
#define INVALID_DEVICE_ID null
|
#define INVALID_DEVICE_INFO null
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
#define DEVICE_NAME_LENGTH 256
|
||||||
|
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
// Useful macros
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
// #define _LIBNFC_VERBOSE_
|
#define INNER_XOR8(n) {n ^= (n >> 4); n ^= (n >> 2); n ^= (n >> 1); n &= 0x01; }
|
||||||
|
#define INNER_XOR32(n) {n ^= (n >> 16); n ^= (n >> 8); INNER_XOR8(n); }
|
||||||
|
#define INNER_XOR64(n) {n ^= (n >> 32); INNER_XOR32(n); }
|
||||||
|
|
||||||
#endif // _LIBNFC_DEFINES_H_
|
#endif // _LIBNFC_DEFINES_H_
|
||||||
|
|
623
libnfc.c
623
libnfc.c
|
@ -18,18 +18,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "libnfc.h"
|
||||||
|
#include "bitutils.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "libnfc.h"
|
|
||||||
#include "acr122.h"
|
|
||||||
#include "bitutils.h"
|
|
||||||
|
|
||||||
|
// Registers and symbols masks used to covers parts within a register
|
||||||
#define REG_CIU_TX_MODE 0x6302
|
#define REG_CIU_TX_MODE 0x6302
|
||||||
|
#define SYMBOL_TX_CRC_ENABLE 0x80
|
||||||
#define REG_CIU_RX_MODE 0x6303
|
#define REG_CIU_RX_MODE 0x6303
|
||||||
|
#define SYMBOL_RX_CRC_ENABLE 0x80
|
||||||
|
#define SYMBOL_RX_NO_ERROR 0x08
|
||||||
|
#define SYMBOL_RX_MULTIPLE 0x04
|
||||||
#define REG_CIU_TX_AUTO 0x6305
|
#define REG_CIU_TX_AUTO 0x6305
|
||||||
|
#define SYMBOL_FORCE_100_ASK 0x40
|
||||||
|
#define SYMBOL_AUTO_WAKE_UP 0x20
|
||||||
|
#define SYMBOL_INITIAL_RF_ON 0x04
|
||||||
#define REG_CIU_MANUAL_RCV 0x630D
|
#define REG_CIU_MANUAL_RCV 0x630D
|
||||||
|
#define SYMBOL_PARITY_DISABLE 0x10
|
||||||
|
#define REG_CIU_STATUS2 0x6338
|
||||||
|
#define SYMBOL_MF_CRYPTO1_ON 0x08
|
||||||
#define REG_CIU_CONTROL 0x633C
|
#define REG_CIU_CONTROL 0x633C
|
||||||
|
#define SYMBOL_INITIATOR 0x10
|
||||||
|
#define SYMBOL_RX_LAST_BITS 0x07
|
||||||
#define REG_CIU_BIT_FRAMING 0x633D
|
#define REG_CIU_BIT_FRAMING 0x633D
|
||||||
|
#define SYMBOL_TX_LAST_BITS 0x07
|
||||||
|
|
||||||
#define PARAM_NONE 0x00
|
#define PARAM_NONE 0x00
|
||||||
#define PARAM_NAD_USED 0x01
|
#define PARAM_NAD_USED 0x01
|
||||||
|
@ -39,7 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#define PARAM_14443_4_PICC 0x20
|
#define PARAM_14443_4_PICC 0x20
|
||||||
#define PARAM_NO_AMBLE 0x40
|
#define PARAM_NO_AMBLE 0x40
|
||||||
|
|
||||||
// PN532 configuration
|
// PN53X configuration
|
||||||
byte pncmd_get_firmware_version [ 2] = { 0xD4,0x02 };
|
byte pncmd_get_firmware_version [ 2] = { 0xD4,0x02 };
|
||||||
byte pncmd_get_general_status [ 2] = { 0xD4,0x04 };
|
byte pncmd_get_general_status [ 2] = { 0xD4,0x04 };
|
||||||
byte pncmd_get_register [ 4] = { 0xD4,0x06 };
|
byte pncmd_get_register [ 4] = { 0xD4,0x06 };
|
||||||
|
@ -55,8 +68,8 @@ byte pncmd_rf_configure_retry_select [ 6] = { 0xD4,0x32,0x05 };
|
||||||
// Reader
|
// Reader
|
||||||
byte pncmd_reader_list_passive [264] = { 0xD4,0x4A };
|
byte pncmd_reader_list_passive [264] = { 0xD4,0x4A };
|
||||||
byte pncmd_reader_select [ 3] = { 0xD4,0x54 };
|
byte pncmd_reader_select [ 3] = { 0xD4,0x54 };
|
||||||
byte pncmd_reader_deselect [ 3] = { 0xD4,0x44 };
|
byte pncmd_reader_deselect [ 3] = { 0xD4,0x44,0x00 };
|
||||||
byte pncmd_reader_release [ 3] = { 0xD4,0x52 };
|
byte pncmd_reader_release [ 3] = { 0xD4,0x52,0x00 };
|
||||||
byte pncmd_reader_set_baud_rate [ 5] = { 0xD4,0x4E };
|
byte pncmd_reader_set_baud_rate [ 5] = { 0xD4,0x4E };
|
||||||
byte pncmd_reader_exchange_data [265] = { 0xD4,0x40 };
|
byte pncmd_reader_exchange_data [265] = { 0xD4,0x40 };
|
||||||
byte pncmd_reader_auto_poll [ 5] = { 0xD4,0x60 };
|
byte pncmd_reader_auto_poll [ 5] = { 0xD4,0x60 };
|
||||||
|
@ -72,42 +85,65 @@ byte pncmd_target_get_status [ 2] = { 0xD4,0x8A };
|
||||||
// Exchange raw data frames
|
// Exchange raw data frames
|
||||||
byte pncmd_exchange_raw_data [266] = { 0xD4,0x42 };
|
byte pncmd_exchange_raw_data [266] = { 0xD4,0x42 };
|
||||||
|
|
||||||
// Global buffers used for communication with the PN532 chip
|
// Global buffers used for communication with the PN53X chip
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
static byte abtRx[MAX_FRAME_LEN];
|
static byte abtRx[MAX_FRAME_LEN];
|
||||||
static ui32 uiRxLen;
|
static ui32 uiRxLen;
|
||||||
static ui8 ui8Value;
|
|
||||||
static ui32 ui32Len = 1;
|
|
||||||
|
|
||||||
bool pn532_transceive(const dev_id di, const byte* pbtTx, const ui32 uiTxLen)
|
bool pn53x_transceive(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen)
|
||||||
{
|
{
|
||||||
|
// Reset the receiving buffer
|
||||||
uiRxLen = MAX_FRAME_LEN;
|
uiRxLen = MAX_FRAME_LEN;
|
||||||
return acr122_transceive(di,pbtTx,uiTxLen,abtRx,&uiRxLen);
|
|
||||||
|
// Call the tranceive callback function of the current device
|
||||||
|
if (!pdi->pdc->transceive(pdi->ds,pbtTx,uiTxLen,abtRx,&uiRxLen)) return false;
|
||||||
|
|
||||||
|
// Make sure there was no failure reported by the PN53X chip (0x00 == OK)
|
||||||
|
if (abtRx[0] != 0) return false;
|
||||||
|
|
||||||
|
// Succesful transmission
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn532_set_reg(const dev_id di, ui16 ui16Reg, ui8 ui8Value)
|
byte pn53x_get_reg(const dev_info* pdi, ui16 ui16Reg)
|
||||||
{
|
|
||||||
pncmd_set_register[2] = ui16Reg >> 8;
|
|
||||||
pncmd_set_register[3] = ui16Reg & 0xff;
|
|
||||||
pncmd_set_register[4] = ui8Value;
|
|
||||||
return acr122_transceive(di,pncmd_set_register,5,null,null);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte pn532_get_reg(const dev_id di, ui16 ui16Reg)
|
|
||||||
{
|
{
|
||||||
|
ui8 ui8Value;
|
||||||
|
ui32 uiValueLen = 1;
|
||||||
pncmd_get_register[2] = ui16Reg >> 8;
|
pncmd_get_register[2] = ui16Reg >> 8;
|
||||||
pncmd_get_register[3] = ui16Reg & 0xff;
|
pncmd_get_register[3] = ui16Reg & 0xff;
|
||||||
acr122_transceive(di,pncmd_get_register,4,&ui8Value,&ui32Len);
|
pdi->pdc->transceive(pdi->ds,pncmd_get_register,4,&ui8Value,&uiValueLen);
|
||||||
return ui8Value;
|
return ui8Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn532_set_parameters(const dev_id di, ui8 ui8Value)
|
bool pn53x_set_reg(const dev_info* pdi, ui16 ui16Reg, ui8 ui8SybmolMask, ui8 ui8Value)
|
||||||
{
|
{
|
||||||
pncmd_set_parameters[2] = ui8Value;
|
pncmd_set_register[2] = ui16Reg >> 8;
|
||||||
return acr122_transceive(di,pncmd_set_parameters,3,null,null);
|
pncmd_set_register[3] = ui16Reg & 0xff;
|
||||||
|
pncmd_set_register[4] = ui8Value | (pn53x_get_reg(pdi,ui16Reg) & (~ui8SybmolMask));
|
||||||
|
return pdi->pdc->transceive(pdi->ds,pncmd_set_register,5,null,null);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn532_wrap_frame(const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtFrame, ui32* puiFrameBits)
|
bool pn53x_set_parameters(const dev_info* pdi, ui8 ui8Value)
|
||||||
|
{
|
||||||
|
pncmd_set_parameters[2] = ui8Value;
|
||||||
|
return pdi->pdc->transceive(pdi->ds,pncmd_set_parameters,3,null,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pn53x_set_tx_bits(const dev_info* pdi, ui8 ui8Bits)
|
||||||
|
{
|
||||||
|
// Test if we need to update the transmission bits register setting
|
||||||
|
if (pdi->ui8TxBits != ui8Bits)
|
||||||
|
{
|
||||||
|
// Set the amount of transmission bits in the PN53X chip register
|
||||||
|
if (!pn53x_set_reg(pdi,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,ui8Bits)) return false;
|
||||||
|
|
||||||
|
// Store the new setting
|
||||||
|
((dev_info*)pdi)->ui8TxBits = ui8Bits;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pn53x_wrap_frame(const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtFrame, ui32* puiFrameBits)
|
||||||
{
|
{
|
||||||
byte btFrame;
|
byte btFrame;
|
||||||
byte btData;
|
byte btData;
|
||||||
|
@ -163,7 +199,7 @@ bool pn532_wrap_frame(const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn532_unwrap_frame(const byte* pbtFrame, const ui32 uiFrameBits, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar)
|
bool pn53x_unwrap_frame(const byte* pbtFrame, const ui32 uiFrameBits, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar)
|
||||||
{
|
{
|
||||||
byte btFrame;
|
byte btFrame;
|
||||||
byte btData;
|
byte btData;
|
||||||
|
@ -209,173 +245,327 @@ bool pn532_unwrap_frame(const byte* pbtFrame, const ui32 uiFrameBits, byte* pbtR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_configure_handle_crc(const dev_id di, const bool bEnable)
|
dev_info* nfc_connect()
|
||||||
{
|
{
|
||||||
if (bEnable)
|
dev_info* pdi;
|
||||||
|
ui32 uiDev;
|
||||||
|
byte abtFw[4];
|
||||||
|
ui32 uiFwLen = sizeof(abtFw);
|
||||||
|
|
||||||
|
// Search through the device list for an available device
|
||||||
|
for (uiDev=0; uiDev<sizeof(dev_callbacks_list)/sizeof(dev_callbacks_list[0]); uiDev++)
|
||||||
{
|
{
|
||||||
// Enable automatic receiving/sending of CRC bytes
|
// Try to claim the device
|
||||||
if (!pn532_set_reg(di,REG_CIU_TX_MODE,pn532_get_reg(di,REG_CIU_TX_MODE) | 0x80)) return false;
|
pdi = dev_callbacks_list[uiDev].connect(0);
|
||||||
if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0x80)) return false;
|
|
||||||
} else {
|
// Test if the connection was successful
|
||||||
// Disable automatic receiving/sending of CRC bytes
|
if (pdi != INVALID_DEVICE_INFO)
|
||||||
if (!pn532_set_reg(di,REG_CIU_TX_MODE,pn532_get_reg(di,REG_CIU_TX_MODE) & 0x7f)) return false;
|
{
|
||||||
if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) & 0x7f)) return false;
|
// Great we have claimed a device
|
||||||
|
pdi->pdc = &(dev_callbacks_list[uiDev]);
|
||||||
|
pdi->pdc->transceive(pdi->ds,pncmd_get_register,4,null,null);
|
||||||
|
|
||||||
|
// Try to retrieve PN53x chip revision
|
||||||
|
if (!pdi->pdc->transceive(pdi->ds,pncmd_get_firmware_version,2,abtFw,&uiFwLen))
|
||||||
|
{
|
||||||
|
// Failed to get firmware revision??, whatever...let's disconnect and clean up and return err
|
||||||
|
pdi->pdc->disconnect(pdi);
|
||||||
|
return INVALID_DEVICE_INFO;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
// Add the firmware revision to the device name, PN531 gives 2 bytes info, but PN532 gives 4
|
||||||
|
switch(pdi->ct)
|
||||||
|
{
|
||||||
|
case CT_PN531: sprintf(pdi->acName,"%s - PN531 v%d.%d",pdi->acName,abtFw[0],abtFw[1]); break;
|
||||||
|
case CT_PN532: sprintf(pdi->acName,"%s - PN532 v%d.%d (0x%02x)",pdi->acName,abtFw[1],abtFw[2],abtFw[3]); break;
|
||||||
|
case CT_PN533: sprintf(pdi->acName,"%s - PN533 v%d.%d (0x%02x)",pdi->acName,abtFw[1],abtFw[2],abtFw[3]); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the ending transmission bits register, it is unknown what the last tranmission used there
|
||||||
|
if (!pn53x_set_reg(pdi,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,0x00)) return INVALID_DEVICE_INFO;
|
||||||
|
|
||||||
|
// Make sure we reset the CRC and parity to chip handling.
|
||||||
|
if (!nfc_configure(pdi,DCO_HANDLE_CRC,true)) return INVALID_DEVICE_INFO;
|
||||||
|
if (!nfc_configure(pdi,DCO_HANDLE_PARITY,true)) return INVALID_DEVICE_INFO;
|
||||||
|
|
||||||
|
// Deactivate the CRYPTO1 chiper, it may could cause problems when still active
|
||||||
|
if (!nfc_configure(pdi,DCO_ACTIVATE_CRYPTO1,false)) return INVALID_DEVICE_INFO;
|
||||||
|
|
||||||
|
return pdi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To bad, no reader is ready to be claimed
|
||||||
|
return INVALID_DEVICE_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_configure_handle_parity(const dev_id di, const bool bEnable)
|
void nfc_disconnect(dev_info* pdi)
|
||||||
{
|
{
|
||||||
if (bEnable)
|
// Disconnect, clean up and release the device
|
||||||
{
|
pdi->pdc->disconnect(pdi);
|
||||||
// Handle parity by chip
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_MANUAL_RCV,pn532_get_reg(di,REG_CIU_MANUAL_RCV) & 0xef)) return false;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Parse parity as data bit
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_MANUAL_RCV,pn532_get_reg(di,REG_CIU_MANUAL_RCV) | 0x10)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_configure_field(const dev_id di, const bool bEnable)
|
bool nfc_configure(dev_info* pdi, const dev_config_option dco, const bool bEnable)
|
||||||
{
|
{
|
||||||
|
byte btValue;
|
||||||
|
|
||||||
|
// Make sure we are dealing with a active device
|
||||||
|
if (!pdi->bActive) return false;
|
||||||
|
|
||||||
|
switch(dco)
|
||||||
|
{
|
||||||
|
case DCO_HANDLE_CRC:
|
||||||
|
// Enable or disable automatic receiving/sending of CRC bytes
|
||||||
|
// TX and RX are both represented by the symbol 0x80
|
||||||
|
btValue = (bEnable) ? 0x80 : 0x00;
|
||||||
|
if (!pn53x_set_reg(pdi,REG_CIU_TX_MODE,SYMBOL_TX_CRC_ENABLE,btValue)) return false;
|
||||||
|
if (!pn53x_set_reg(pdi,REG_CIU_RX_MODE,SYMBOL_RX_CRC_ENABLE,btValue)) return false;
|
||||||
|
pdi->bCrc = bEnable;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DCO_HANDLE_PARITY:
|
||||||
|
// Handle parity bit by PN53X chip or parse it as data bit
|
||||||
|
btValue = (bEnable) ? 0x00 : SYMBOL_PARITY_DISABLE;
|
||||||
|
if (!pn53x_set_reg(pdi,REG_CIU_MANUAL_RCV,SYMBOL_PARITY_DISABLE,btValue)) return false;
|
||||||
|
pdi->bPar = bEnable;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DCO_ACTIVATE_FIELD:
|
||||||
pncmd_rf_configure_field[3] = (bEnable) ? 1 : 0;
|
pncmd_rf_configure_field[3] = (bEnable) ? 1 : 0;
|
||||||
return acr122_transceive(di,pncmd_rf_configure_field,4,null,null);
|
if (!pdi->pdc->transceive(pdi->ds,pncmd_rf_configure_field,4,null,null)) return false;
|
||||||
}
|
break;
|
||||||
|
|
||||||
bool nfc_configure_list_passive_infinite(const dev_id di, const bool bEnable)
|
case DCO_ACTIVATE_CRYPTO1:
|
||||||
{
|
btValue = (bEnable) ? SYMBOL_MF_CRYPTO1_ON : 0x00;
|
||||||
|
if (!pn53x_set_reg(pdi,REG_CIU_STATUS2,SYMBOL_MF_CRYPTO1_ON,btValue)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DCO_INFINITE_SELECT:
|
||||||
// Retry format: 0x00 means only 1 try, 0xff means infinite
|
// Retry format: 0x00 means only 1 try, 0xff means infinite
|
||||||
pncmd_rf_configure_retry_select[3] = (bEnable) ? 0xff : 0x00; // MxRtyATR, default: active = 0xff, passive = 0x02
|
pncmd_rf_configure_retry_select[3] = (bEnable) ? 0xff : 0x00; // MxRtyATR, default: active = 0xff, passive = 0x02
|
||||||
pncmd_rf_configure_retry_select[4] = (bEnable) ? 0xff : 0x00; // MxRtyPSL, default: 0x01
|
pncmd_rf_configure_retry_select[4] = (bEnable) ? 0xff : 0x00; // MxRtyPSL, default: 0x01
|
||||||
pncmd_rf_configure_retry_select[5] = (bEnable) ? 0xff : 0x00; // MxRtyPassiveActivation, default: 0xff
|
pncmd_rf_configure_retry_select[5] = (bEnable) ? 0xff : 0x00; // MxRtyPassiveActivation, default: 0xff
|
||||||
return acr122_transceive(di,pncmd_rf_configure_retry_select,6,null,null);
|
if(!pdi->pdc->transceive(pdi->ds,pncmd_rf_configure_retry_select,6,null,null)) return false;
|
||||||
}
|
break;
|
||||||
|
|
||||||
bool nfc_configure_accept_invalid_frames(const dev_id di, const bool bEnable)
|
case DCO_ACCEPT_INVALID_FRAMES:
|
||||||
{
|
btValue = (bEnable) ? SYMBOL_RX_NO_ERROR : 0x00;
|
||||||
if (bEnable)
|
if (!pn53x_set_reg(pdi,REG_CIU_RX_MODE,SYMBOL_RX_NO_ERROR,btValue)) return false;
|
||||||
{
|
break;
|
||||||
// Handle parity by chip
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0x08)) return false;
|
|
||||||
|
|
||||||
} else {
|
case DCO_ACCEPT_MULTIPLE_FRAMES:
|
||||||
// Parse parity as data bit
|
btValue = (bEnable) ? SYMBOL_RX_MULTIPLE : 0x00;
|
||||||
if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0xf7)) return false;
|
if (!pn53x_set_reg(pdi,REG_CIU_RX_MODE,SYMBOL_RX_MULTIPLE,btValue)) return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When we reach this, the configuration is completed and succesful
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_configure_accept_multiple_frames(const dev_id di, const bool bEnable)
|
bool nfc_reader_init(const dev_info* pdi)
|
||||||
{
|
{
|
||||||
if (bEnable)
|
// Make sure we are dealing with a active device
|
||||||
{
|
if (!pdi->bActive) return false;
|
||||||
// Handle parity by chip
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0x04)) return false;
|
|
||||||
|
|
||||||
} else {
|
// Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
|
||||||
// Parse parity as data bit
|
if (!pn53x_set_reg(pdi,REG_CIU_TX_AUTO,SYMBOL_FORCE_100_ASK,0x40)) return false;
|
||||||
if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0xfb)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nfc_reader_init(const dev_id di)
|
// Configure the PN53X to be an Initiator or Reader/Writer
|
||||||
{
|
if (!pn53x_set_reg(pdi,REG_CIU_CONTROL,SYMBOL_INITIATOR,0x10)) return false;
|
||||||
// Try to connect to the NFC reader
|
|
||||||
if (di == INVALID_DEVICE_ID) return INVALID_DEVICE_ID;
|
|
||||||
|
|
||||||
// Let the PN5XX automatically be activated by the RF level detector
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_TX_AUTO,pn532_get_reg(di,REG_CIU_TX_AUTO) | 0x40)) return false;
|
|
||||||
|
|
||||||
// Configure the PN532 to be an Initiator or Reader/Writer
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_CONTROL,pn532_get_reg(di,REG_CIU_CONTROL) | 0x10)) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_reader_list_passive(const dev_id di, const ModulationType mt, const byte* pbtInitData, const ui32 uiInitDataLen, byte* pbtTag, ui32* puiTagLen)
|
bool nfc_reader_select(const dev_info* pdi, const init_modulation im, const byte* pbtInitData, const ui32 uiInitDataLen, tag_info* pti)
|
||||||
{
|
{
|
||||||
|
// Make sure we are dealing with a active device
|
||||||
|
if (!pdi->bActive) return false;
|
||||||
|
|
||||||
pncmd_reader_list_passive[2] = 1; // MaxTg, we only want to select 1 tag at the time
|
pncmd_reader_list_passive[2] = 1; // MaxTg, we only want to select 1 tag at the time
|
||||||
pncmd_reader_list_passive[3] = mt; // BrTy, the type of modulation used for polling a passive tag
|
pncmd_reader_list_passive[3] = im; // BrTy, the type of init modulation used for polling a passive tag
|
||||||
|
|
||||||
// Set the optional initiator data (used for Felica, ISO14443B, Topaz Polling or selecting a specific UID).
|
// Set the optional initiator data (used for Felica, ISO14443B, Topaz Polling or for ISO14443A selecting a specific UID).
|
||||||
if (pbtInitData) memcpy(pncmd_reader_list_passive+4,pbtInitData,uiInitDataLen);
|
if (pbtInitData) memcpy(pncmd_reader_list_passive+4,pbtInitData,uiInitDataLen);
|
||||||
|
|
||||||
// Try to find the available tags
|
// Try to find a tag, call the tranceive callback function of the current device
|
||||||
if (!acr122_transceive(di,pncmd_reader_list_passive,4+uiInitDataLen,pbtTag,puiTagLen)) return false;
|
uiRxLen = MAX_FRAME_LEN;
|
||||||
|
if (!pdi->pdc->transceive(pdi->ds,pncmd_reader_list_passive,4+uiInitDataLen,abtRx,&uiRxLen)) return false;
|
||||||
|
|
||||||
// Return true only if at least one tag has been found, the PN532 returns 0x00 if none was available
|
// Make sure one tag has been found, the PN53X returns 0x00 if none was available
|
||||||
return (pbtTag[0] != 0x00);
|
if (abtRx[0] != 1) return false;
|
||||||
}
|
|
||||||
|
|
||||||
bool nfc_reader_transceive_7bits(const dev_id di, const byte btTx, byte* pbtRx, ui32* puiRxLen)
|
// Is a tag info struct available
|
||||||
{
|
if (pti)
|
||||||
// Set transmission bits to 7
|
{
|
||||||
if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,7)) return false;
|
// Fill the tag info struct with the values corresponding to this init modulation
|
||||||
|
switch(im)
|
||||||
|
{
|
||||||
|
case IM_ISO14443A_106:
|
||||||
|
// Somehow they switched the lower and upper ATQA bytes around for the PN531 chipset
|
||||||
|
if (pdi->ct == CT_PN531)
|
||||||
|
{
|
||||||
|
pti->tia.abtAtqa[0] = abtRx[3];
|
||||||
|
pti->tia.abtAtqa[1] = abtRx[2];
|
||||||
|
} else {
|
||||||
|
memcpy(pti->tia.abtAtqa,abtRx+2,2);
|
||||||
|
}
|
||||||
|
pti->tia.btSak = abtRx[4];
|
||||||
|
// Copy the NFCID1
|
||||||
|
pti->tia.uiUidLen = abtRx[5];
|
||||||
|
memcpy(pti->tia.abtUid,abtRx+6,pti->tia.uiUidLen);
|
||||||
|
// Did we received an optional ATS (Smardcard ATR)
|
||||||
|
if (uiRxLen > pti->tia.uiUidLen+6)
|
||||||
|
{
|
||||||
|
pti->tia.uiAtsLen = abtRx[pti->tia.uiUidLen+6];
|
||||||
|
memcpy(pti->tia.abtAts,abtRx+pti->tia.uiUidLen+6,pti->tia.uiAtsLen);
|
||||||
|
} else {
|
||||||
|
pti->tia.uiAtsLen = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
pncmd_exchange_raw_data[2] = btTx;
|
case IM_FELICA_212:
|
||||||
if (!pn532_transceive(di,pncmd_exchange_raw_data,3)) return false;
|
case IM_FELICA_424:
|
||||||
|
// Store the mandatory info
|
||||||
|
pti->tif.uiLen = abtRx[2];
|
||||||
|
pti->tif.btResCode = abtRx[3];
|
||||||
|
// Copy the NFCID2t
|
||||||
|
memcpy(pti->tif.abtId,abtRx+4,8);
|
||||||
|
// Copy the felica padding
|
||||||
|
memcpy(pti->tif.abtPad,abtRx+12,8);
|
||||||
|
// Test if the System code (SYST_CODE) is available
|
||||||
|
if (uiRxLen > 20)
|
||||||
|
{
|
||||||
|
memcpy(pti->tif.abtSysCode,abtRx+20,2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
case IM_ISO14443B_106:
|
||||||
*puiRxLen = uiRxLen-1;
|
// Store the mandatory info
|
||||||
memcpy(pbtRx,abtRx+1,*puiRxLen);
|
memcpy(pti->tib.abtAtqb,abtRx+2,12);
|
||||||
|
// Ignore the 0x1D byte, and just store the 4 byte id
|
||||||
|
memcpy(pti->tib.abtId,abtRx+15,4);
|
||||||
|
pti->tib.btParam1 = abtRx[19];
|
||||||
|
pti->tib.btParam2 = abtRx[20];
|
||||||
|
pti->tib.btParam3 = abtRx[21];
|
||||||
|
pti->tib.btParam4 = abtRx[22];
|
||||||
|
// Test if the Higher layer (INF) is available
|
||||||
|
if (uiRxLen > 22)
|
||||||
|
{
|
||||||
|
pti->tib.uiInfLen = abtRx[23];
|
||||||
|
memcpy(pti->tib.abtInf,abtRx+24,pti->tib.uiInfLen);
|
||||||
|
} else {
|
||||||
|
pti->tib.uiInfLen = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// Reset transmission bits count
|
case IM_JEWEL_106:
|
||||||
if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,0)) return false;
|
// Store the mandatory info
|
||||||
|
memcpy(pti->tij.btSensRes,abtRx+2,2);
|
||||||
|
memcpy(pti->tij.btId,abtRx+4,4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Should not be possible, so whatever...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_reader_transceive_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen)
|
bool nfc_reader_deselect(const dev_info* pdi)
|
||||||
{
|
{
|
||||||
memcpy(pncmd_exchange_raw_data+2,pbtTx,uiTxLen);
|
return (pdi->pdc->transceive(pdi->ds,pncmd_reader_deselect,3,null,null));
|
||||||
|
|
||||||
if (!pn532_transceive(di,pncmd_exchange_raw_data,2+uiTxLen)) return false;
|
|
||||||
|
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
|
||||||
*puiRxLen = uiRxLen-1;
|
|
||||||
memcpy(pbtRx,abtRx+1,*puiRxLen);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_reader_transceive_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar)
|
bool nfc_reader_transceive_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar)
|
||||||
{
|
{
|
||||||
ui32 uiFrameBits = 0;
|
ui32 uiFrameBits = 0;
|
||||||
|
ui32 uiFrameBytes = 0;
|
||||||
ui8 ui8Bits = 0;
|
ui8 ui8Bits = 0;
|
||||||
|
|
||||||
// Convert data to a frame
|
// Check if we should prepare the parity bits ourself
|
||||||
pn532_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_exchange_raw_data+2,&uiFrameBits);
|
if (!pdi->bPar)
|
||||||
|
{
|
||||||
|
// Convert data with parity to a frame
|
||||||
|
pn53x_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_exchange_raw_data+2,&uiFrameBits);
|
||||||
|
} else {
|
||||||
|
uiFrameBits = uiTxBits;
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve the resting bits
|
// Retrieve the leading bits
|
||||||
ui8Bits = uiFrameBits%8;
|
ui8Bits = uiFrameBits%8;
|
||||||
|
|
||||||
// Set the amount of transmission bits in the pn532 chip register
|
// Get the amount of frame bytes + optional (1 byte if there are leading bits)
|
||||||
if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,ui8Bits)) return false;
|
uiFrameBytes = (uiFrameBits/8)+((ui8Bits==0)?0:1);
|
||||||
|
|
||||||
// Send the frame to the pn532 chip and get the answer
|
// When the parity is handled before us, we just copy the data
|
||||||
// We have to give the amount of bytes + 1 byte if there are leading bits + the two 0xD4,0x42
|
if (pdi->bPar) memcpy(pncmd_exchange_raw_data+2,pbtTx,uiFrameBytes);
|
||||||
if (!pn532_transceive(di,pncmd_exchange_raw_data,(uiFrameBits/8)+((ui8Bits==0)?0:1)+2)) return false;
|
|
||||||
|
|
||||||
// Make sure there was no failure reported by the PN532 chip (0 == OK)
|
// Set the amount of transmission bits in the PN53X chip register
|
||||||
// TODO: is this ACR122 specific?
|
if (!pn53x_set_tx_bits(pdi,ui8Bits)) return false;
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
|
||||||
|
// Send the frame to the PN53X chip and get the answer
|
||||||
|
// We have to give the amount of bytes + (the two command bytes 0xD4, 0x42)
|
||||||
|
if (!pn53x_transceive(pdi,pncmd_exchange_raw_data,uiFrameBytes+2)) return false;
|
||||||
|
|
||||||
// Get the last bit-count that is stored in the received byte
|
// Get the last bit-count that is stored in the received byte
|
||||||
ui8Bits = pn532_get_reg(di,REG_CIU_CONTROL) & 0x07;
|
ui8Bits = pn53x_get_reg(pdi,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS;
|
||||||
|
|
||||||
|
// Recover the real frame length in bits
|
||||||
|
uiFrameBits = ((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits;
|
||||||
|
|
||||||
|
// Ignore the status byte from the PN53X here, it was checked earlier in pn53x_transceive()
|
||||||
|
// Check if we should recover the parity bits ourself
|
||||||
|
if (!pdi->bPar)
|
||||||
|
{
|
||||||
// Unwrap the response frame
|
// Unwrap the response frame
|
||||||
pn532_unwrap_frame(abtRx+1,((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits,pbtRx,puiRxBits,pbtRxPar);
|
pn53x_unwrap_frame(abtRx+1,uiFrameBits,pbtRx,puiRxBits,pbtRxPar);
|
||||||
|
} else {
|
||||||
|
// Save the received bits
|
||||||
|
*puiRxBits = uiFrameBits;
|
||||||
|
// Copy the received bytes
|
||||||
|
memcpy(pbtRx,abtRx+1,uiRxLen-1);
|
||||||
|
}
|
||||||
|
|
||||||
// Everything went successful
|
// Everything went successful
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Block, MifareParam* pmp)
|
bool nfc_reader_transceive_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen)
|
||||||
|
{
|
||||||
|
// We can not just send bytes without parity if while the PN53X expects we handled them
|
||||||
|
if (!pdi->bPar) return false;
|
||||||
|
|
||||||
|
// Copy the data into the command frame
|
||||||
|
memcpy(pncmd_exchange_raw_data+2,pbtTx,uiTxLen);
|
||||||
|
|
||||||
|
// To transfer command frames bytes we can not have any leading bits, reset this to zero
|
||||||
|
if (!pn53x_set_tx_bits(pdi,0)) return false;
|
||||||
|
|
||||||
|
// Send the frame to the PN53X chip and get the answer
|
||||||
|
// We have to give the amount of bytes + (the two command bytes 0xD4, 0x42)
|
||||||
|
if (!pn53x_transceive(pdi,pncmd_exchange_raw_data,uiTxLen+2)) return false;
|
||||||
|
|
||||||
|
// Save the received byte count
|
||||||
|
*puiRxLen = uiRxLen-1;
|
||||||
|
|
||||||
|
// Copy the received bytes
|
||||||
|
memcpy(pbtRx,abtRx+1,*puiRxLen);
|
||||||
|
|
||||||
|
// Everything went successful
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_reader_mifare_cmd(const dev_info* pdi, const mifare_cmd mc, const ui8 ui8Block, mifare_param* pmp)
|
||||||
{
|
{
|
||||||
ui32 uiParamLen;
|
ui32 uiParamLen;
|
||||||
|
|
||||||
|
// Make sure we are dealing with a active device
|
||||||
|
if (!pdi->bActive) return false;
|
||||||
|
|
||||||
pncmd_reader_exchange_data[2] = 0x01; // Use first target/card
|
pncmd_reader_exchange_data[2] = 0x01; // Use first target/card
|
||||||
pncmd_reader_exchange_data[3] = mc; // The MIFARE Classic command
|
pncmd_reader_exchange_data[3] = mc; // The MIFARE Classic command
|
||||||
pncmd_reader_exchange_data[4] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
pncmd_reader_exchange_data[4] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
||||||
|
@ -391,19 +581,19 @@ bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Blo
|
||||||
// Authenticate command
|
// Authenticate command
|
||||||
case MC_AUTH_A:
|
case MC_AUTH_A:
|
||||||
case MC_AUTH_B:
|
case MC_AUTH_B:
|
||||||
uiParamLen = sizeof(MifareParamAuth);
|
uiParamLen = sizeof(mifare_param_auth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Data command
|
// Data command
|
||||||
case MC_WRITE:
|
case MC_WRITE:
|
||||||
uiParamLen = sizeof(MifareParamData);
|
uiParamLen = sizeof(mifare_param_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Value command
|
// Value command
|
||||||
case MC_DECREMENT:
|
case MC_DECREMENT:
|
||||||
case MC_INCREMENT:
|
case MC_INCREMENT:
|
||||||
case MC_TRANSFER:
|
case MC_TRANSFER:
|
||||||
uiParamLen = sizeof(MifareParamValue);
|
uiParamLen = sizeof(mifare_param_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Please fix your code, you never should reach this statement
|
// Please fix your code, you never should reach this statement
|
||||||
|
@ -416,11 +606,7 @@ bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Blo
|
||||||
if (uiParamLen) memcpy(pncmd_reader_exchange_data+5,(byte*)pmp,uiParamLen);
|
if (uiParamLen) memcpy(pncmd_reader_exchange_data+5,(byte*)pmp,uiParamLen);
|
||||||
|
|
||||||
// Fire the mifare command
|
// Fire the mifare command
|
||||||
if (!pn532_transceive(di,pncmd_reader_exchange_data,5+uiParamLen)) return false;
|
if (!pn53x_transceive(pdi,pncmd_reader_exchange_data,5+uiParamLen)) return false;
|
||||||
|
|
||||||
// Make sure there was no failure reported by the PN532 chip (0 == OK)
|
|
||||||
// TODO: is this ACR122 specific?
|
|
||||||
if (abtRx[0] != 0) return false;
|
|
||||||
|
|
||||||
// When we have executed a read command, copy the received bytes into the param
|
// When we have executed a read command, copy the received bytes into the param
|
||||||
if (mc == MC_READ) memcpy(pmp->mpd.abtData,abtRx+1,16);
|
if (mc == MC_READ) memcpy(pmp->mpd.abtData,abtRx+1,16);
|
||||||
|
@ -429,8 +615,14 @@ bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Blo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_target_init(const dev_id di, byte* pbtRx, ui32* puiRxLen)
|
bool nfc_target_init(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits)
|
||||||
{
|
{
|
||||||
|
ui8 ui8Bits;
|
||||||
|
|
||||||
|
// Save the current configuration settings
|
||||||
|
bool bCrc = pdi->bCrc;
|
||||||
|
bool bPar = pdi->bPar;
|
||||||
|
|
||||||
// Clear the target init struct, reset to all zeros
|
// Clear the target init struct, reset to all zeros
|
||||||
memset(pncmd_target_init+2,0x00,37);
|
memset(pncmd_target_init+2,0x00,37);
|
||||||
|
|
||||||
|
@ -446,79 +638,124 @@ bool nfc_target_init(const dev_id di, byte* pbtRx, ui32* puiRxLen)
|
||||||
pncmd_target_init[6] = 0xb0;
|
pncmd_target_init[6] = 0xb0;
|
||||||
pncmd_target_init[7] = 0x0b;
|
pncmd_target_init[7] = 0x0b;
|
||||||
|
|
||||||
// Enable CRC & parity, needed for target_init to work properly
|
// Make sure the CRC & parity are handled by the device, this is needed for target_init to work properly
|
||||||
nfc_configure_handle_crc(di,true);
|
if (!bCrc) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,true);
|
||||||
nfc_configure_handle_parity(di,true);
|
if (!bPar) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,true);
|
||||||
|
|
||||||
// Request the initialization as a target
|
// Let the PN53X be activated by the RF level detector from power down mode
|
||||||
if (!pn532_transceive(di,pncmd_target_init,39)) return false;
|
if (!pn53x_set_reg(pdi,REG_CIU_TX_AUTO, SYMBOL_INITIAL_RF_ON,0x04)) return false;
|
||||||
|
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
// Request the initialization as a target, we can not use pn53x_transceive() because
|
||||||
*puiRxLen = uiRxLen-1;
|
// abtRx[0] contains the emulation mode (baudrate, 14443-4?, DEP and framing type)
|
||||||
memcpy(pbtRx,abtRx+1,*puiRxLen);
|
uiRxLen = MAX_FRAME_LEN;
|
||||||
|
if (!pdi->pdc->transceive(pdi->ds,pncmd_target_init,39,abtRx,&uiRxLen)) return false;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nfc_target_receive_bytes(const dev_id di, byte* pbtRx, ui32* puiRxLen)
|
|
||||||
{
|
|
||||||
if (!pn532_transceive(di,pncmd_target_receive,2)) return false;
|
|
||||||
|
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
|
||||||
*puiRxLen = uiRxLen-1;
|
|
||||||
memcpy(pbtRx,abtRx+1,*puiRxLen);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nfc_target_receive_bits(const dev_id di, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar)
|
|
||||||
{
|
|
||||||
ui8 ui8Bits;
|
|
||||||
|
|
||||||
// Try to gather the received frames from the reader
|
|
||||||
if (!pn532_transceive(di,pncmd_target_receive,2)) return false;
|
|
||||||
|
|
||||||
// Make sure there was no failure reported by the PN532 chip (0 == OK)
|
|
||||||
// TODO: is this ACR122 specific?
|
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
|
||||||
|
|
||||||
// Get the last bit-count that is stored in the received byte
|
// Get the last bit-count that is stored in the received byte
|
||||||
ui8Bits = pn532_get_reg(di,REG_CIU_CONTROL) & 0x07;
|
ui8Bits = pn53x_get_reg(pdi,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS;
|
||||||
|
|
||||||
// Unwrap the response frame
|
// We are sure the parity is handled by the PN53X chip, so we handle it this way
|
||||||
pn532_unwrap_frame(abtRx+1,((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits,pbtRx,puiRxBits,pbtRxPar);
|
*puiRxBits = ((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits;
|
||||||
|
// Copy the received bytes
|
||||||
|
memcpy(pbtRx,abtRx+1,uiRxLen-1);
|
||||||
|
|
||||||
|
// Restore the CRC & parity setting to the original value (if needed)
|
||||||
|
if (!bCrc) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,false);
|
||||||
|
if (!bPar) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_target_send_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen)
|
bool nfc_target_receive_bits(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar)
|
||||||
{
|
{
|
||||||
memcpy(pncmd_target_send+2,pbtTx,uiTxLen);
|
ui32 uiFrameBits;
|
||||||
return acr122_transceive(di,pncmd_target_send,2+uiTxLen,null,null);
|
ui8 ui8Bits;
|
||||||
|
|
||||||
|
// Try to gather a received frame from the reader
|
||||||
|
if (!pn53x_transceive(pdi,pncmd_target_receive,2)) return false;
|
||||||
|
|
||||||
|
// Get the last bit-count that is stored in the received byte
|
||||||
|
ui8Bits = pn53x_get_reg(pdi,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS;
|
||||||
|
|
||||||
|
// Recover the real frame length in bits
|
||||||
|
uiFrameBits = ((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits;
|
||||||
|
|
||||||
|
// Ignore the status byte from the PN53X here, it was checked earlier in pn53x_transceive()
|
||||||
|
// Check if we should recover the parity bits ourself
|
||||||
|
if (!pdi->bPar)
|
||||||
|
{
|
||||||
|
// Unwrap the response frame
|
||||||
|
pn53x_unwrap_frame(abtRx+1,uiFrameBits,pbtRx,puiRxBits,pbtRxPar);
|
||||||
|
} else {
|
||||||
|
// Save the received bits
|
||||||
|
*puiRxBits = uiFrameBits;
|
||||||
|
// Copy the received bytes
|
||||||
|
memcpy(pbtRx,abtRx+1,uiRxLen-1);
|
||||||
|
}
|
||||||
|
// Everyting seems ok, return true
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_target_send_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar)
|
bool nfc_target_receive_bytes(const dev_info* pdi, byte* pbtRx, ui32* puiRxLen)
|
||||||
{
|
{
|
||||||
ui32 uiFrameBits = 0;
|
// Try to gather a received frame from the reader
|
||||||
ui8 ui8Bits = 0;
|
if (!pn53x_transceive(pdi,pncmd_target_receive,2)) return false;
|
||||||
|
|
||||||
// Convert data to a frame
|
// Save the received byte count
|
||||||
pn532_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_target_send+2,&uiFrameBits);
|
*puiRxLen = uiRxLen-1;
|
||||||
|
|
||||||
// Retrieve the resting bits
|
// Copy the received bytes
|
||||||
ui8Bits = uiFrameBits%8;
|
memcpy(pbtRx,abtRx+1,*puiRxLen);
|
||||||
|
|
||||||
// Set the amount of transmission bits in the pn532 chip register
|
|
||||||
if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,ui8Bits)) return false;
|
|
||||||
|
|
||||||
// Try to send the bits to the reader
|
|
||||||
if (!pn532_transceive(di,pncmd_target_send,(uiFrameBits/8)+((ui8Bits==0)?0:1)+2)) return false;
|
|
||||||
|
|
||||||
// Make sure there was no failure reported by the PN532 chip (0 == OK)
|
|
||||||
// TODO: is this ACR122 specific?
|
|
||||||
if (uiRxLen == 1 || abtRx[0] != 0) return false;
|
|
||||||
|
|
||||||
// Everyting seems ok, return true
|
// Everyting seems ok, return true
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nfc_target_send_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar)
|
||||||
|
{
|
||||||
|
ui32 uiFrameBits = 0;
|
||||||
|
ui32 uiFrameBytes = 0;
|
||||||
|
ui8 ui8Bits = 0;
|
||||||
|
|
||||||
|
// Check if we should prepare the parity bits ourself
|
||||||
|
if (!pdi->bPar)
|
||||||
|
{
|
||||||
|
// Convert data with parity to a frame
|
||||||
|
pn53x_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_target_send+2,&uiFrameBits);
|
||||||
|
} else {
|
||||||
|
uiFrameBits = uiTxBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the leading bits
|
||||||
|
ui8Bits = uiFrameBits%8;
|
||||||
|
|
||||||
|
// Get the amount of frame bytes + optional (1 byte if there are leading bits)
|
||||||
|
uiFrameBytes = (uiFrameBits/8)+((ui8Bits==0)?0:1);
|
||||||
|
|
||||||
|
// When the parity is handled before us, we just copy the data
|
||||||
|
if (pdi->bPar) memcpy(pncmd_target_send+2,pbtTx,uiFrameBytes);
|
||||||
|
|
||||||
|
// Set the amount of transmission bits in the PN53X chip register
|
||||||
|
if (!pn53x_set_tx_bits(pdi,ui8Bits)) return false;
|
||||||
|
|
||||||
|
// Try to send the bits to the reader
|
||||||
|
if (!pn53x_transceive(pdi,pncmd_target_send,uiFrameBytes+2)) return false;
|
||||||
|
|
||||||
|
// Everyting seems ok, return true
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool nfc_target_send_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen)
|
||||||
|
{
|
||||||
|
// We can not just send bytes without parity if while the PN53X expects we handled them
|
||||||
|
if (!pdi->bPar) return false;
|
||||||
|
|
||||||
|
// Copy the data into the command frame
|
||||||
|
memcpy(pncmd_target_send+2,pbtTx,uiTxLen);
|
||||||
|
|
||||||
|
// Try to send the bits to the reader
|
||||||
|
if (!pn53x_transceive(pdi,pncmd_target_send,uiTxLen+2)) return false;
|
||||||
|
|
||||||
|
// Everyting seems ok, return true
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
33
libnfc.h
33
libnfc.h
|
@ -24,27 +24,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "bitutils.h"
|
#include "bitutils.h"
|
||||||
#include "acr122.h"
|
#include "devices.h"
|
||||||
|
|
||||||
bool nfc_configure_handle_crc(const dev_id di, const bool bEnable);
|
dev_info* nfc_connect();
|
||||||
bool nfc_configure_handle_parity(const dev_id di, const bool bEnable);
|
void nfc_disconnect(dev_info* pdi);
|
||||||
bool nfc_configure_field(const dev_id di, const bool bEnable);
|
bool nfc_configure(dev_info* pdi, const dev_config_option dco, const bool bEnable);
|
||||||
bool nfc_configure_list_passive_infinite(const dev_id di, const bool bEnable);
|
|
||||||
bool nfc_configure_accept_invalid_frames(const dev_id di, const bool bEnable);
|
|
||||||
bool nfc_configure_accept_multiple_frames(const dev_id di, const bool bEnable);
|
|
||||||
|
|
||||||
bool nfc_reader_init(const dev_id di);
|
bool nfc_reader_init(const dev_info* pdi);
|
||||||
bool nfc_reader_list_passive(const dev_id di, const ModulationType mt, const byte* pbtInitData, const ui32 uiInitDataLen, byte* pbtTag, ui32* puiTagLen);
|
bool nfc_reader_select(const dev_info* pdi, const init_modulation im, const byte* pbtInitData, const ui32 uiInitDataLen, tag_info* pti);
|
||||||
bool nfc_reader_transceive_7bits(const dev_id di, const byte btTx, byte* pbtRx, ui32* puiRxLen);
|
bool nfc_reader_deselect(const dev_info* pdi);
|
||||||
bool nfc_reader_transceive_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
bool nfc_reader_transceive_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar);
|
||||||
bool nfc_reader_transceive_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar);
|
bool nfc_reader_transceive_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
||||||
bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Block, MifareParam* pmp);
|
bool nfc_reader_mifare_cmd(const dev_info* pdi, const mifare_cmd mc, const ui8 ui8Block, mifare_param* pmp);
|
||||||
|
|
||||||
bool nfc_target_init(const dev_id di, byte* pbtRx, ui32* puiRxLen);
|
bool nfc_target_init(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits);
|
||||||
bool nfc_target_receive_bytes(const dev_id di, byte* pbtRx, ui32* puiRxLen);
|
bool nfc_target_receive_bits(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar);
|
||||||
bool nfc_target_receive_bits(const dev_id di, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar);
|
bool nfc_target_receive_bytes(const dev_info* pdi, byte* pbtRx, ui32* puiRxLen);
|
||||||
bool nfc_target_send_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen);
|
bool nfc_target_send_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar);
|
||||||
bool nfc_target_send_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar);
|
bool nfc_target_send_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen);
|
||||||
|
|
||||||
#endif // _LIBNFC_H_
|
#endif // _LIBNFC_H_
|
||||||
|
|
||||||
|
|
85
list.c
85
list.c
|
@ -23,61 +23,74 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "libnfc.h"
|
#include "libnfc.h"
|
||||||
|
|
||||||
static byte abtRecv[MAX_FRAME_LEN];
|
static dev_info* pdi;
|
||||||
static ui32 uiRecvLen;
|
static byte abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
|
||||||
static dev_id di;
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
// Try to open the NFC reader
|
tag_info ti;
|
||||||
di = acr122_connect(0);
|
|
||||||
|
|
||||||
if (di == INVALID_DEVICE_ID)
|
// Try to open the NFC reader
|
||||||
|
pdi = nfc_connect();
|
||||||
|
|
||||||
|
if (pdi == INVALID_DEVICE_INFO)
|
||||||
{
|
{
|
||||||
printf("Error connecting NFC reader\n");
|
printf("Error connecting NFC reader\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
nfc_reader_init(di);
|
nfc_reader_init(pdi);
|
||||||
|
|
||||||
|
// Drop the field for a while
|
||||||
|
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
nfc_configure_list_passive_infinite(di,false);
|
nfc_configure(pdi,DCO_INFINITE_SELECT,false);
|
||||||
|
|
||||||
// Drop the field so the tag will be reset
|
// Configure the CRC and Parity settings
|
||||||
nfc_configure_field(di,false);
|
nfc_configure(pdi,DCO_HANDLE_CRC,true);
|
||||||
|
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||||
|
|
||||||
// Configure the communication channel
|
// Enable field so more power consuming cards can power themselves up
|
||||||
nfc_configure_handle_crc(di,true);
|
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||||
nfc_configure_handle_parity(di,true);
|
|
||||||
|
|
||||||
printf("\nConnected to NFC reader\n\n");
|
printf("\nConnected to NFC reader: %s\n\n",pdi->acName);
|
||||||
|
|
||||||
uiRecvLen = MAX_FRAME_LEN;
|
// Poll for a ISO14443A (MIFARE) tag
|
||||||
if (nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen))
|
if (nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti))
|
||||||
{
|
{
|
||||||
// ISO14443A tag info = ( tag_count[1], tag_nr[1], ATQA[2], SAK[1], uid_len[1], UID[uid_len], ats_len[1], ATS[ats_len-1] )
|
|
||||||
// ATS is optional
|
|
||||||
printf("The following (NFC) ISO14443A tag was found:\n\n");
|
printf("The following (NFC) ISO14443A tag was found:\n\n");
|
||||||
printf("%17s","ATQA (SENS_RES): ");
|
printf(" ATQA (SENS_RES): "); print_hex(ti.tia.abtAtqa,2);
|
||||||
print_hex(abtRecv+2,2);
|
printf(" UID (NFCID%c): ",(ti.tia.abtUid[0]==0x08?'3':'1')); print_hex(ti.tia.abtUid,ti.tia.uiUidLen);
|
||||||
printf("%17s","UID (NFCID1): ");
|
printf(" SAK (SEL_RES): "); print_hex(&ti.tia.btSak,1);
|
||||||
print_hex(abtRecv+6,abtRecv[5]);
|
if (ti.tia.uiAtsLen)
|
||||||
printf("%17s","SAK (SEL_RES): ");
|
|
||||||
print_hex(abtRecv+4,1);
|
|
||||||
if (uiRecvLen > 6+(ui32)abtRecv[5])
|
|
||||||
{
|
{
|
||||||
printf("%17s","ATS (ATR): ");
|
printf(" ATS (ATR): ");
|
||||||
print_hex(abtRecv+6+abtRecv[5]+1,abtRecv[6+abtRecv[5]]-1);
|
print_hex(ti.tia.abtAts,ti.tia.uiAtsLen);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
printf("Error: no tag was found\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: listing the folllowing tags types
|
// Poll for a Felica tag
|
||||||
//
|
if (nfc_reader_select(pdi,IM_FELICA_212,abtFelica,5,&ti) || nfc_reader_select(pdi,IM_FELICA_424,abtFelica,5,&ti))
|
||||||
// MT_FELICA_212
|
{
|
||||||
// MT_FELICA_424
|
printf("The following (NFC) Felica tag was found:\n\n");
|
||||||
// MT_ISO14443B_106
|
printf("%18s","ID (NFCID2): "); print_hex(ti.tif.abtId,8);
|
||||||
// MT_TOPAZ_106
|
printf("%18s","Parameter (PAD): "); print_hex(ti.tif.abtPad,8);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
// Poll for a ISO14443B tag
|
||||||
|
if (nfc_reader_select(pdi,IM_ISO14443B_106,null,null,&ti))
|
||||||
|
{
|
||||||
|
// No test results yet
|
||||||
|
printf("iso14443b\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Poll for a Jewel tag
|
||||||
|
if (nfc_reader_select(pdi,IM_JEWEL_106,null,null,&ti))
|
||||||
|
{
|
||||||
|
// No test results yet
|
||||||
|
printf("jewel\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
nfc_disconnect(pdi);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
36
mifaretag.h
36
mifaretag.h
|
@ -18,37 +18,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MIFARE_TAG_H_
|
#ifndef _LIBNFC_MIFARE_TAG_H_
|
||||||
#define _MIFARE_TAG_H_
|
#define _LIBNFC_MIFARE_TAG_H_
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
typedef struct tagBlockManufacturer {
|
typedef struct {
|
||||||
byte abtUID[4];
|
byte abtUID[4];
|
||||||
byte btBCC;
|
byte btBCC;
|
||||||
byte btUnknown;
|
byte btUnknown;
|
||||||
byte abtATQA[2];
|
byte abtATQA[2];
|
||||||
byte abtUnknown[8];
|
byte abtUnknown[8];
|
||||||
} BlockManufacturer;
|
} mifare_block_manufacturer;
|
||||||
|
|
||||||
typedef struct tagBlockData {
|
typedef struct {
|
||||||
byte abtContent[16];
|
byte abtData[16];
|
||||||
} BlockData;
|
} mifare_block_data;
|
||||||
|
|
||||||
typedef struct tagBlockTrailer {
|
typedef struct {
|
||||||
byte abtKeyA[6];
|
byte abtKeyA[6];
|
||||||
byte abtAccessBits[4];
|
byte abtAccessBits[4];
|
||||||
byte abtKeyB[6];
|
byte abtKeyB[6];
|
||||||
} BlockTrailer;
|
} mifare_block_trailer;
|
||||||
|
|
||||||
typedef union tagBlock {
|
typedef union {
|
||||||
BlockManufacturer bm;
|
mifare_block_manufacturer mbm;
|
||||||
BlockData bd;
|
mifare_block_data mbd;
|
||||||
BlockTrailer bt;
|
mifare_block_trailer mbt;
|
||||||
} Block;
|
} mifare_block;
|
||||||
|
|
||||||
typedef struct tagMifareTag {
|
typedef struct {
|
||||||
Block blContent[256];
|
mifare_block amb[256];
|
||||||
} MifareTag;
|
} mifare_tag;
|
||||||
|
|
||||||
#endif // _MIFARE_TAG_H_
|
#endif // _LIBNFC_MIFARE_TAG_H_
|
||||||
|
|
90
relay.c
90
relay.c
|
@ -23,85 +23,77 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "libnfc.h"
|
#include "libnfc.h"
|
||||||
|
|
||||||
static byte abtReaderRecv[MAX_FRAME_LEN];
|
static byte abtReaderRx[MAX_FRAME_LEN];
|
||||||
static byte abtReaderRecvPar[MAX_FRAME_LEN];
|
static byte abtReaderRxPar[MAX_FRAME_LEN];
|
||||||
static ui32 uiReaderRecvBits;
|
static ui32 uiReaderRxBits;
|
||||||
static byte abtTagRecv[MAX_FRAME_LEN];
|
static byte abtTagRx[MAX_FRAME_LEN];
|
||||||
static byte abtTagRecvPar[MAX_FRAME_LEN];
|
static byte abtTagRxPar[MAX_FRAME_LEN];
|
||||||
static ui32 uiTagRecvBits;
|
static ui32 uiTagRxBits;
|
||||||
static dev_id diReader;
|
static dev_info* pdiReader;
|
||||||
static dev_id diTag;
|
static dev_info* pdiTag;
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC emulator device
|
||||||
diReader = acr122_connect(0);
|
pdiTag = nfc_connect();
|
||||||
if (diReader == INVALID_DEVICE_ID)
|
if (pdiTag == INVALID_DEVICE_INFO)
|
||||||
{
|
{
|
||||||
printf("Error connecting first NFC reader\n");
|
printf("Error connecting NFC emulator device\n");
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
diTag = acr122_connect(1);
|
|
||||||
if (diTag == INVALID_DEVICE_ID)
|
|
||||||
{
|
|
||||||
printf("Error connecting second NFC reader\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("[+] Connected to the both NFC readers\n");
|
printf("[+] Connected to the NFC emulator device\n");
|
||||||
acr122_led_red(diTag,true);
|
printf("[+] Try to break out the auto-simulation, this requires a second reader!\n");
|
||||||
printf("[+] Identified simulated tag by setting the red light\n");
|
printf("[+] To do this, please send any command after the anti-collision\n");
|
||||||
printf("[+] Place both readers on top of each other\n");
|
printf("[+] For example, send a RATS command or use the \"anticol\" tool\n");
|
||||||
printf("[+] Please run 'anticol' tool in a different shell\n");
|
nfc_target_init(pdiTag,abtReaderRx,&uiReaderRxBits);
|
||||||
nfc_target_init(diTag,abtReaderRecv,&uiReaderRecvBits);
|
printf("[+] Configuring emulator settings\n");
|
||||||
nfc_configure_handle_crc(diTag,false);
|
nfc_configure(pdiTag,DCO_HANDLE_CRC,false);
|
||||||
nfc_configure_handle_parity(diTag,false);
|
nfc_configure(pdiTag,DCO_HANDLE_PARITY,false);
|
||||||
nfc_configure_accept_invalid_frames(diTag,true);
|
nfc_configure(pdiTag,DCO_ACCEPT_INVALID_FRAMES,true);
|
||||||
printf("[+] Thank you, the simulated tag is initialized\n");
|
printf("[+] Thank you, the emulated tag is initialized\n");
|
||||||
|
|
||||||
printf("[+] Attaching to first NFC reader \n");
|
// Try to open the NFC reader
|
||||||
// Retry until it becomes ready
|
pdiReader = INVALID_DEVICE_INFO;
|
||||||
while (!nfc_reader_init(diReader))
|
while (pdiReader == INVALID_DEVICE_INFO) pdiReader = nfc_connect();
|
||||||
{
|
printf("[+] Configuring NFC reader settings\n");
|
||||||
acr122_disconnect(diReader);
|
nfc_configure(pdiReader,DCO_HANDLE_CRC,false);
|
||||||
printf("error\n");
|
nfc_configure(pdiReader,DCO_HANDLE_PARITY,false);
|
||||||
diReader = acr122_connect(0);
|
nfc_configure(pdiReader,DCO_ACCEPT_INVALID_FRAMES,true);
|
||||||
}
|
|
||||||
nfc_configure_handle_crc(diReader,false);
|
|
||||||
nfc_configure_handle_parity(diReader,false);
|
|
||||||
nfc_configure_accept_invalid_frames(diReader,true);
|
|
||||||
printf("[+] Done, relaying frames now!\n\n");
|
printf("[+] Done, relaying frames now!\n\n");
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
// Test if we received a frame from the reader
|
// Test if we received a frame from the reader
|
||||||
if (nfc_target_receive_bits(diTag,abtReaderRecv,&uiReaderRecvBits,abtReaderRecvPar))
|
if (nfc_target_receive_bits(pdiTag,abtReaderRx,&uiReaderRxBits,abtReaderRxPar))
|
||||||
{
|
{
|
||||||
// Drop down the field before sending a REQA command and start a new session
|
// Drop down the field before sending a REQA command and start a new session
|
||||||
if (uiReaderRecvBits == 7 && abtReaderRecv[0] == 0x26)
|
if (uiReaderRxBits == 7 && abtReaderRx[0] == 0x26)
|
||||||
{
|
{
|
||||||
// Drop down field for a very short time (tag will reboot)
|
// Drop down field for a very short time (original tag will reboot)
|
||||||
nfc_configure_field(diReader,false);
|
nfc_configure(pdiReader,DCO_ACTIVATE_FIELD,false);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
nfc_configure_field(diReader,true);
|
nfc_configure(pdiReader,DCO_ACTIVATE_FIELD,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the reader frame to the screen
|
// Print the reader frame to the screen
|
||||||
printf("R: ");
|
printf("R: ");
|
||||||
print_hex_par(abtReaderRecv,uiReaderRecvBits,abtReaderRecvPar);
|
print_hex_par(abtReaderRx,uiReaderRxBits,abtReaderRxPar);
|
||||||
|
|
||||||
// Forward the frame to the original tag
|
// Forward the frame to the original tag
|
||||||
if (nfc_reader_transceive_bits(diReader,abtReaderRecv,uiReaderRecvBits,abtReaderRecvPar,abtTagRecv,&uiTagRecvBits,abtTagRecvPar))
|
if (nfc_reader_transceive_bits(pdiReader,abtReaderRx,uiReaderRxBits,abtReaderRxPar,abtTagRx,&uiTagRxBits,abtTagRxPar))
|
||||||
{
|
{
|
||||||
// Redirect the answer back to the reader
|
// Redirect the answer back to the reader
|
||||||
nfc_target_send_bits(diTag,abtTagRecv,uiTagRecvBits,abtTagRecvPar);
|
nfc_target_send_bits(pdiTag,abtTagRx,uiTagRxBits,abtTagRxPar);
|
||||||
|
|
||||||
// Print the tag frame to the screen
|
// Print the tag frame to the screen
|
||||||
printf("T: ");
|
printf("T: ");
|
||||||
print_hex_par(abtTagRecv,uiTagRecvBits,abtTagRecvPar);
|
print_hex_par(abtTagRx,uiTagRxBits,abtTagRxPar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nfc_disconnect(pdiTag);
|
||||||
|
nfc_disconnect(pdiReader);
|
||||||
}
|
}
|
||||||
|
|
71
simulate.c
71
simulate.c
|
@ -24,8 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "libnfc.h"
|
#include "libnfc.h"
|
||||||
|
|
||||||
static byte abtRecv[MAX_FRAME_LEN];
|
static byte abtRecv[MAX_FRAME_LEN];
|
||||||
static ui32 uiRecvLen;
|
static ui32 uiRecvBits;
|
||||||
static dev_id di;
|
static dev_info* pdi;
|
||||||
|
|
||||||
// ISO14443A Anti-Collision response
|
// ISO14443A Anti-Collision response
|
||||||
byte abtAtqa [2] = { 0x04,0x00 };
|
byte abtAtqa [2] = { 0x04,0x00 };
|
||||||
|
@ -34,75 +34,78 @@ byte abtSak [9] = { 0x08,0xb6,0xdd };
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
byte* pbtTx;
|
byte* pbtTx = null;
|
||||||
ui32 uiTxLen;
|
ui32 uiTxBits;
|
||||||
|
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
di = acr122_connect(0);
|
pdi = nfc_connect();
|
||||||
|
|
||||||
if (di == INVALID_DEVICE_ID)
|
if (pdi == INVALID_DEVICE_INFO)
|
||||||
{
|
{
|
||||||
printf("Error connecting NFC reader\n");
|
printf("Error connecting NFC second reader\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("[+] Connected to NFC target\n");
|
printf("[+] Connected to NFC reader: %s\n",pdi->acName);
|
||||||
acr122_led_red(di,true);
|
printf("[+] Try to break out the auto-simulation, this requires a second reader!\n");
|
||||||
printf("[+] Identified simulated tag by setting the red light\n");
|
printf("[+] To do this, please send any command after the anti-collision\n");
|
||||||
printf("[+] First we have to come out auto-simulation\n");
|
printf("[+] For example, send a RATS command or use the \"anticol\" tool\n");
|
||||||
printf("[+] To do this, please send any command after the\n");
|
if (!nfc_target_init(pdi,abtRecv,&uiRecvBits))
|
||||||
printf("[+] anti-collision, for example, the RATS command\n\n");
|
{
|
||||||
nfc_target_init(di,abtRecv,&uiRecvLen);
|
printf("Error: Could not come out of auto-simulation, no command was received\n");
|
||||||
printf("[+] Initiator command: ");
|
return 1;
|
||||||
print_hex(abtRecv,uiRecvLen);
|
}
|
||||||
printf("[+] Configuring communication");
|
printf("[+] Received initiator command: ");
|
||||||
nfc_configure_accept_invalid_frames(di,true);
|
print_hex_bits(abtRecv,uiRecvBits);
|
||||||
nfc_configure_handle_crc(di,false);
|
printf("[+] Configuring communication\n");
|
||||||
printf("[+] Done, the simulated tag is initialized \n");
|
nfc_configure(pdi,DCO_HANDLE_CRC,false);
|
||||||
|
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||||
|
printf("[+] Done, the simulated tag is initialized\n\n");
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
// Test if we received a frame
|
// Test if we received a frame
|
||||||
if (nfc_target_receive_bytes(di,abtRecv,&uiRecvLen))
|
if (nfc_target_receive_bits(pdi,abtRecv,&uiRecvBits,null))
|
||||||
{
|
{
|
||||||
// Prepare the command to send back for the anti-collision request
|
// Prepare the command to send back for the anti-collision request
|
||||||
switch(uiRecvLen)
|
switch(uiRecvBits)
|
||||||
{
|
{
|
||||||
case 1: // Request or Wakeup
|
case 7: // Request or Wakeup
|
||||||
pbtTx = abtAtqa;
|
pbtTx = abtAtqa;
|
||||||
uiTxLen = 2;
|
uiTxBits = 16;
|
||||||
// New anti-collsion session started
|
// New anti-collsion session started
|
||||||
printf("\n");
|
printf("\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // Select All
|
case 16: // Select All
|
||||||
pbtTx = abtUidBcc;
|
pbtTx = abtUidBcc;
|
||||||
uiTxLen = 5;
|
uiTxBits = 40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9: // Select Tag
|
case 72: // Select Tag
|
||||||
pbtTx = abtSak;
|
pbtTx = abtSak;
|
||||||
uiTxLen = 3;
|
uiTxBits = 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // unknown length?
|
default: // unknown length?
|
||||||
uiTxLen = 0;
|
uiTxBits = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("R: ");
|
printf("R: ");
|
||||||
print_hex(abtRecv,uiRecvLen);
|
print_hex_bits(abtRecv,uiRecvBits);
|
||||||
|
|
||||||
// Test if we know how to respond
|
// Test if we know how to respond
|
||||||
if(uiTxLen)
|
if(uiTxBits)
|
||||||
{
|
{
|
||||||
// Send and print the command to the screen
|
// Send and print the command to the screen
|
||||||
nfc_target_send_bytes(di,pbtTx,uiTxLen);
|
nfc_target_send_bits(pdi,pbtTx,uiTxBits,null);
|
||||||
printf("T: ");
|
printf("T: ");
|
||||||
print_hex(pbtTx,uiTxLen);
|
print_hex_bits(pbtTx,uiTxBits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nfc_disconnect(pdi);
|
||||||
}
|
}
|
||||||
|
|
120
types.h
120
types.h
|
@ -23,18 +23,104 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
|
// Compiler directive, set struct alignment to 1 byte for compatibility
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
false = 0x00,
|
false = 0x00,
|
||||||
true = 0x01
|
true = 0x01
|
||||||
}bool;
|
} bool;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MT_ISO14443A_106 = 0x00,
|
CT_PN531 = 0x10,
|
||||||
MT_FELICA_212 = 0x01,
|
CT_PN532 = 0x20,
|
||||||
MT_FELICA_424 = 0x02,
|
CT_PN533 = 0x30,
|
||||||
MT_ISO14443B_106 = 0x03,
|
} chip_type;
|
||||||
MT_TOPAZ_106 = 0x04,
|
|
||||||
}ModulationType;
|
struct dev_callbacks; // Prototype the callback struct
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const struct dev_callbacks* pdc; // Callback functions for handling device specific wrapping
|
||||||
|
char acName[DEVICE_NAME_LENGTH]; // Device name string, including device wrapper firmware
|
||||||
|
chip_type ct; // PN53X chip type, this is useful for some "bug" work-arounds
|
||||||
|
dev_spec ds; // Pointer to the device connection specification
|
||||||
|
bool bActive; // This represents if the PN53X device was initialized succesful
|
||||||
|
bool bCrc; // Is the crc automaticly added, checked and removed from the frames
|
||||||
|
bool bPar; // Does the PN53x chip handles parity bits, all parities are handled as data
|
||||||
|
ui8 ui8TxBits; // The last tx bits setting, we need to reset this if it does not apply anymore
|
||||||
|
} dev_info;
|
||||||
|
|
||||||
|
struct dev_callbacks {
|
||||||
|
const char* acDriver; // Driver description
|
||||||
|
dev_info* (*connect)(const ui32 uiIndex);
|
||||||
|
bool (*transceive)(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
||||||
|
void (*disconnect)(dev_info* pdi);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DCO_HANDLE_CRC = 0x00,
|
||||||
|
DCO_HANDLE_PARITY = 0x01,
|
||||||
|
DCO_ACTIVATE_FIELD = 0x10,
|
||||||
|
DCO_ACTIVATE_CRYPTO1 = 0x11,
|
||||||
|
DCO_INFINITE_SELECT = 0x20,
|
||||||
|
DCO_ACCEPT_INVALID_FRAMES = 0x30,
|
||||||
|
DCO_ACCEPT_MULTIPLE_FRAMES = 0x31
|
||||||
|
}dev_config_option;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// nfc_reader_list_passive - using InListPassiveTarget
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IM_ISO14443A_106 = 0x00,
|
||||||
|
IM_FELICA_212 = 0x01,
|
||||||
|
IM_FELICA_424 = 0x02,
|
||||||
|
IM_ISO14443B_106 = 0x03,
|
||||||
|
IM_JEWEL_106 = 0x04
|
||||||
|
}init_modulation;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte abtAtqa[2];
|
||||||
|
byte btSak;
|
||||||
|
ui32 uiUidLen;
|
||||||
|
byte abtUid[10];
|
||||||
|
ui32 uiAtsLen;
|
||||||
|
byte abtAts[36];
|
||||||
|
}tag_info_iso14443a;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ui32 uiLen;
|
||||||
|
byte btResCode;
|
||||||
|
byte abtId[8];
|
||||||
|
byte abtPad[8];
|
||||||
|
byte abtSysCode[2];
|
||||||
|
}tag_info_felica;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte abtAtqb[12];
|
||||||
|
byte abtId[4];
|
||||||
|
byte btParam1;
|
||||||
|
byte btParam2;
|
||||||
|
byte btParam3;
|
||||||
|
byte btParam4;
|
||||||
|
byte btCid;
|
||||||
|
ui32 uiInfLen;
|
||||||
|
byte abtInf[64];
|
||||||
|
}tag_info_iso14443b;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte btSensRes[2];
|
||||||
|
byte btId[4];
|
||||||
|
}tag_info_jewel;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
tag_info_iso14443a tia;
|
||||||
|
tag_info_felica tif;
|
||||||
|
tag_info_iso14443b tib;
|
||||||
|
tag_info_jewel tij;
|
||||||
|
}tag_info;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// InDataExchange, MIFARE Classic card
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MC_AUTH_A = 0x60,
|
MC_AUTH_A = 0x60,
|
||||||
|
@ -45,25 +131,29 @@ typedef enum {
|
||||||
MC_DECREMENT = 0xC0,
|
MC_DECREMENT = 0xC0,
|
||||||
MC_INCREMENT = 0xC1,
|
MC_INCREMENT = 0xC1,
|
||||||
MC_STORE = 0xC2,
|
MC_STORE = 0xC2,
|
||||||
}MifareCmd;
|
}mifare_cmd;
|
||||||
|
|
||||||
|
// MIFARE Classic command params
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte abtKey[6];
|
byte abtKey[6];
|
||||||
byte abtUid[4];
|
byte abtUid[4];
|
||||||
}MifareParamAuth;
|
}mifare_param_auth;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte abtData[16];
|
byte abtData[16];
|
||||||
}MifareParamData;
|
}mifare_param_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte abtValue[4];
|
byte abtValue[4];
|
||||||
}MifareParamValue;
|
}mifare_param_value;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
MifareParamAuth mpa;
|
mifare_param_auth mpa;
|
||||||
MifareParamData mpd;
|
mifare_param_data mpd;
|
||||||
MifareParamValue mpv;
|
mifare_param_value mpv;
|
||||||
}MifareParam;
|
}mifare_param;
|
||||||
|
|
||||||
|
// Reset struct alignment to default
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
#endif // _LIBNFC_TYPES_H_
|
#endif // _LIBNFC_TYPES_H_
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="anticol"
|
Name="anticol"
|
||||||
ProjectGUID="{71722DBB-4253-4D68-A29C-AA159360FCE4}"
|
ProjectGUID="{71722DBB-4253-4D68-A29C-AA159360FCE4}"
|
||||||
RootNamespace="anticol"
|
RootNamespace="anticol"
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories=""
|
AdditionalIncludeDirectories=""
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
AdditionalIncludeDirectories="../"
|
AdditionalIncludeDirectories="../"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
|
|
@ -1,31 +1,33 @@
|
||||||
EXPORTS
|
EXPORTS
|
||||||
; acr122.c
|
; dev_acr122.h
|
||||||
acr122_connect
|
dev_acr122_connect
|
||||||
acr122_disconnect
|
dev_acr122_disconnect
|
||||||
acr122_transceive
|
dev_acr122_transceive
|
||||||
acr122_firmware
|
dev_acr122_firmware
|
||||||
acr122_led_red
|
dev_acr122_led_red
|
||||||
|
|
||||||
; libnfc.c
|
; dev_pn531.h
|
||||||
nfc_configure_handle_crc
|
dev_pn531_connect
|
||||||
nfc_configure_handle_parity
|
dev_pn531_disconnect
|
||||||
nfc_configure_field
|
dev_pn531_transceive
|
||||||
nfc_configure_list_passive_infinite
|
|
||||||
nfc_configure_accept_invalid_frames
|
; libnfc.h
|
||||||
nfc_configure_accept_multiple_frames
|
nfc_connect
|
||||||
|
nfc_disconnect
|
||||||
|
nfc_configure
|
||||||
nfc_reader_init
|
nfc_reader_init
|
||||||
nfc_reader_transceive_7bits
|
|
||||||
nfc_reader_transceive_bytes
|
|
||||||
nfc_reader_transceive_bits
|
nfc_reader_transceive_bits
|
||||||
nfc_reader_list_passive
|
nfc_reader_transceive_bytes
|
||||||
|
nfc_reader_select
|
||||||
|
nfc_reader_deselect
|
||||||
nfc_reader_mifare_cmd
|
nfc_reader_mifare_cmd
|
||||||
nfc_target_init
|
nfc_target_init
|
||||||
nfc_target_receive_bytes
|
|
||||||
nfc_target_receive_bits
|
nfc_target_receive_bits
|
||||||
nfc_target_send_bytes
|
nfc_target_receive_bytes
|
||||||
nfc_target_send_bits
|
nfc_target_send_bits
|
||||||
|
nfc_target_send_bytes
|
||||||
|
|
||||||
; bitutils.c
|
; bitutils.h
|
||||||
oddparity
|
oddparity
|
||||||
oddparity_bytes
|
oddparity_bytes
|
||||||
mirror
|
mirror
|
||||||
|
@ -36,6 +38,7 @@ EXPORTS
|
||||||
swap_endian64
|
swap_endian64
|
||||||
append_iso14443a_crc
|
append_iso14443a_crc
|
||||||
print_hex
|
print_hex
|
||||||
|
print_hex_bits
|
||||||
print_hex_par
|
print_hex_par
|
||||||
|
|
||||||
|
|
|
@ -10,26 +10,31 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "anticol", "anticol.vcproj",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simulate", "simulate.vcproj", "{9F813EB4-8F43-4E58-8C62-8E43D9AC137D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simulate", "simulate.vcproj", "{9F813EB4-8F43-4E58-8C62-8E43D9AC137D}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{9CC505F9-AE58-4827-8921-A59E7C4839FE} = {9CC505F9-AE58-4827-8921-A59E7C4839FE}
|
||||||
|
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3} = {BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}
|
||||||
|
{ADB1806A-745E-4DB4-9CDC-51658A5061E1} = {ADB1806A-745E-4DB4-9CDC-51658A5061E1}
|
||||||
|
{71722DBB-4253-4D68-A29C-AA159360FCE4} = {71722DBB-4253-4D68-A29C-AA159360FCE4}
|
||||||
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "relay", "relay.vcproj", "{9CC505F9-AE58-4827-8921-A59E7C4839FE}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "relay", "relay.vcproj", "{9CC505F9-AE58-4827-8921-A59E7C4839FE}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3} = {BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}
|
||||||
|
{ADB1806A-745E-4DB4-9CDC-51658A5061E1} = {ADB1806A-745E-4DB4-9CDC-51658A5061E1}
|
||||||
|
{71722DBB-4253-4D68-A29C-AA159360FCE4} = {71722DBB-4253-4D68-A29C-AA159360FCE4}
|
||||||
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list.vcproj", "{ADB1806A-745E-4DB4-9CDC-51658A5061E1}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list", "list.vcproj", "{ADB1806A-745E-4DB4-9CDC-51658A5061E1}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{71722DBB-4253-4D68-A29C-AA159360FCE4} = {71722DBB-4253-4D68-A29C-AA159360FCE4}
|
||||||
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mfread", "mfread.vcproj", "{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mftool", "mftool.vcproj", "{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mfwrite", "mfwrite.vcproj", "{77907F3D-BA6E-4A7F-AF9D-4F60C0A79952}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{ADB1806A-745E-4DB4-9CDC-51658A5061E1} = {ADB1806A-745E-4DB4-9CDC-51658A5061E1}
|
||||||
|
{71722DBB-4253-4D68-A29C-AA159360FCE4} = {71722DBB-4253-4D68-A29C-AA159360FCE4}
|
||||||
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884} = {AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -63,10 +68,6 @@ Global
|
||||||
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}.Debug|Win32.Build.0 = Debug|Win32
|
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}.Release|Win32.ActiveCfg = Release|Win32
|
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}.Release|Win32.Build.0 = Release|Win32
|
{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}.Release|Win32.Build.0 = Release|Win32
|
||||||
{77907F3D-BA6E-4A7F-AF9D-4F60C0A79952}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{77907F3D-BA6E-4A7F-AF9D-4F60C0A79952}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{77907F3D-BA6E-4A7F-AF9D-4F60C0A79952}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{77907F3D-BA6E-4A7F-AF9D-4F60C0A79952}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="libnfc"
|
Name="libnfc"
|
||||||
ProjectGUID="{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}"
|
ProjectGUID="{AAEEDA5F-F86F-452D-BFA3-53B1C00B8884}"
|
||||||
RootNamespace="libnfc"
|
RootNamespace="libnfc"
|
||||||
|
@ -40,7 +40,8 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBNFC_EXPORTS"
|
AdditionalIncludeDirectories="libusb"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBNFC_EXPORTS;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
@ -61,8 +62,9 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="winscard.lib"
|
AdditionalDependencies="winscard.lib libusb.lib"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
|
AdditionalLibraryDirectories="libusb"
|
||||||
ModuleDefinitionFile="libnfc.def"
|
ModuleDefinitionFile="libnfc.def"
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
|
@ -118,7 +120,8 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBNFC_EXPORTS"
|
AdditionalIncludeDirectories="libusb"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBNFC_EXPORTS;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
@ -137,8 +140,9 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="winscard.lib"
|
AdditionalDependencies="winscard.lib libusb.lib"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
|
AdditionalLibraryDirectories="libusb"
|
||||||
ModuleDefinitionFile="libnfc.def"
|
ModuleDefinitionFile="libnfc.def"
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
|
@ -175,14 +179,6 @@
|
||||||
<References>
|
<References>
|
||||||
</References>
|
</References>
|
||||||
<Files>
|
<Files>
|
||||||
<File
|
|
||||||
RelativePath="..\acr122.c"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\acr122.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\bitutils.c"
|
RelativePath="..\bitutils.c"
|
||||||
>
|
>
|
||||||
|
@ -195,6 +191,26 @@
|
||||||
RelativePath="..\defines.h"
|
RelativePath="..\defines.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\dev_acr122.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\dev_acr122.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\dev_pn531.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\dev_pn531.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\devices.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\libnfc.c"
|
RelativePath="..\libnfc.c"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="list"
|
Name="list"
|
||||||
ProjectGUID="{ADB1806A-745E-4DB4-9CDC-51658A5061E1}"
|
ProjectGUID="{ADB1806A-745E-4DB4-9CDC-51658A5061E1}"
|
||||||
RootNamespace="list"
|
RootNamespace="list"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="relay"
|
Name="relay"
|
||||||
ProjectGUID="{9CC505F9-AE58-4827-8921-A59E7C4839FE}"
|
ProjectGUID="{9CC505F9-AE58-4827-8921-A59E7C4839FE}"
|
||||||
RootNamespace="relay"
|
RootNamespace="relay"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8,00"
|
Version="8.00"
|
||||||
Name="simulate"
|
Name="simulate"
|
||||||
ProjectGUID="{9F813EB4-8F43-4E58-8C62-8E43D9AC137D}"
|
ProjectGUID="{9F813EB4-8F43-4E58-8C62-8E43D9AC137D}"
|
||||||
RootNamespace="simulate"
|
RootNamespace="simulate"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue