diff --git a/examples/nfc-emulate-forum-tag4.c b/examples/nfc-emulate-forum-tag4.c index d9aaa9b..8edcede 100644 --- a/examples/nfc-emulate-forum-tag4.c +++ b/examples/nfc-emulate-forum-tag4.c @@ -55,26 +55,16 @@ #include #include +#include #include "nfc-utils.h" -#define MAX_FRAME_LEN 264 -static byte_t abtRx[MAX_FRAME_LEN]; -static size_t szRx = sizeof(abtRx); static nfc_device_t *pnd; static bool quiet_output = false; #define SYMBOL_PARAM_fISO14443_4_PICC 0x20 -struct nfc_emulator; - -struct nfc_emulator { - nfc_target_t *target; - void *data; - int (*io) (struct nfc_emulator *emulator, const byte_t *data_in, const size_t data_in_len, byte_t *data_out, const size_t data_out_len); -}; - typedef enum { NONE, CC_FILE, NDEF_FILE } file; struct nfcforum_tag4 { @@ -110,11 +100,9 @@ uint8_t nfcforum_capability_container[] = { int nfcforum_tag4_io (struct nfc_emulator *emulator, const byte_t *data_in, const size_t data_in_len, byte_t *data_out, const size_t data_out_len) { - (void) emulator; - (void) data_out_len; int res = 0; - struct nfcforum_tag4 *data = (struct nfcforum_tag4 *)(emulator->data); + struct nfcforum_tag4 *data = (struct nfcforum_tag4 *)(emulator->user_data); // Show transmitted command if (!quiet_output) { @@ -176,7 +164,7 @@ nfcforum_tag4_io (struct nfc_emulator *emulator, const byte_t *data_in, const si break; case ISO7816_READ_BINARY: - if (data_in[LC] + 2 > data_out_len) { + if ((size_t)(data_in[LC] + 2) > data_out_len) { return -ENOSPC; } switch (data->current_file) { @@ -224,37 +212,6 @@ nfcforum_tag4_io (struct nfc_emulator *emulator, const byte_t *data_in, const si return res; } - -bool -nfc_emulate_target (nfc_device_t* pnd, struct nfc_emulator *emulator) -{ - size_t szRx; - byte_t abtTx[MAX_FRAME_LEN]; - int res = 0; - - if (!nfc_target_init (pnd, emulator->target, abtRx, &szRx)) { - nfc_perror (pnd, "nfc_target_init"); - return false; - } - - while (res >= 0) { - res = emulator->io (emulator, abtRx, szRx, abtTx, sizeof (abtTx)); - if (res > 0) { - if (!nfc_target_send_bytes(pnd, abtTx, res)) { - nfc_perror (pnd, "nfc_target_send_bytes"); - return false; - } - } - if (res >= 0) { - if (!nfc_target_receive_bytes(pnd, abtRx, &szRx)) { - nfc_perror (pnd, "nfc_target_receive_bytes"); - return false; - } - } - } - return true; -} - void stop_emulation (int sig) { (void) sig; @@ -264,39 +221,6 @@ void stop_emulation (int sig) exit (EXIT_FAILURE); } -bool send_bytes (const byte_t * pbtTx, const size_t szTx) -{ - // Show transmitted command - if (!quiet_output) { - printf ("Sent data: "); - print_hex (pbtTx, szTx); - } - - // Transmit the command bytes - if (!nfc_target_send_bytes(pnd, pbtTx, szTx)) { - nfc_perror (pnd, "nfc_target_send_bytes"); - exit(EXIT_FAILURE); - } - // Succesful transfer - return true; -} - -bool receive_bytes (void) -{ - if (!nfc_target_receive_bytes(pnd,abtRx,&szRx)) { - nfc_perror (pnd, "nfc_target_receive_bytes"); - exit(EXIT_FAILURE); - } - - // Show received answer - if (!quiet_output) { - printf ("Received data: "); - print_hex (abtRx, szRx); - } - // Succesful transfer - return true; -} - size_t ndef_message_load (char *filename, struct nfcforum_tag4 *tag_data) { @@ -381,10 +305,14 @@ main (int argc, char *argv[]) .current_file = NONE, }; + struct nfc_emulation_state_machine state_machine = { + .io = nfcforum_tag4_io, + }; + struct nfc_emulator emulator = { .target = &nt, - .io = nfcforum_tag4_io, - .data = &nfcforum_tag4_data, + .state_machine = &state_machine, + .user_data = &nfcforum_tag4_data, }; if (argc > 3) { diff --git a/include/nfc/Makefile.am b/include/nfc/Makefile.am index 9e5dc78..9d8bd89 100644 --- a/include/nfc/Makefile.am +++ b/include/nfc/Makefile.am @@ -1,5 +1,8 @@ -nfcinclude_HEADERS = nfc.h nfc-types.h +nfcinclude_HEADERS = \ + nfc.h \ + nfc-emulation.h \ + nfc-types.h nfcincludedir = $(includedir)/nfc EXTRA_DIST = CMakeLists.txt diff --git a/include/nfc/nfc-emulation.h b/include/nfc/nfc-emulation.h new file mode 100644 index 0000000..307d04a --- /dev/null +++ b/include/nfc/nfc-emulation.h @@ -0,0 +1,42 @@ +/*- + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2011, Romuald Conty, Romain Tartière + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +#ifndef __NFC_EMULATION_H__ +#define __NFC_EMULATION_H__ + +#include + +struct nfc_emulator; +struct nfc_emulation_state_machine; + + +struct nfc_emulator { + nfc_target_t *target; + struct nfc_emulation_state_machine *state_machine; + void *user_data; +}; + +struct nfc_emulation_state_machine { + int (*io)(struct nfc_emulator *emulator, const byte_t *data_in, const size_t data_in_len, byte_t *data_out, const size_t data_out_len); + void *state_machine_data; +}; + +int nfc_emulate_target (nfc_device_t* pnd, struct nfc_emulator *emulator); + +#endif /* __NFC_EMULATION_H__ */ diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am index e56f8dd..eae7f76 100644 --- a/libnfc/Makefile.am +++ b/libnfc/Makefile.am @@ -3,9 +3,18 @@ SUBDIRS = chips buses drivers . # set the include path found by configure INCLUDES = $(all_includes) $(LIBNFC_CFLAGS) -noinst_HEADERS = drivers.h mirror-subr.h nfc-internal.h +noinst_HEADERS = \ + drivers.h \ + iso7816.h \ + mirror-subr.h \ + nfc-internal.h lib_LTLIBRARIES = libnfc.la -libnfc_la_SOURCES = nfc.c iso14443-subr.c mirror-subr.c nfc-device.c +libnfc_la_SOURCES = \ + iso14443-subr.c \ + mirror-subr.c \ + nfc.c \ + nfc-device.c \ + nfc-emulation.c libnfc_la_LDFLAGS = -no-undefined -version-info 1:0:0 libnfc_la_CFLAGS = @DRIVERS_CFLAGS@ libnfc_la_LIBADD = \ diff --git a/libnfc/iso7816.h b/libnfc/iso7816.h new file mode 100644 index 0000000..fb80377 --- /dev/null +++ b/libnfc/iso7816.h @@ -0,0 +1,31 @@ +/*- + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2011, Romuald Conty, Romain Tartière + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +#ifndef __ISO7816_H__ +#define __ISO7816_H__ + +#define ISO7816_C_APDU_COMMAND_HEADER_LEN 4 +#define ISO7816_SHORT_APDU_MAX_DATA_LEN 256 +#define ISO7816_SHORT_C_APDU_MAX_OVERHEAD 2 +#define ISO7816_SHORT_R_APDU_RESPONSE_TRAILER_LEN 2 + +#define ISO7816_SHORT_C_APDU_MAX_LEN (ISO7816_C_APDU_COMMAND_HEADER_LEN + ISO7816_SHORT_APDU_MAX_DATA_LEN + ISO7816_SHORT_C_APDU_MAX_OVERHEAD) +#define ISO7816_SHORT_R_APDU_MAX_LEN (ISO7816_SHORT_APDU_MAX_DATA_LEN + ISO7816_SHORT_R_APDU_RESPONSE_TRAILER_LEN) + +#endif diff --git a/libnfc/nfc-emulation.c b/libnfc/nfc-emulation.c new file mode 100644 index 0000000..0686917 --- /dev/null +++ b/libnfc/nfc-emulation.c @@ -0,0 +1,51 @@ +/*- + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2011, Romuald Conty, Romain Tartière + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +#include +#include + +#include "iso7816.h" + +int +nfc_emulate_target (nfc_device_t* pnd, struct nfc_emulator *emulator) +{ + byte_t abtRx[ISO7816_SHORT_R_APDU_MAX_LEN]; + size_t szRx = sizeof(abtRx); + byte_t abtTx[ISO7816_SHORT_C_APDU_MAX_LEN]; + int res = 0; + + if (!nfc_target_init (pnd, emulator->target, abtRx, &szRx)) { + return -1; + } + + while (res >= 0) { + res = emulator->state_machine->io (emulator, abtRx, szRx, abtTx, sizeof (abtTx)); + if (res > 0) { + if (!nfc_target_send_bytes(pnd, abtTx, res)) { + return -1; + } + } + if (res >= 0) { + if (!nfc_target_receive_bytes(pnd, abtRx, &szRx)) { + return -1; + } + } + } + return 0; +}