From b4ef1a3a5d02c6396f801e44d5e358b58ecc5a65 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 4 Jun 2012 00:16:28 +0000 Subject: [PATCH] New nfc_initiator_init_secure_element() function to set SAM as wired card (only relevant with a PN532 SAM-equipped) --- NEWS | 7 +++++-- examples/pn53x-sam.c | 26 ++++++++++++++++---------- include/nfc/nfc.h | 3 ++- libnfc/Makefile.am | 2 +- libnfc/chips/pn53x.c | 25 ++++++++++++++++++++----- libnfc/chips/pn53x.h | 27 +++++++++++++++------------ libnfc/drivers/acr122_pcsc.c | 5 +++-- libnfc/drivers/acr122_usb.c | 1 + libnfc/drivers/acr122s.c | 1 + libnfc/drivers/arygon.c | 1 + libnfc/drivers/pn532_uart.c | 3 ++- libnfc/drivers/pn53x_usb.c | 1 + libnfc/nfc-internal.h | 1 + libnfc/nfc.c | 15 +++++++++++++++ 14 files changed, 84 insertions(+), 34 deletions(-) diff --git a/NEWS b/NEWS index 4e275b9..2fd4f75 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,8 @@ New in TBD: API Changes: * Types - - New NFC_ESOFT error to handle software errors (allocations, pie creation, etc.) + - New NFC_ESOFT error to handle software errors (allocations, pipe + creation, etc.) * Functions - New enum-to-string converter functions str_nfc_modulation_type() and @@ -15,7 +16,9 @@ API Changes: - New nfc_initiator_target_is_present() to test is the previously selected target is available in the field - nfc_initiator_transceive_bytes() returns NFC_ETGRELEASED when AUTH - command failed on a Mifare Classic. + command failed on a Mifare Classic + - New nfc_initiator_init_secure_element() to initiate a connection with + secure element (Only supported with a PN532 with SAM equipped) New in 1.6.0-rc1: diff --git a/examples/pn53x-sam.c b/examples/pn53x-sam.c index f7e1f2a..ea09372 100644 --- a/examples/pn53x-sam.c +++ b/examples/pn53x-sam.c @@ -118,25 +118,23 @@ main(int argc, const char *argv[]) pn532_sam_mode mode = iMode; // Connect with the SAM - // FIXME: Its a private pn53x function - if (pn53x_SAMConfiguration(pnd, mode, 0) < 0) { - nfc_perror(pnd, "pn53x_SAMConfiguration"); - goto error; - } switch (mode) { case PSM_VIRTUAL_CARD: { + // FIXME Its a private pn53x function + if (pn532_SAMConfiguration(pnd, mode, 0) < 0) { + nfc_perror(pnd, "pn53x_SAMConfiguration"); + goto error; + } printf("Now the SAM is readable for 1 minute from an external reader.\n"); wait_one_minute(); } break; case PSM_WIRED_CARD: { - nfc_target nt; - // Set opened NFC device to initiator mode - if (nfc_initiator_init(pnd) < 0) { - nfc_perror(pnd, "nfc_initiator_init"); + if (nfc_initiator_init_secure_element(pnd) < 0) { + nfc_perror(pnd, "nfc_initiator_init_secure_element"); goto error; } @@ -150,6 +148,8 @@ main(int argc, const char *argv[]) .nmt = NMT_ISO14443A, .nbr = NBR_106, }; + nfc_target nt; + int res; if ((res = nfc_initiator_select_passive_target(pnd, nmSAM, NULL, 0, &nt)) < 0) { nfc_perror(pnd, "nfc_initiator_select_passive_target"); @@ -168,6 +168,11 @@ main(int argc, const char *argv[]) break; case PSM_DUAL_CARD: { + // FIXME Its a private pn53x function + if (pn532_SAMConfiguration(pnd, mode, 0) < 0) { + nfc_perror(pnd, "pn53x_SAMConfiguration"); + goto error; + } uint8_t abtRx[MAX_FRAME_LEN]; nfc_target nt = { @@ -195,13 +200,14 @@ main(int argc, const char *argv[]) } break; case PSM_NORMAL: + // This should not happend... nothing to do. break; } ret = EXIT_SUCCESS; error: // Disconnect from the SAM - pn53x_SAMConfiguration(pnd, PSM_NORMAL, 0); + pn532_SAMConfiguration(pnd, PSM_NORMAL, -1); // Close NFC device nfc_close(pnd); diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 04eed54..75aad63 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -2,7 +2,7 @@ * Public platform independent Near Field Communication (NFC) library * * Copyright (C) 2009, Roel Verdult - * Copyright (C) 2010, Romuald Conty + * Copyright (C) 2010-2012, Romuald Conty * * 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 @@ -76,6 +76,7 @@ extern "C" { /* NFC initiator: act as "reader" */ NFC_EXPORT int nfc_initiator_init(nfc_device *pnd); + NFC_EXPORT int nfc_initiator_init_secure_element(nfc_device *pnd); NFC_EXPORT int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt); NFC_EXPORT int nfc_initiator_list_passive_targets(nfc_device *pnd, const nfc_modulation nm, nfc_target ant[], const size_t szTargets); NFC_EXPORT int nfc_initiator_poll_target(nfc_device *pnd, const nfc_modulation *pnmTargetTypes, const size_t szTargetTypes, const uint8_t uiPollNr, const uint8_t uiPeriod, nfc_target *pnt); diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am index f916633..7fcb62c 100644 --- a/libnfc/Makefile.am +++ b/libnfc/Makefile.am @@ -18,7 +18,7 @@ libnfc_la_SOURCES = \ nfc-emulation.c \ nfc-internal.c -libnfc_la_LDFLAGS = -no-undefined -version-info 3:0:0 -export-symbols-regex '^nfc_|^iso14443a_|^str_nfc_|pn53x_transceive|pn53x_SAMConfiguration' +libnfc_la_LDFLAGS = -no-undefined -version-info 3:0:0 -export-symbols-regex '^nfc_|^iso14443a_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration' libnfc_la_CFLAGS = @DRIVERS_CFLAGS@ libnfc_la_LIBADD = \ $(top_builddir)/libnfc/chips/libnfcchips.la \ diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 9647e3e..32f791d 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -998,7 +998,12 @@ int pn53x_initiator_init(struct nfc_device *pnd) { pn53x_reset_settings(pnd); - int res = 0; + int res; + if (CHIP_DATA(pnd)->sam_mode != PSM_NORMAL) { + if ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, -1)) < 0) { + return res; + } + } // Configure the PN53X to be an Initiator or Reader/Writer if ((res = pn53x_write_register(pnd, PN53X_REG_CIU_Control, SYMBOL_INITIATOR, 0x10)) < 0) @@ -1008,6 +1013,12 @@ pn53x_initiator_init(struct nfc_device *pnd) return NFC_SUCCESS; } +int +pn532_initiator_init_secure_element(struct nfc_device *pnd) +{ + return pn532_SAMConfiguration(pnd, PSM_WIRED_CARD, -1); +} + static int pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, const nfc_modulation nm, @@ -2204,9 +2215,9 @@ pn53x_SetParameters(struct nfc_device *pnd, const uint8_t ui8Value) } int -pn53x_SAMConfiguration(struct nfc_device *pnd, const pn532_sam_mode ui8Mode, int timeout) +pn532_SAMConfiguration(struct nfc_device *pnd, const pn532_sam_mode sam_mode, int timeout) { - uint8_t abtCmd[] = { SAMConfiguration, ui8Mode, 0x00, 0x00 }; + uint8_t abtCmd[] = { SAMConfiguration, sam_mode, 0x00, 0x00 }; size_t szCmd = sizeof(abtCmd); if (CHIP_DATA(pnd)->type != PN532) { @@ -2215,12 +2226,12 @@ pn53x_SAMConfiguration(struct nfc_device *pnd, const pn532_sam_mode ui8Mode, int return pnd->last_error; } - switch (ui8Mode) { + switch (sam_mode) { case PSM_NORMAL: // Normal mode + case PSM_WIRED_CARD: // Wired card mode szCmd = 2; break; case PSM_VIRTUAL_CARD: // Virtual card mode - case PSM_WIRED_CARD: // Wired card mode case PSM_DUAL_CARD: // Dual card mode // TODO Implement timeout handling szCmd = 3; @@ -2229,6 +2240,7 @@ pn53x_SAMConfiguration(struct nfc_device *pnd, const pn532_sam_mode ui8Mode, int pnd->last_error = NFC_EINVARG; return pnd->last_error; } + CHIP_DATA(pnd)->sam_mode = sam_mode; return (pn53x_transceive(pnd, abtCmd, szCmd, NULL, 0, timeout)); } @@ -3080,6 +3092,9 @@ pn53x_data_new(struct nfc_device *pnd, const struct pn53x_io *io) // Set current target to NULL CHIP_DATA(pnd)->current_target = NULL; + // Set current sam_mode to normal mode + CHIP_DATA(pnd)->sam_mode = PSM_NORMAL; + // WriteBack cache is clean CHIP_DATA(pnd)->wb_trigged = false; memset(CHIP_DATA(pnd)->wb_mask, 0x00, PN53X_CACHE_REGISTER_SIZE); diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index ff26634..fcee233 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -134,6 +134,17 @@ typedef enum { TARGET, } pn53x_operating_mode; +/** + * @enum pn532_sam_mode + * @brief PN532 SAM mode enumeration + */ +typedef enum { + PSM_NORMAL = 0x01, + PSM_VIRTUAL_CARD = 0x02, + PSM_WIRED_CARD = 0x03, + PSM_DUAL_CARD = 0x04 +} pn532_sam_mode; + /** * @internal * @struct pn53x_io @@ -165,6 +176,8 @@ struct pn53x_data { pn53x_operating_mode operating_mode; /** Current emulated target */ nfc_target *current_target; + /** Current sam mode (only applicable for PN532) */ + pn532_sam_mode sam_mode; /** PN53x I/O functions stored in struct */ const struct pn53x_io *io; /** Last status byte returned by PN53x */ @@ -262,17 +275,6 @@ typedef enum { PTT_DEP_ACTIVE_424 = 0x82, } pn53x_target_type; -/** - * @enum pn532_sam_mode - * @brief PN53x SAM mode enumeration - */ -typedef enum { - PSM_NORMAL = 0x01, - PSM_VIRTUAL_CARD = 0x02, - PSM_WIRED_CARD = 0x03, - PSM_DUAL_CARD = 0x04 -} pn532_sam_mode; - /** * @enum pn53x_target_mode * @brief PN53x target mode enumeration @@ -312,6 +314,7 @@ int pn53x_idle(struct nfc_device *pnd); // NFC device as Initiator functions int pn53x_initiator_init(struct nfc_device *pnd); +int pn532_initiator_init_secure_element(struct nfc_device *pnd); int pn53x_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, @@ -348,7 +351,7 @@ const char *pn53x_strerror(const struct nfc_device *pnd); // C wrappers for PN53x commands int pn53x_SetParameters(struct nfc_device *pnd, const uint8_t ui8Value); -int pn53x_SAMConfiguration(struct nfc_device *pnd, const pn532_sam_mode mode, int timeout); +int pn532_SAMConfiguration(struct nfc_device *pnd, const pn532_sam_mode mode, int timeout); int pn53x_PowerDown(struct nfc_device *pnd); int pn53x_InListPassiveTarget(struct nfc_device *pnd, const pn53x_modulation pmInitModulation, const uint8_t szMaxTargets, const uint8_t *pbtInitiatorData, diff --git a/libnfc/drivers/acr122_pcsc.c b/libnfc/drivers/acr122_pcsc.c index 71362ac..29c652b 100644 --- a/libnfc/drivers/acr122_pcsc.c +++ b/libnfc/drivers/acr122_pcsc.c @@ -494,6 +494,7 @@ const struct nfc_driver acr122_pcsc_driver = { .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support .initiator_select_passive_target = pn53x_initiator_select_passive_target, .initiator_poll_target = pn53x_initiator_poll_target, .initiator_select_dep_target = pn53x_initiator_select_dep_target, @@ -516,7 +517,7 @@ const struct nfc_driver acr122_pcsc_driver = { .get_supported_baud_rate = pn53x_get_supported_baud_rate, .device_get_information_about = pn53x_get_information_about, - .abort_command = NULL, // FIXME: abort is not supported in this driver - .idle = NULL, // FIXME: idle is not supported in this driver + .abort_command = NULL, // Abort is not supported in this driver + .idle = NULL, // Idle is not supported in this driver }; diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index f6d554e..1efe079 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -751,6 +751,7 @@ const struct nfc_driver acr122_usb_driver = { .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support .initiator_select_passive_target = pn53x_initiator_select_passive_target, .initiator_poll_target = pn53x_initiator_poll_target, .initiator_select_dep_target = pn53x_initiator_select_dep_target, diff --git a/libnfc/drivers/acr122s.c b/libnfc/drivers/acr122s.c index 1a4b3fe..368217e 100644 --- a/libnfc/drivers/acr122s.c +++ b/libnfc/drivers/acr122s.c @@ -730,6 +730,7 @@ const struct nfc_driver acr122s_driver = { .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support .initiator_select_passive_target = pn53x_initiator_select_passive_target, .initiator_poll_target = pn53x_initiator_poll_target, .initiator_select_dep_target = pn53x_initiator_select_dep_target, diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 8231c6e..43f3ab7 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -571,6 +571,7 @@ const struct nfc_driver arygon_driver = { .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support .initiator_select_passive_target = pn53x_initiator_select_passive_target, .initiator_poll_target = pn53x_initiator_poll_target, .initiator_select_dep_target = pn53x_initiator_select_dep_target, diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 8f6924b..b7f1302 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -301,7 +301,7 @@ pn532_uart_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, in return res; } // According to PN532 application note, C106 appendix: to go out Low Vbat mode and enter in normal mode we need to send a SAMConfiguration command - if ((res = pn53x_SAMConfiguration(pnd, 0x01, 1000)) < 0) { + if ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000)) < 0) { return res; } } @@ -513,6 +513,7 @@ const struct nfc_driver pn532_uart_driver = { .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, + .initiator_init_secure_element = pn532_initiator_init_secure_element, // No secure-element support .initiator_select_passive_target = pn53x_initiator_select_passive_target, .initiator_poll_target = pn53x_initiator_poll_target, .initiator_select_dep_target = pn53x_initiator_select_dep_target, diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 5e64f66..fcf774f 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -764,6 +764,7 @@ const struct nfc_driver pn53x_usb_driver = { .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support .initiator_select_passive_target = pn53x_initiator_select_passive_target, .initiator_poll_target = pn53x_initiator_poll_target, .initiator_select_dep_target = pn53x_initiator_select_dep_target, diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h index df095c4..298ec56 100644 --- a/libnfc/nfc-internal.h +++ b/libnfc/nfc-internal.h @@ -141,6 +141,7 @@ struct nfc_driver { const char *(*strerror)(const struct nfc_device *pnd); int (*initiator_init)(struct nfc_device *pnd); + int (*initiator_init_secure_element)(struct nfc_device *pnd); int (*initiator_select_passive_target)(struct nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt); int (*initiator_poll_target)(struct nfc_device *pnd, const nfc_modulation *pnmModulations, const size_t szModulations, const uint8_t uiPollNr, const uint8_t btPeriod, nfc_target *pnt); int (*initiator_select_dep_target)(struct nfc_device *pnd, const nfc_dep_mode ndm, const nfc_baud_rate nbr, const nfc_dep_info *pndiInitiator, nfc_target *pnt, const int timeout); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 05bb6b7..4895abe 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -370,6 +370,21 @@ nfc_initiator_init(nfc_device *pnd) HAL(initiator_init, pnd); } +/** @ingroup initiator + * @brief Initialize NFC device as initiator with its secure element initiator (reader) + * @return Returns 0 on success, otherwise returns libnfc's error code (negative value) + * @param pnd \a nfc_device struct pointer that represent currently used device + * + * The NFC device is configured to function as secure element reader. + * After initialization it can be used to communicate with the secure element. + * @note RF field is desactvated in order to some power + */ +int +nfc_initiator_init_secure_element(nfc_device *pnd) +{ + HAL(initiator_init_secure_element, pnd); +} + /** @ingroup initiator * @brief Select a passive or emulated tag * @return Returns selected passive target count on success, otherwise returns libnfc's error code (negative value)