From 94474236f1a3480888b393498ecdc7c5613bffb7 Mon Sep 17 00:00:00 2001 From: Kees Bakker Date: Sun, 4 Sep 2022 20:58:27 +0200 Subject: [PATCH] drivers/at: add a function read a response plus the OK There are many modem commands for which you get a line of response followed by an OK. Take for example the AT+CGSN command to get the IMEI of a Ublox G350. >> AT+CGSN << 004999010640000 << OK --- drivers/at/at.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ drivers/include/at.h | 21 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/drivers/at/at.c b/drivers/at/at.c index 958a42971a..b8883cdb6b 100644 --- a/drivers/at/at.c +++ b/drivers/at/at.c @@ -228,6 +228,56 @@ out: return res; } +ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const char *resp_prefix, + char *resp_buf, size_t len, uint32_t timeout) +{ + ssize_t res; + ssize_t res_ok; + char ok_buf[64]; + + at_drain(dev); + + res = at_send_cmd(dev, command, timeout); + if (res) { + goto out; + } + + res = at_readline(dev, resp_buf, len, false, timeout); + if (res == 0) { + /* skip possible empty line */ + res = at_readline(dev, resp_buf, len, false, timeout); + } + + /* Strip the expected prefix */ + if (res > 0 && resp_prefix && *resp_prefix) { + size_t prefix_len = strlen(resp_prefix); + if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) { + size_t remaining_len = strlen(resp_buf) - prefix_len; + /* The one extra byte in the copy is the terminating nul byte */ + memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1); + res -= prefix_len; + } + } + + /* wait for OK */ + if (res >= 0) { + res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout); + if (res_ok == 0) { + /* skip possible empty line */ + res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout); + } + ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1; + if ((len_ok != 0) && (strcmp(ok_buf, CONFIG_AT_RECV_OK) == 0)) { + } + else { + /* Something else then OK */ + res = -1; + } + } +out: + return res; +} + ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf, size_t len, bool keep_eol, uint32_t timeout) { diff --git a/drivers/include/at.h b/drivers/include/at.h index 21f56aa136..90126a0630 100644 --- a/drivers/include/at.h +++ b/drivers/include/at.h @@ -248,6 +248,27 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout */ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout); +/** + * @brief Send AT command, wait for response plus OK + * + * This function sends the supplied @p command, then waits and returns one + * line of response. + * + * A possible empty line will be skipped. + * + * @param[in] dev device to operate on + * @param[in] command command to send + * @param[in] resp_prefix expected prefix in the response + * @param[out] resp_buf buffer for storing response + * @param[in] len len of @p buffer + * @param[in] timeout timeout (in usec) + * + * @returns length of response on success + * @returns <0 on error + */ +ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const char *resp_prefix, + char *resp_buf, size_t len, uint32_t timeout); + /** * @brief Send AT command, wait for multiline response *