examples/nfc-read-forum-tag3: add new example to read a NFC Forum Tag Type 3
This commit is contained in:
parent
57db10acf0
commit
dc842a844c
8 changed files with 344 additions and 9 deletions
|
@ -23,6 +23,7 @@ Improvements:
|
|||
- libnfc: list_targets support for ASK CTS512B (no anticol support yet)
|
||||
- libnfc: nfc_disconnect() now switches NFC device into idle before disconnecting
|
||||
- libnfc: nfc_initiator_poll_target() is now available for all devices
|
||||
- libnfc: implement software polling for non-PN532 equipped device
|
||||
- chips/pn53x: add pn53x_data_new() function to alloc and init pn53x_data structure
|
||||
- chips/pn53x: add some SFR registers description
|
||||
- chips/pn53x: implement WriteBack cache
|
||||
|
@ -50,6 +51,7 @@ Improvements:
|
|||
- examples/nfc-emulate-forum-tag4: this example now fails with ENOTSUPP when used with a non-PN532 chip.
|
||||
- examples/nfc-mfclassic: write special Mifare 1K cards, including Block 0 / UID
|
||||
- examples/nfc-mfsetuid: add a new example to set UID of special Mifare 1K cards
|
||||
- examples/nfc-read-forum-tag3: add new example to read a NFC Forum Tag Type 3
|
||||
- examples/pn53x-tamashell-scripts: minor enhancements
|
||||
- tests/test-dep: add a threaded DEP test to check DEP communication between two local devices
|
||||
- debian: enable all drivers at compile time
|
||||
|
|
8
debian/changelog
vendored
8
debian/changelog
vendored
|
@ -1,3 +1,11 @@
|
|||
libnfc (1.5.1-0) unstable; urgency=low
|
||||
|
||||
* Move nfc-emulate-nfcforum-tag2, nfc-emulate-nfcforum-tag4 and
|
||||
nfc-relay-picc from libnfc-examples to libnfc-bin package.
|
||||
* Add nfc-read-forum-tag3 to libnfc-bin package.
|
||||
|
||||
-- Romuald Conty <rconty@il4p.fr> Mon, 10 Oct 2011 02:42:42 +0100
|
||||
|
||||
libnfc (1.5.0pre1.4-0) unstable; urgency=low
|
||||
|
||||
* All drivers are now enabled under Debian;
|
||||
|
|
6
debian/libnfc-bin.install
vendored
6
debian/libnfc-bin.install
vendored
|
@ -1,6 +1,12 @@
|
|||
debian/tmp/usr/bin/nfc-emulate-forum-tag2
|
||||
debian/tmp/usr/bin/nfc-emulate-forum-tag4
|
||||
debian/tmp/usr/bin/nfc-list
|
||||
debian/tmp/usr/bin/nfc-mfclassic
|
||||
debian/tmp/usr/bin/nfc-mfultralight
|
||||
debian/tmp/usr/bin/nfc-relay-picc
|
||||
debian/tmp/usr/bin/nfc-read-forum-tag3
|
||||
debian/tmp/usr/share/man/man1/nfc-emulate-forum-tag4.1
|
||||
debian/tmp/usr/share/man/man1/nfc-list.1
|
||||
debian/tmp/usr/share/man/man1/nfc-mfclassic.1
|
||||
debian/tmp/usr/share/man/man1/nfc-mfultralight.1
|
||||
debian/tmp/usr/share/man/man1/nfc-relay-picc.1
|
||||
|
|
5
debian/libnfc-examples.install
vendored
5
debian/libnfc-examples.install
vendored
|
@ -1,21 +1,16 @@
|
|||
debian/tmp/usr/bin/nfc-anticol
|
||||
debian/tmp/usr/bin/nfc-dep-initiator
|
||||
debian/tmp/usr/bin/nfc-dep-target
|
||||
debian/tmp/usr/bin/nfc-emulate-forum-tag2
|
||||
debian/tmp/usr/bin/nfc-emulate-forum-tag4
|
||||
debian/tmp/usr/bin/nfc-emulate-tag
|
||||
debian/tmp/usr/bin/nfc-emulate-uid
|
||||
debian/tmp/usr/bin/nfc-mfsetuid
|
||||
debian/tmp/usr/bin/nfc-poll
|
||||
debian/tmp/usr/bin/nfc-relay
|
||||
debian/tmp/usr/bin/nfc-relay-picc
|
||||
debian/tmp/usr/share/man/man1/nfc-anticol.1
|
||||
debian/tmp/usr/share/man/man1/nfc-dep-initiator.1
|
||||
debian/tmp/usr/share/man/man1/nfc-dep-target.1
|
||||
debian/tmp/usr/share/man/man1/nfc-emulate-forum-tag4.1
|
||||
debian/tmp/usr/share/man/man1/nfc-emulate-tag.1
|
||||
debian/tmp/usr/share/man/man1/nfc-emulate-uid.1
|
||||
debian/tmp/usr/share/man/man1/nfc-mfsetuid.1
|
||||
debian/tmp/usr/share/man/man1/nfc-poll.1
|
||||
debian/tmp/usr/share/man/man1/nfc-relay-picc.1
|
||||
debian/tmp/usr/share/man/man1/nfc-relay.1
|
||||
|
|
|
@ -477,6 +477,7 @@ pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData,
|
|||
// response packet. With this hack, the nextly executed function (ie.
|
||||
// pn53x_usb_receive()) will be able to retreive the correct response
|
||||
// packet.
|
||||
// FIXME Sony reader is also affected by this bug but NACK is not supported
|
||||
int res = pn53x_usb_bulk_write (DRIVER_DATA (pnd), (byte_t *)pn53x_nack_frame, sizeof(pn53x_nack_frame), timeout);
|
||||
if (res < 0) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
|
|
|
@ -5,6 +5,7 @@ bin_PROGRAMS = \
|
|||
nfc-mfclassic \
|
||||
nfc-mfsetuid \
|
||||
nfc-mfultralight \
|
||||
nfc-read-forum-tag3 \
|
||||
nfc-relay-picc
|
||||
|
||||
# set the include path found by configure
|
||||
|
@ -29,9 +30,6 @@ nfc_list_SOURCES = nfc-list.c
|
|||
nfc_list_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||
libnfcutils.la
|
||||
|
||||
nfc_mfultralight_SOURCES = nfc-mfultralight.c mifare.c mifare.h
|
||||
nfc_mfultralight_LDADD = $(top_builddir)/libnfc/libnfc.la
|
||||
|
||||
nfc_mfclassic_SOURCES = nfc-mfclassic.c mifare.c mifare.h
|
||||
nfc_mfclassic_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||
libnfcutils.la
|
||||
|
@ -40,9 +38,16 @@ nfc_mfsetuid_SOURCES = nfc-mfsetuid.c
|
|||
nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||
libnfcutils.la
|
||||
|
||||
nfc_mfultralight_SOURCES = nfc-mfultralight.c mifare.c mifare.h
|
||||
nfc_mfultralight_LDADD = $(top_builddir)/libnfc/libnfc.la
|
||||
|
||||
nfc_read_forum_tag3_SOURCES = nfc-read-forum-tag3.c
|
||||
nfc_read_forum_tag3_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||
libnfcutils.la
|
||||
|
||||
nfc_relay_picc_SOURCES = nfc-relay-picc.c
|
||||
nfc_relay_picc_LDADD = $(top_builddir)/libnfc/libnfc.la \
|
||||
libnfcutils.la
|
||||
libnfcutils.la
|
||||
|
||||
dist_man_MANS = \
|
||||
nfc-emulate-forum-tag4.1 \
|
||||
|
|
316
utils/nfc-read-forum-tag3.c
Normal file
316
utils/nfc-read-forum-tag3.c
Normal file
|
@ -0,0 +1,316 @@
|
|||
/*-
|
||||
* Public platform independent Near Field Communication (NFC) library examples
|
||||
*
|
||||
* Copyright (C) 2011, Romuald Conty
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1) Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nfc-read-forum-tag3.c
|
||||
* @brief Extract NDEF Message from a NFC Forum Tag Type 3
|
||||
* This utility extract (if available) the NDEF Message contained in an NFC Forum Tag Type 3.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This implementation was written based on information provided by the
|
||||
* following documents:
|
||||
*
|
||||
* NFC Forum Type 3 Tag Operation Specification
|
||||
* Technical Specification
|
||||
* NFCForum-TS-Type-3-Tag_1.1 - 2011-06-28
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/nfc-emulation.h>
|
||||
|
||||
#include "nfc-utils.h"
|
||||
|
||||
static nfc_device_t *pnd;
|
||||
|
||||
void
|
||||
print_usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s -o FILE\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -o Extract NDEF message if available in FILE\n");
|
||||
}
|
||||
|
||||
void stop_select (int sig)
|
||||
{
|
||||
(void) sig;
|
||||
if (pnd)
|
||||
nfc_abort_command (pnd);
|
||||
else
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
build_felica_frame(const nfc_felica_info_t nfi, const byte_t command, const byte_t* payload, const size_t payload_len, byte_t * frame, size_t * frame_len)
|
||||
{
|
||||
frame[0] = 1 + 1 + 8 + payload_len;
|
||||
*frame_len = frame[0];
|
||||
frame[1] = command;
|
||||
memcpy (frame + 2, nfi.abtId, 8);
|
||||
memcpy (frame + 10, payload, payload_len);
|
||||
}
|
||||
|
||||
#define CHECK 0x06
|
||||
int
|
||||
nfc_forum_tag_type3_check (nfc_device_t *pnd, const nfc_target_t nt, const uint16_t block, const uint8_t block_count, byte_t * data, size_t * data_len)
|
||||
{
|
||||
byte_t payload[1024] = {
|
||||
1, // Services
|
||||
0x0B, 0x00, // NFC Forum Tag Type 3's Service code
|
||||
block_count,
|
||||
0x80, block, // block 0
|
||||
};
|
||||
|
||||
size_t payload_len = 1 + 2 + 1;
|
||||
for (uint8_t b=0; b<block_count; b++) {
|
||||
if (block < 0x100) {
|
||||
payload[payload_len++] = 0x80;
|
||||
payload[payload_len++] = block + b;
|
||||
} else {
|
||||
payload[payload_len++] = 0x00;
|
||||
payload[payload_len++] = (block + b) >> 8;
|
||||
payload[payload_len++] = (block + b) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
byte_t frame[1024];
|
||||
size_t frame_len = sizeof(frame);
|
||||
build_felica_frame (nt.nti.nfi, CHECK, payload, payload_len, frame, &frame_len);
|
||||
|
||||
byte_t res[1024];
|
||||
|
||||
size_t res_len;
|
||||
if (!nfc_initiator_transceive_bytes (pnd, frame, frame_len, res, &res_len, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
const size_t res_overhead = 1 + 1 + 8 + 2; // 1+1+8+2: LEN + CMD + NFCID2 + STATUS
|
||||
if (res_len<res_overhead) {
|
||||
// Not enough data
|
||||
return -1;
|
||||
}
|
||||
uint8_t felica_res_len = res[0];
|
||||
if (res_len != felica_res_len) {
|
||||
// Error while receiving felica frame
|
||||
return -1;
|
||||
}
|
||||
if ((CHECK + 1) != res[1]) {
|
||||
// Command return does not match
|
||||
return -1;
|
||||
}
|
||||
if (0 != memcmp (&res[2], nt.nti.nfi.abtId, 8)) {
|
||||
// NFCID2 does not match
|
||||
return -1;
|
||||
}
|
||||
const byte_t status_flag1 = res[10];
|
||||
const byte_t status_flag2 = res[11];
|
||||
if ((status_flag1) || (status_flag2)) {
|
||||
// Felica card's error
|
||||
fprintf (stderr, "Status bytes: %02x, %02x\n", status_flag1, status_flag2);
|
||||
return -1;
|
||||
}
|
||||
// const uint8_t res_block_count = res[12];
|
||||
*data_len = res_len - res_overhead + 1; // +1 => block count is stored on 1 byte
|
||||
memcpy (data, &res[res_overhead+1], *data_len);
|
||||
return *data_len;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
int ch;
|
||||
char *ndef_output = NULL;
|
||||
while ((ch = getopt (argc, argv, "ho:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
break;
|
||||
case 'o':
|
||||
ndef_output = optarg;
|
||||
break;
|
||||
case '?':
|
||||
if (optopt == 'o')
|
||||
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
|
||||
default:
|
||||
print_usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ndef_output == NULL) {
|
||||
print_usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
FILE* message_stream = NULL;
|
||||
FILE* ndef_stream = NULL;
|
||||
|
||||
if ((strlen (ndef_output) == 1) && (ndef_output[0] == '-')) {
|
||||
message_stream = stderr;
|
||||
ndef_stream = stdout;
|
||||
} else {
|
||||
message_stream = stdout;
|
||||
ndef_stream = fopen(ndef_output, "wb");
|
||||
if (!ndef_stream) {
|
||||
fprintf (stderr, "Could not open file %s.\n", ndef_output);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
pnd = nfc_connect (NULL);
|
||||
|
||||
if (pnd == NULL) {
|
||||
ERR("Unable to connect to NFC device");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf (message_stream, "Connected to NFC device: %s\n", pnd->acName);
|
||||
|
||||
nfc_modulation_t nm = {
|
||||
.nmt = NMT_FELICA,
|
||||
.nbr = NBR_212,
|
||||
};
|
||||
|
||||
signal (SIGINT, stop_select);
|
||||
|
||||
nfc_target_t nt;
|
||||
|
||||
nfc_initiator_init(pnd);
|
||||
fprintf (message_stream, "Place your NFC Forum Tag Type 3 in the field...\n");
|
||||
|
||||
int error = EXIT_SUCCESS;
|
||||
// Polling payload (SENSF_REQ) must be present (see NFC Digital Protol)
|
||||
const byte_t *pbtSensfReq = (byte_t*)"\x00\xff\xff\x01\x00";
|
||||
if (!nfc_initiator_select_passive_target(pnd, nm, pbtSensfReq, 5, &nt)) {
|
||||
nfc_perror (pnd, "nfc_initiator_select_passive_target");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Check if System Code equals 0x12fc
|
||||
const byte_t abtNfcForumSysCode[] = { 0x12, 0xfc };
|
||||
if (0 != memcmp (nt.nti.nfi.abtSysCode, abtNfcForumSysCode, 2)) {
|
||||
// Retry with special polling
|
||||
const byte_t *pbtSensfReqNfcForum = (byte_t*)"\x00\x12\xfc\x01\x00";
|
||||
if (!nfc_initiator_select_passive_target(pnd, nm, pbtSensfReqNfcForum, 5, &nt)) {
|
||||
nfc_perror (pnd, "nfc_initiator_select_passive_target");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
// Check again if System Code equals 0x12fc
|
||||
if (0 != memcmp (nt.nti.nfi.abtSysCode, abtNfcForumSysCode, 2)) {
|
||||
fprintf (stderr, "Tag is not NFC Forum Tag Type 3 compiliant.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
//print_nfc_felica_info(nt.nti.nfi, true);
|
||||
|
||||
if (!nfc_configure (pnd, NDO_EASY_FRAMING, false) || !nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||
nfc_perror (pnd, "nfc_configure");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
byte_t data[1024];
|
||||
size_t data_len = sizeof(data);
|
||||
int len;
|
||||
|
||||
if (0 >= (len = nfc_forum_tag_type3_check (pnd, nt, 0, 1, data, &data_len))) {
|
||||
nfc_perror (pnd, "nfc_forum_tag_type3_check");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
const int ndef_major_version = (data[0] & 0xf0) >> 4;
|
||||
const int ndef_minor_version = (data[0] & 0x0f);
|
||||
fprintf (message_stream, "NDEF Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version);
|
||||
|
||||
const int available_block_count = (data[3] << 8) + data[4];
|
||||
fprintf (message_stream, "NFC Forum Tag Type 3 capacity: %d bytes\n", available_block_count * 16);
|
||||
|
||||
uint32_t ndef_data_len = (data[11] << 16) + (data[12] << 8) + data[13];
|
||||
fprintf (message_stream, "NDEF data lenght: %d bytes\n", ndef_data_len);
|
||||
|
||||
uint16_t ndef_calculated_checksum = 0;
|
||||
for (size_t n=0; n<14; n++)
|
||||
ndef_calculated_checksum += data[n];
|
||||
|
||||
const uint16_t ndef_checksum = (data[14] << 8) + data[15];
|
||||
if (ndef_calculated_checksum != ndef_checksum) {
|
||||
fprintf (stderr, "NDEF CRC does not match with calculated one\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!ndef_data_len) {
|
||||
fprintf (stderr, "Empty NFC Forum Tag Type 3\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
const uint8_t block_max_per_check = data[1];
|
||||
const uint16_t block_count_to_check = (ndef_data_len / 16) + 1;
|
||||
|
||||
data_len = 0;
|
||||
for (uint16_t b=0; b<(block_count_to_check/block_max_per_check); b+=block_max_per_check) {
|
||||
size_t len = sizeof(data) - data_len;
|
||||
if(!nfc_forum_tag_type3_check (pnd, nt, 1+b, MIN(block_max_per_check, (block_count_to_check-(b*block_max_per_check))), data + data_len, &len)) {
|
||||
nfc_perror (pnd, "nfc_forum_tag_type3_check");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
data_len += len;
|
||||
}
|
||||
if (fwrite (data, 1, data_len, ndef_stream) != data_len) {
|
||||
fprintf (stderr, "Could not write to file.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
fclose (ndef_stream);
|
||||
if (pnd) {
|
||||
nfc_disconnect (pnd);
|
||||
}
|
||||
exit (error);
|
||||
}
|
|
@ -537,6 +537,8 @@ print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
|
|||
print_hex (nfi.abtId, 8);
|
||||
printf (" Parameter (PAD): ");
|
||||
print_hex (nfi.abtPad, 8);
|
||||
printf (" System Code (SC): ");
|
||||
print_hex (nfi.abtSysCode, 2);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue