diff --git a/drivers/at/at.c b/drivers/at/at.c index b521b7f3d4..d02a095cba 100644 --- a/drivers/at/at.c +++ b/drivers/at/at.c @@ -80,6 +80,34 @@ ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout) return (resp_pos - bytes); } +int at_recv_bytes_until_string(at_dev_t *dev, const char *string, + char *bytes, size_t *bytes_len, uint32_t timeout) +{ + size_t len = 0; + char *_string = (char *)string; + + while (*_string && len < *bytes_len) { + int res; + char c; + if ((res = isrpipe_read_timeout(&dev->isrpipe, &c, 1, timeout)) == 1) { + if (AT_PRINT_INCOMING) { + print(&c, 1); + } + if (c == *_string) { + _string++; + } + bytes[len] = c; + len++; + } + else { + *bytes_len = len; + return res; + } + } + *bytes_len = len; + return 0; +} + int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout) { size_t cmdlen = strlen(command); diff --git a/drivers/include/at.h b/drivers/include/at.h index 42132ed5ff..8e26bd5381 100644 --- a/drivers/include/at.h +++ b/drivers/include/at.h @@ -211,6 +211,25 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf */ int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout); +/** + * @brief Receives bytes into @p bytes buffer until the string pattern + * @p string is received or the buffer is full. + * + * @param[in] dev device to operate on + * @param[in] string string pattern to expect + * @param[out] bytes buffer to store received bytes + * @param[in, out] bytes_len pointer to the maximum number of bytes to + * receive. On return stores the amount of received + * bytes. + * @param[in] timeout timeout (in usec) of inactivity to finish read + * + * @returns 0 on success + * @returns <0 on error + */ +int at_recv_bytes_until_string(at_dev_t *dev, const char *string, + char *bytes, size_t *bytes_len, + uint32_t timeout); + /** * @brief Send raw bytes to a device * diff --git a/tests/driver_at/README.md b/tests/driver_at/README.md index 0edc0e2d17..3262e69076 100644 --- a/tests/driver_at/README.md +++ b/tests/driver_at/README.md @@ -1,6 +1,6 @@ Expected result =============== -You should be presented with a RIOT shell that privides commands to +You should be presented with a RIOT shell that provides commands to initialize an UART and send AT commands to an AT module. Background diff --git a/tests/driver_at/main.c b/tests/driver_at/main.c index 2c0d62644a..bcb433d7aa 100644 --- a/tests/driver_at/main.c +++ b/tests/driver_at/main.c @@ -134,6 +134,34 @@ static int send_recv_bytes(int argc, char **argv) return 0; } +static int send_recv_bytes_until_string(int argc, char **argv) +{ + char buffer[128]; + size_t len = sizeof(buffer); + + memset(buffer, 0, sizeof(buffer)); + + if (argc < 3) { + printf("Usage: %s \n", argv[0]); + return 1; + } + + sprintf(buffer, "%s%s", argv[1], AT_SEND_EOL); + at_send_bytes(&at_dev, buffer, strlen(buffer)); + memset(buffer, 0, sizeof(buffer)); + + int res = at_recv_bytes_until_string(&at_dev, argv[2], buffer, &len, + 10 * US_PER_SEC); + + if (res) { + puts("Error"); + return 1; + } + + printf("Response (len=%d): %s\n", (int)len, buffer); + return 0; +} + static int drain(int argc, char **argv) { (void)argc; @@ -258,6 +286,8 @@ static const shell_command_t shell_commands[] = { { "send_ok", "Send a command and wait OK", send_ok }, { "send_lines", "Send a command and wait lines", send_lines }, { "send_recv_bytes", "Send a command and wait response as raw bytes", send_recv_bytes }, + { "send_recv_until_string", "Send a command and receive response until " + "the expected pattern arrives", send_recv_bytes_until_string }, { "drain", "Drain AT device", drain }, { "power_on", "Power on AT device", power_on }, { "power_off", "Power off AT device", power_off },