From c7c91bb762a69cd844ef610f6bb2e3313e317265 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 21 Nov 2024 08:11:15 +0100 Subject: [PATCH] feat(modem): Add support for pausing netif Closes https://github.com/espressif/esp-protocols/issues/699 --- components/esp_modem/Kconfig | 7 ++++++ .../modem_console/main/modem_console_main.cpp | 11 ++++++++++ .../include/cxx_include/esp_modem_dce.hpp | 22 +++++++++++++++++++ .../include/cxx_include/esp_modem_dte.hpp | 12 +++++----- .../include/cxx_include/esp_modem_netif.hpp | 12 +++++++++- components/esp_modem/src/esp_modem_netif.cpp | 14 ++++++++++++ components/esp_modem/src/esp_modem_uart.cpp | 11 ++++++++-- 7 files changed, 80 insertions(+), 9 deletions(-) diff --git a/components/esp_modem/Kconfig b/components/esp_modem/Kconfig index f4b47fb787..4e6fb88332 100644 --- a/components/esp_modem/Kconfig +++ b/components/esp_modem/Kconfig @@ -85,4 +85,11 @@ menu "esp-modem" mode more robust for some devices (e.g. Quectel), but might cause trouble for other devices (e.g. SIMCOM). + config ESP_MODEM_ADD_DEBUG_LOGS + bool "Add UART Tx/Rx logs" + default n + help + If enabled, the library dumps all transmitted and received data. + This option is only used for debugging. + endmenu diff --git a/components/esp_modem/examples/modem_console/main/modem_console_main.cpp b/components/esp_modem/examples/modem_console/main/modem_console_main.cpp index 42dd6a76e4..3c3184f5a9 100644 --- a/components/esp_modem/examples/modem_console/main/modem_console_main.cpp +++ b/components/esp_modem/examples/modem_console/main/modem_console_main.cpp @@ -385,6 +385,17 @@ extern "C" void app_main(void) return 0; }); #endif + const ConsoleCommand PauseNetwork("pause_net", "toggle network pause", no_args, [&](ConsoleCommand * c) { + static int cnt = 0; + if (++cnt % 2) { + ESP_LOGI(TAG, "Pausing netif"); + dce->pause_netif(true); + } else { + ESP_LOGI(TAG, "Unpausing netif"); + dce->pause_netif(false); + } + return 0; + }); const struct SetApn { SetApn(): apn(STR1, nullptr, nullptr, "", "APN (Access Point Name)") {} diff --git a/components/esp_modem/include/cxx_include/esp_modem_dce.hpp b/components/esp_modem/include/cxx_include/esp_modem_dce.hpp index 045783c2dd..c323277319 100644 --- a/components/esp_modem/include/cxx_include/esp_modem_dce.hpp +++ b/components/esp_modem/include/cxx_include/esp_modem_dce.hpp @@ -103,6 +103,28 @@ class DCE_T { } #endif + /** + * @brief Pauses/Unpauses network temporarily + * @param do_pause true to pause, false to unpause + * @param force true to ignore command failures and continue + * @return command_result of the underlying commands + */ + command_result pause_netif(bool do_pause, bool force = false) + { + command_result result; + if (do_pause) { + netif.pause(); + dte->set_command_callbacks(); + result = device->set_command_mode(); + } else { + result = device->resume_data_mode(); + if (result == command_result::OK || force) { + netif.unpause(); + } + } + return result; + } + protected: std::shared_ptr dte; std::shared_ptr device; diff --git a/components/esp_modem/include/cxx_include/esp_modem_dte.hpp b/components/esp_modem/include/cxx_include/esp_modem_dte.hpp index f576e75f1e..4e11515ff7 100644 --- a/components/esp_modem/include/cxx_include/esp_modem_dte.hpp +++ b/components/esp_modem/include/cxx_include/esp_modem_dte.hpp @@ -145,6 +145,12 @@ class DTE : public CommandableIf { */ bool recover(); + /** + * @brief Set internal command callbacks to the underlying terminal. + * Here we capture command replies to be processed by supplied command callbacks in struct command_cb. + */ + void set_command_callbacks(); + protected: /** * @brief Allows for locking the DTE @@ -204,12 +210,6 @@ class DTE : public CommandableIf { } inflatable; #endif // CONFIG_ESP_MODEM_USE_INFLATABLE_BUFFER_IF_NEEDED - /** - * @brief Set internal command callbacks to the underlying terminal. - * Here we capture command replies to be processed by supplied command callbacks in struct command_cb. - */ - void set_command_callbacks(); - /** * @brief This abstracts command callback processing and implements its locking, signaling of completion and timeouts. */ diff --git a/components/esp_modem/include/cxx_include/esp_modem_netif.hpp b/components/esp_modem/include/cxx_include/esp_modem_netif.hpp index 05a6a1ddf5..13bdc78684 100644 --- a/components/esp_modem/include/cxx_include/esp_modem_netif.hpp +++ b/components/esp_modem/include/cxx_include/esp_modem_netif.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,6 +54,16 @@ class Netif { */ void stop(); + /** + * @brief Pause the network interface + */ + void pause(); + + /** + * @brief Resume the network interface + */ + void unpause(); + void receive(uint8_t *data, size_t len); private: diff --git a/components/esp_modem/src/esp_modem_netif.cpp b/components/esp_modem/src/esp_modem_netif.cpp index fbb75c37c5..cf3684621e 100644 --- a/components/esp_modem/src/esp_modem_netif.cpp +++ b/components/esp_modem/src/esp_modem_netif.cpp @@ -99,6 +99,20 @@ void Netif::stop() signal.clear(PPP_STARTED); } +void Netif::unpause() +{ + ppp_dte->set_read_cb([this](uint8_t *data, size_t len) -> bool { + receive(data, len); + return true; + }); + signal.set(PPP_STARTED); +} + +void Netif::pause() +{ + signal.clear(PPP_STARTED); +} + Netif::~Netif() { if (signal.is_any(PPP_STARTED)) { diff --git a/components/esp_modem/src/esp_modem_uart.cpp b/components/esp_modem/src/esp_modem_uart.cpp index 945fb2889f..ebe31fdded 100644 --- a/components/esp_modem/src/esp_modem_uart.cpp +++ b/components/esp_modem/src/esp_modem_uart.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -176,13 +176,20 @@ int UartTerminal::read(uint8_t *data, size_t len) uart_get_buffered_data_len(uart.port, &length); length = std::min(len, length); if (length > 0) { - return uart_read_bytes(uart.port, data, length, portMAX_DELAY); + int read_len = uart_read_bytes(uart.port, data, length, portMAX_DELAY); +#if CONFIG_ESP_MODEM_ADD_DEBUG_LOGS + ESP_LOG_BUFFER_HEXDUMP("uart-rx", data, read_len, ESP_LOG_DEBUG); +#endif + return read_len; } return 0; } int UartTerminal::write(uint8_t *data, size_t len) { +#if CONFIG_ESP_MODEM_ADD_DEBUG_LOGS + ESP_LOG_BUFFER_HEXDUMP("uart-tx", data, len, ESP_LOG_DEBUG); +#endif return uart_write_bytes_compat(uart.port, data, len); }