From 8b4822861be227d46059fffa51500315a55e68fc Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Tue, 27 Feb 2024 09:02:37 +0100 Subject: [PATCH] modem: chat: Add runtime API to modem chat matches Add APIs for changing the contents of modem chat matches safely at runtime. This allows for reusing a single modem_chat_match at the cost of placing the match and its buffers in RAM. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/chat.h | 54 +++++++++++++++++++++++- subsys/modem/modem_chat.c | 54 ++++++++++++++++++++++++ tests/subsys/modem/modem_chat/src/main.c | 28 ++++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index a30a7191ba9..4111c06aca4 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -45,9 +45,9 @@ struct modem_chat_match { /** Size of separators array */ uint8_t separators_size; /** Set if modem chat instance shall use wildcards when matching */ - uint8_t wildcards : 1; + bool wildcards; /** Set if script shall not continue to next step in case of match */ - uint8_t partial : 1; + bool partial; /** Type of modem chat instance */ modem_chat_match_callback callback; }; @@ -376,6 +376,56 @@ void modem_chat_script_abort(struct modem_chat *chat); */ void modem_chat_release(struct modem_chat *chat); +/** + * @brief Initialize modem chat match + * @param chat_match Modem chat match instance + */ +void modem_chat_match_init(struct modem_chat_match *chat_match); + +/** + * @brief Set match of modem chat match instance + * @param chat_match Modem chat match instance + * @param match Match to set + * @note The lifetime of match must match or exceed the lifetime of chat_match + * @warning Always call this API after match is modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_match_set_match(struct modem_chat_match *chat_match, const char *match); + +/** + * @brief Set separators of modem chat match instance + * @param chat_match Modem chat match instance + * @param separators Separators to set + * @note The lifetime of separators must match or exceed the lifetime of chat_match + * @warning Always call this API after separators are modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_match_set_separators(struct modem_chat_match *chat_match, const char *separators); + +/** + * @brief Set modem chat match callback + * @param chat_match Modem chat match instance + * @param callback Callback to set + */ +void modem_chat_match_set_callback(struct modem_chat_match *chat_match, + modem_chat_match_callback callback); + +/** + * @brief Set modem chat match partial flag + * @param chat_match Modem chat match instance + * @param partial Partial flag to set + */ +void modem_chat_match_set_partial(struct modem_chat_match *chat_match, bool partial); + +/** + * @brief Set modem chat match wildcards flag + * @param chat_match Modem chat match instance + * @param enable Enable/disable Wildcards + */ +void modem_chat_match_enable_wildcards(struct modem_chat_match *chat_match, bool enable); + #ifdef __cplusplus } #endif diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index b13334d145b..82742e7329d 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L + #include LOG_MODULE_REGISTER(modem_chat, CONFIG_MODEM_MODULES_LOG_LEVEL); @@ -929,3 +932,54 @@ void modem_chat_release(struct modem_chat *chat) chat->matches[MODEM_CHAT_MATCHES_INDEX_RESPONSE] = NULL; chat->matches_size[MODEM_CHAT_MATCHES_INDEX_RESPONSE] = 0; } + +void modem_chat_match_init(struct modem_chat_match *chat_match) +{ + memset(chat_match, 0, sizeof(struct modem_chat_match)); +} + +int modem_chat_match_set_match(struct modem_chat_match *chat_match, const char *match) +{ + size_t size; + + size = strnlen(match, UINT8_MAX + 1); + + if (size == (UINT8_MAX + 1)) { + return -ENOMEM; + } + + chat_match->match = match; + chat_match->match_size = (uint8_t)size; + return 0; +} + +int modem_chat_match_set_separators(struct modem_chat_match *chat_match, const char *separators) +{ + size_t size; + + size = strnlen(separators, UINT8_MAX + 1); + + if (size == (UINT8_MAX + 1)) { + return -ENOMEM; + } + + chat_match->separators = separators; + chat_match->separators_size = (uint8_t)size; + return 0; +} + +void modem_chat_match_set_callback(struct modem_chat_match *match, + modem_chat_match_callback callback) +{ + match->callback = callback; +} + +void modem_chat_match_set_partial(struct modem_chat_match *match, bool partial) +{ + match->partial = partial; +} + +void modem_chat_match_enable_wildcards(struct modem_chat_match *match, bool enable) +{ + match->wildcards = enable; +} diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index e589c34bb92..532805b65f6 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -676,6 +676,34 @@ ZTEST(modem_chat, test_script_chat_timeout_cmd) "Script sent too many requests"); } +ZTEST(modem_chat, test_runtime_match) +{ + int ret; + struct modem_chat_match test_match; + + modem_chat_match_init(&test_match); + + ret = modem_chat_match_set_match(&test_match, "AT345"); + zassert_ok(ret, "Failed to set match"); + zassert_ok(strcmp(test_match.match, "AT345"), "Failed to set match"); + zassert_equal(test_match.match_size, 5, "Failed to set size of match"); + + ret = modem_chat_match_set_separators(&test_match, ",*"); + zassert_ok(ret, "Failed to set match"); + zassert_ok(strcmp(test_match.separators, ",*"), "Failed to set separators"); + zassert_equal(test_match.separators_size, 2, "Failed to set size of separators"); + + modem_chat_match_set_partial(&test_match, true); + zassert_equal(test_match.partial, true); + modem_chat_match_set_partial(&test_match, false); + zassert_equal(test_match.partial, false); + + modem_chat_match_enable_wildcards(&test_match, true); + zassert_equal(test_match.wildcards, true); + modem_chat_match_enable_wildcards(&test_match, false); + zassert_equal(test_match.wildcards, false); +} + /*************************************************************************************************/ /* Test suite */ /*************************************************************************************************/