diff --git a/doc/nrf/nrf.doxyfile.in b/doc/nrf/nrf.doxyfile.in index d80dae2486c1..75863bed8ff4 100644 --- a/doc/nrf/nrf.doxyfile.in +++ b/doc/nrf/nrf.doxyfile.in @@ -2458,6 +2458,7 @@ PREDEFINED = __DOXYGEN__ \ "CONFIG_NRF_MODEM=y" \ "CONFIG_NRF_CLOUD_GATEWAY=y" \ "CONFIG_BT_CENTRAL" \ + "CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR=y" \ "CONFIG_LTE_LC_FUNCTIONAL_MODE_MODULE=y" \ "CONFIG_LTE_LC_NETWORK_REGISTRATION_MODULE=y" \ "CONFIG_LTE_LC_CONNECTION_STATUS_MODULE=y" \ diff --git a/include/nfc/tnep/tag.h b/include/nfc/tnep/tag.h index c11f4b4c88e0..fa3c7436a80d 100644 --- a/include/nfc/tnep/tag.h +++ b/include/nfc/tnep/tag.h @@ -16,9 +16,8 @@ #include #include +#include -/** NFC TNEP library event count. */ -#define NFC_TNEP_EVENTS_NUMBER 2 /** Maximum Service Waiting Time. */ #define NFC_TNEP_TAG_MAX_WAIT_TIME 63 @@ -185,6 +184,9 @@ typedef int (*initial_msg_encode_t)(struct nfc_ndef_msg_desc *msg); int nfc_tnep_tag_tx_msg_buffer_register(uint8_t *tx_buff, uint8_t *tx_swap_buff, size_t len); + +#if defined(CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR) + /** * @brief Start communication using TNEP. * @@ -202,6 +204,7 @@ int nfc_tnep_tag_tx_msg_buffer_register(uint8_t *tx_buff, int nfc_tnep_tag_init(struct k_poll_event *events, uint8_t event_cnt, nfc_payload_set_t payload_set); +#endif /* CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR */ /** * @brief Create the Initial TNEP NDEF message. * @@ -323,6 +326,24 @@ void nfc_tnep_tag_on_selected(void); */ size_t nfc_tnep_tag_svc_count_get(void); +/** + * @brief Internal TNEP Tag initialization. + * + * This function is not intended to be used directly by the application. + * Use @c nfc_tnep_tag_init instead. This function is provided to allow + * custom implementations of @c nfc_tnep_tag_init with non-default signalling. + * + * @param[in] payload_set Function for setting NDEF data for NFC TNEP + * Tag Device. This library use it internally + * to set raw NDEF message to the Tag NDEF file. + * This function is called from atomic context, so + * sleeping or anyhow delaying is not allowed there. + * + * @retval 0 If the operation was successful. + * Otherwise, a (negative) error code is returned. + */ +int nfc_tnep_tag_internal_init(nfc_payload_set_t payload_set); + /** * @} */ diff --git a/include/nfc/tnep/tag_signalling.h b/include/nfc/tnep/tag_signalling.h new file mode 100644 index 000000000000..de9d28a9eb26 --- /dev/null +++ b/include/nfc/tnep/tag_signalling.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef NFC_TNEP_TAG_SIGNALLING_H_ +#define NFC_TNEP_TAG_SIGNALLING_H_ + +#include +#if defined(CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR) +#include +#endif + +enum tnep_event { + TNEP_EVENT_DUMMY, + TNEP_EVENT_MSG_RX_NEW, + TNEP_EVENT_TAG_SELECTED, +}; + +#if defined(CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR) + +/** NFC TNEP library event count. */ +#define NFC_TNEP_EVENTS_NUMBER 2 + +/** @brief Initializes TNEP signalling using Zephyr primitives. + * + * @param[out] events Pointer to array of k_poll_event structures. + * @param[in] event_cnt Number of events in the array. + * Must be @ref NFC_TNEP_EVENTS_NUMBER. + * + * @retval 0 If the operation was successful. + * Otherwise, an (negative) error code is returned. + */ +int nfc_tnep_tag_signalling_init(struct k_poll_event *events, uint8_t event_cnt); + +#endif /* CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR */ + +/** @brief Raises a receive event. + * + * @param event Event to be raised. + */ +void nfc_tnep_tag_signalling_rx_event_raise(enum tnep_event event); + +/** @brief Raises a transmit event. + * + * @param event Event to be raised. + */ +void nfc_tnep_tag_signalling_tx_event_raise(enum tnep_event event); + +/** @brief Checks and clears receive event. + * + * @param event Pointer to store the raised event. + * The value is valid only if the function returns @c true. + * + * @retval true if a receive event was raised. + * @retval false if no receive event was raised. + */ +bool nfc_tnep_tag_signalling_rx_event_check_and_clear(enum tnep_event *event); + +/** @brief Checks and clears transmit event. + * + * @param event Pointer to store the raised event. + * The value is valid only if the function returns @c true. + * + * @retval true if a transmit event was raised. + * @retval false if no transmit event was raised. + */ +bool nfc_tnep_tag_signalling_tx_event_check_and_clear(enum tnep_event *event); + +#endif /* NFC_TNEP_TAG_SIGNALLING_H_ */ diff --git a/subsys/nfc/tnep/CMakeLists.txt b/subsys/nfc/tnep/CMakeLists.txt index e7ef201eee0b..dc997ba86f0c 100644 --- a/subsys/nfc/tnep/CMakeLists.txt +++ b/subsys/nfc/tnep/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_NFC_TNEP_TAG tag.c) +zephyr_library_sources_ifdef(CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR tag_signalling.c) zephyr_library_sources_ifdef(CONFIG_NFC_TNEP_POLLER poller.c) add_subdirectory_ifdef(CONFIG_NFC_TNEP_CH ch) diff --git a/subsys/nfc/tnep/Kconfig b/subsys/nfc/tnep/Kconfig index a5c4538076c6..f7901071e911 100644 --- a/subsys/nfc/tnep/Kconfig +++ b/subsys/nfc/tnep/Kconfig @@ -28,6 +28,15 @@ config NFC_TNEP_RX_MAX_RECORD_SIZE help Set the maximum size of received NDEF Record +choice NFC_TNEP_TAG_SIGNALLING + prompt "NFC TNEP Tag signalling method" + +config NFC_TNEP_TAG_SIGNALLING_ZEPHYR + bool "NFC TNEP Tag signalling using Zephyr primitives" + select POLL + +endchoice + module = NFC_TNEP_TAG module-str = TNEP_TAG source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config" diff --git a/subsys/nfc/tnep/tag.c b/subsys/nfc/tnep/tag.c index b8f30b6ffbaf..e0e87835f21e 100644 --- a/subsys/nfc/tnep/tag.c +++ b/subsys/nfc/tnep/tag.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,15 +15,6 @@ LOG_MODULE_REGISTER(nfc_tnep_tag, CONFIG_NFC_TNEP_TAG_LOG_LEVEL); -#define TNEP_EVENT_RX_IDX 0 -#define TNEP_EVENT_TX_IDX 1 - -enum tnep_event { - TNEP_EVENT_DUMMY, - TNEP_EVENT_MSG_RX_NEW, - TNEP_EVENT_TAG_SELECTED, -}; - enum tnep_state_name { TNEP_STATE_DISABLED, TNEP_STATE_SERVICE_READY, @@ -53,12 +45,6 @@ struct tnep_rx_buffer { size_t len; }; -struct tnep_control { - struct k_poll_event *events; - struct k_poll_signal msg_rx; - struct k_poll_signal msg_tx; -}; - struct tnep_tag { struct nfc_ndef_msg_desc *msg; struct tnep_buffer tx; @@ -72,7 +58,6 @@ struct tnep_tag { uint8_t *current_buff; }; -static struct tnep_control tnep_ctrl; static struct tnep_tag tnep; struct tnep_state { @@ -501,11 +486,10 @@ void nfc_tnep_tag_rx_msg_indicate(const uint8_t *rx_buffer, size_t len) tnep.rx.len = len; tnep.rx.data = rx_buffer; - k_poll_signal_raise(&tnep_ctrl.msg_rx, TNEP_EVENT_MSG_RX_NEW); + nfc_tnep_tag_signalling_rx_event_raise(TNEP_EVENT_MSG_RX_NEW); } -int nfc_tnep_tag_init(struct k_poll_event *events, uint8_t event_cnt, - nfc_payload_set_t payload_set) +int nfc_tnep_tag_internal_init(nfc_payload_set_t payload_set) { extern struct nfc_tnep_tag_service _nfc_tnep_tag_service_list_start[]; @@ -514,21 +498,11 @@ int nfc_tnep_tag_init(struct k_poll_event *events, uint8_t event_cnt, LOG_DBG("TNEP initialization"); - if (!events) { - return -EINVAL; - } - if (!payload_set) { LOG_ERR("No function for NFC payload set provided"); return -EINVAL; } - if (event_cnt != NFC_TNEP_EVENTS_NUMBER) { - LOG_ERR("Invalid k_pool events count. Got %d events, required %d", - event_cnt, NFC_TNEP_EVENTS_NUMBER); - return -EINVAL; - } - if (!atomic_cas(¤t_state, TNEP_STATE_DISABLED, TNEP_STATE_DISABLED)) { LOG_ERR("TNEP already running"); @@ -541,28 +515,30 @@ int nfc_tnep_tag_init(struct k_poll_event *events, uint8_t event_cnt, return -EIO; } - tnep_ctrl.events = events; tnep.current_buff = tnep.tx.data; tnep.data_set = payload_set; tnep.svc_cnt = _nfc_tnep_tag_service_list_end - _nfc_tnep_tag_service_list_start; - LOG_DBG("k_pool signals initialization"); + return 0; +} - k_poll_signal_init(&tnep_ctrl.msg_rx); - k_poll_signal_init(&tnep_ctrl.msg_tx); +#if defined(CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR) - k_poll_event_init(&tnep_ctrl.events[TNEP_EVENT_RX_IDX], - K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, - &tnep_ctrl.msg_rx); +int nfc_tnep_tag_init(struct k_poll_event *events, uint8_t event_cnt, + nfc_payload_set_t payload_set) +{ + int err = nfc_tnep_tag_signalling_init(events, event_cnt); - k_poll_event_init(&tnep_ctrl.events[TNEP_EVENT_TX_IDX], - K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, - &tnep_ctrl.msg_tx); + if (err) { + return err; + } - return 0; + return nfc_tnep_tag_internal_init(payload_set); } +#endif /* CONFIG_NFC_TNEP_TAG_SIGNALLING_ZEPHYR */ + int nfc_tnep_tag_initial_msg_create(size_t max_record_cnt, initial_msg_encode_t msg_encode_cb) { @@ -635,19 +611,16 @@ int nfc_tnep_initial_msg_encode(struct nfc_ndef_msg_desc *msg, void nfc_tnep_tag_process(void) { - /* Check for signals */ - for (size_t i = 0; i < NFC_TNEP_EVENTS_NUMBER; i++) { - if (tnep_ctrl.events[i].state == K_POLL_STATE_SIGNALED) { - enum tnep_event event; + enum tnep_event event = TNEP_EVENT_DUMMY; - event = tnep_ctrl.events[i].signal->result; - - k_poll_signal_reset(tnep_ctrl.events[i].signal); - tnep_ctrl.events[i].state = K_POLL_STATE_NOT_READY; + if (nfc_tnep_tag_signalling_rx_event_check_and_clear(&event)) { + /* Run TNEP State Machine - prepare response */ + tnep_state_machine[atomic_get(¤t_state)].process(event); + } - /* Run TNEP State Machine - prepare response */ - tnep_state_machine[atomic_get(¤t_state)].process(event); - } + if (nfc_tnep_tag_signalling_tx_event_check_and_clear(&event)) { + /* Run TNEP State Machine - prepare response */ + tnep_state_machine[atomic_get(¤t_state)].process(event); } } @@ -707,7 +680,7 @@ int nfc_tnep_tag_tx_msg_no_app_data(void) void nfc_tnep_tag_on_selected(void) { - k_poll_signal_raise(&tnep_ctrl.msg_tx, TNEP_EVENT_TAG_SELECTED); + nfc_tnep_tag_signalling_tx_event_raise(TNEP_EVENT_TAG_SELECTED); } size_t nfc_tnep_tag_svc_count_get(void) diff --git a/subsys/nfc/tnep/tag_signalling.c b/subsys/nfc/tnep/tag_signalling.c new file mode 100644 index 000000000000..3646fd464f50 --- /dev/null +++ b/subsys/nfc/tnep/tag_signalling.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +LOG_MODULE_DECLARE(nfc_tnep_tag, CONFIG_NFC_TNEP_TAG_LOG_LEVEL); + +#define TNEP_EVENT_RX_IDX 0 +#define TNEP_EVENT_TX_IDX 1 + +struct tnep_control { + struct k_poll_event *events; + struct k_poll_signal msg_rx; + struct k_poll_signal msg_tx; +}; + +static struct tnep_control tnep_ctrl; + +int nfc_tnep_tag_signalling_init(struct k_poll_event *events, uint8_t event_cnt) +{ + if (!events) { + return -EINVAL; + } + + if (event_cnt != NFC_TNEP_EVENTS_NUMBER) { + LOG_ERR("Invalid k_pool events count. Got %d events, required %d", + event_cnt, NFC_TNEP_EVENTS_NUMBER); + return -EINVAL; + } + + tnep_ctrl.events = events; + + k_poll_signal_init(&tnep_ctrl.msg_rx); + k_poll_signal_init(&tnep_ctrl.msg_tx); + + k_poll_event_init(&tnep_ctrl.events[TNEP_EVENT_RX_IDX], + K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, + &tnep_ctrl.msg_rx); + + k_poll_event_init(&tnep_ctrl.events[TNEP_EVENT_TX_IDX], + K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, + &tnep_ctrl.msg_tx); + + return 0; +} + +void nfc_tnep_tag_signalling_rx_event_raise(enum tnep_event event) +{ + k_poll_signal_raise(&tnep_ctrl.msg_rx, event); +} + +void nfc_tnep_tag_signalling_tx_event_raise(enum tnep_event event) +{ + k_poll_signal_raise(&tnep_ctrl.msg_tx, event); +} + +static bool event_check_and_clear(int event_idx, enum tnep_event *event) +{ + if (tnep_ctrl.events[event_idx].state == K_POLL_STATE_SIGNALED) { + *event = tnep_ctrl.events[event_idx].signal->result; + + k_poll_signal_reset(tnep_ctrl.events[event_idx].signal); + tnep_ctrl.events[event_idx].state = K_POLL_STATE_NOT_READY; + + return true; + } + + return false; +} + +bool nfc_tnep_tag_signalling_rx_event_check_and_clear(enum tnep_event *event) +{ + return event_check_and_clear(TNEP_EVENT_RX_IDX, event); +} + +bool nfc_tnep_tag_signalling_tx_event_check_and_clear(enum tnep_event *event) +{ + return event_check_and_clear(TNEP_EVENT_TX_IDX, event); +}