diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index fd399515e629e7bb92905734624d1d2417a6936a..1621e5ec5dd804a3802a10d50de89efc80782364 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -22,8 +22,10 @@ ifneq (,$(filter apa102,$(USEMODULE))) endif ifneq (,$(filter at,$(USEMODULE))) - USEMODULE += fmt - USEMODULE += xtimer + FEATURES_REQUIRED += periph_uart + USEMODULE += fmt + USEMODULE += xtimer + USEMODULE += isrpipe endif ifneq (,$(filter at30tse75x,$(USEMODULE))) diff --git a/drivers/at/at.c b/drivers/at/at.c index aff5757dca3c3eaacb1997b4e58bd56a536d1921..ec37d8e8bc407ee3cbc7b53563ac89102b226610 100644 --- a/drivers/at/at.c +++ b/drivers/at/at.c @@ -32,19 +32,18 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t return 0; } -int at_expect_bytes(at_dev_t *dev, const char *bytes, size_t len, uint32_t timeout) +int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout) { - while (len) { + while (*bytes) { char c; int res; if ((res = isrpipe_read_timeout(&dev->isrpipe, &c, 1, timeout)) == 1) { if (AT_PRINT_INCOMING) { print(&c, 1); } - if (!(c == *bytes++)) { + if (c != *bytes++) { return -1; } - len--; } else { return res; @@ -61,17 +60,19 @@ void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len) int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout) { - unsigned cmdlen = strlen(command); + size_t cmdlen = strlen(command); uart_write(dev->uart, (const uint8_t *)command, cmdlen); - uart_write(dev->uart, (const uint8_t *)AT_END_OF_LINE, sizeof(AT_END_OF_LINE) - 1); + uart_write(dev->uart, (const uint8_t *)AT_SEND_EOL, AT_SEND_EOL_LEN); - if (at_expect_bytes(dev, command, cmdlen, timeout)) { - return -1; - } + if (AT_SEND_ECHO) { + if (at_expect_bytes(dev, command, timeout)) { + return -1; + } - if (at_expect_bytes(dev, AT_END_OF_LINE "\r\n", sizeof(AT_END_OF_LINE) + 1, timeout)) { - return -2; + if (at_expect_bytes(dev, AT_SEND_EOL "\r\n", timeout)) { + return -2; + } } return 0; @@ -83,13 +84,15 @@ void at_drain(at_dev_t *dev) int res; do { + /* consider no character within 10ms "drained" */ res = isrpipe_read_timeout(&dev->isrpipe, _tmp, sizeof(_tmp), 10000U); } while (res > 0); } -ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, 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) { - ssize_t res = -1; + ssize_t res; at_drain(dev); @@ -108,9 +111,10 @@ out: return res; } -ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout) +ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, + char *resp_buf, size_t len, uint32_t timeout) { - ssize_t res = -1; + ssize_t res; size_t bytes_left = len - 1; char *pos = resp_buf; @@ -123,7 +127,7 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf goto out; } - while(1) { + while (1) { res = at_readline(dev, pos, bytes_left, timeout); if (res == 0) { continue; @@ -140,6 +144,9 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf else if (strncmp(pos, "+CME ERROR:", 11) == 0) { return -1; } + else if (strncmp(pos, "+CMS ERROR:", 11) == 0) { + return -1; + } else { pos += res; if (bytes_left) { @@ -167,17 +174,17 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout at_drain(dev); uart_write(dev->uart, (const uint8_t *)command, cmdlen); - uart_write(dev->uart, (const uint8_t *)AT_END_OF_LINE, sizeof(AT_END_OF_LINE) - 1); + uart_write(dev->uart, (const uint8_t *)AT_SEND_EOL, AT_SEND_EOL_LEN); - if (at_expect_bytes(dev, command, cmdlen, timeout)) { + if (at_expect_bytes(dev, command, timeout)) { return -1; } - if (at_expect_bytes(dev, AT_END_OF_LINE "\n", sizeof(AT_END_OF_LINE), timeout)) { + if (at_expect_bytes(dev, AT_SEND_EOL "\n", timeout)) { return -2; } - if (at_expect_bytes(dev, ">", 1, timeout)) { + if (at_expect_bytes(dev, ">", timeout)) { return -3; } @@ -187,7 +194,7 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout) { int res; - char resp_buf[32]; + char resp_buf[64]; res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf), timeout); if (res > 0) { @@ -234,5 +241,8 @@ ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, uint32_t timeout) } out: + if (res < 0) { + *resp_buf = '\0'; + } return res; } diff --git a/drivers/include/at.h b/drivers/include/at.h index 37608bee9d428db62b8bd0c8969dd08c46b00a67..53e2991ab381b4eb143f61cc7a25406b860c47dd 100644 --- a/drivers/include/at.h +++ b/drivers/include/at.h @@ -16,7 +16,7 @@ * Most functions compare the bytes echoed by the device with what they * intended to send, and bail out if there's no match. * - * Furthermore, the library tries to copy with difficulties regarding different + * Furthermore, the library tries to cope with difficulties regarding different * line endings. It usually sends "<command><CR>", but expects * "<command>\LF\CR" as echo. * @@ -34,6 +34,7 @@ #define AT_H #include <stdint.h> +#include <unistd.h> #include "isrpipe.h" #include "periph/uart.h" @@ -42,11 +43,19 @@ extern "C" { #endif -#ifndef AT_END_OF_LINE +#ifndef AT_SEND_EOL /** End of line character to send after the AT command */ -#define AT_END_OF_LINE "\r" +#define AT_SEND_EOL "\r" #endif +#ifndef AT_SEND_ECHO +/** Enable/disable the expected echo after an AT command is sent */ +#define AT_SEND_ECHO 1 +#endif + +/** Shortcut for getting send end of line length */ +#define AT_SEND_EOL_LEN (sizeof(AT_SEND_EOL) - 1) + /** * @brief AT device structure */ @@ -55,7 +64,6 @@ typedef struct { uart_t uart; /**< UART device where the AT device is attached */ } at_dev_t; - /** * @brief Initialize AT device struct * @@ -71,7 +79,7 @@ typedef struct { int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t bufsize); /** - * @brief simple command helper + * @brief Simple command helper * * This function sends an AT command to the device and waits for "OK". * @@ -85,10 +93,10 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout); /** - * @brief send AT command, wait for a prompt + * @brief Send AT command, wait for a prompt * - * This function will send the supplied @p command, then wait for the prompt (>) - * character and return + * This function sends the supplied @p command, then waits for the prompt (>) + * character and returns * * @param[in] dev device to operate on * @param[in] command command string to send @@ -100,9 +108,9 @@ int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout); int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout); /** - * @brief send AT command, wait for response + * @brief Send AT command, wait for response * - * This function will send the supplied @p command, then wait and return one + * This function sends the supplied @p command, then waits and returns one * line of response. * * A possible empty line will be skipped. @@ -113,15 +121,15 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout * @param[in] len len of @p buffer * @param[in] timeout timeout (in usec) * - * @returns lenght of response on success + * @returns length of response on success * @returns <0 on error */ 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 multiline response + * @brief Send AT command, wait for multiline response * - * This function will send the supplied @p command, then return all response + * This function sends the supplied @p command, then returns all response * lines until the device sends "OK". * * If a line starts with "ERROR" or "+CME ERROR:", or the buffer is full, the @@ -133,7 +141,7 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, * @param[in] len len of @p buffer * @param[in] timeout timeout (in usec) * - * @returns lenght of response on success + * @returns length of response on success * @returns <0 on error */ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout); @@ -142,17 +150,16 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf * @brief Expect bytes from device * * @param[in] dev device to operate on - * @param[in] bytes buffer containing bytes to expect - * @param[in] len number of bytes to expect + * @param[in] bytes buffer containing bytes to expect (NULL-terminated) * @param[in] timeout timeout (in usec) * * @returns 0 on success * @returns <0 otherwise */ -int at_expect_bytes(at_dev_t *dev, const char *bytes, size_t len, uint32_t timeout); +int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout); /** - * @brief Send raw bytes to a device + * @brief Send raw bytes to a device * * @param[in] dev device to operate on * @param[in] bytes buffer containing bytes to send @@ -161,7 +168,7 @@ int at_expect_bytes(at_dev_t *dev, const char *bytes, size_t len, uint32_t timeo void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len); /** - * @brief send command to device + * @brief Send command to device * * @param[in] dev device to operate on * @param[in] command command to send @@ -173,7 +180,7 @@ void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len); int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout); /** - * @brief read a line from device + * @brief Read a line from device * * @param[in] dev device to operate on * @param[in] resp_buf buffer to store line @@ -186,7 +193,7 @@ int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout); ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, uint32_t timeout); /** - * @brief drain device input buffer + * @brief Drain device input buffer * * This function drains any possible bytes waiting in the device's input * buffer. @@ -200,3 +207,4 @@ void at_drain(at_dev_t *dev); #endif #endif /* AT_H */ +/** @} */