From 3393888ceaa6f4c76b622c6052dbfa4d6fcf31ca Mon Sep 17 00:00:00 2001 From: Vincent Dupont Date: Tue, 26 Jun 2018 10:03:10 -0700 Subject: [PATCH] drivers/at: add URC registering and parsing feature --- drivers/at/at.c | 49 +++++++++++++++++++++++++++++ drivers/include/at.h | 56 ++++++++++++++++++++++++++++++++++ makefiles/pseudomodules.inc.mk | 1 + 3 files changed, 106 insertions(+) diff --git a/drivers/at/at.c b/drivers/at/at.c index f74b5e3702..dfbff87cf7 100644 --- a/drivers/at/at.c +++ b/drivers/at/at.c @@ -266,3 +266,52 @@ out: } return res; } + +#ifdef MODULE_AT_URC +void at_add_urc(at_dev_t *dev, at_urc_t *urc) +{ + assert(urc); + assert(urc->code); + assert(strlen(urc->code) != 0); + assert(urc->cb); + + clist_rpush(&dev->urc_list, &urc->list_node); +} + +void at_remove_urc(at_dev_t *dev, at_urc_t *urc) +{ + clist_remove(&dev->urc_list, &urc->list_node); +} + +static int _check_urc(clist_node_t *node, void *arg) +{ + const char *buf = arg; + at_urc_t *urc = container_of(node, at_urc_t, list_node); + + DEBUG("Trying to match with %s\n", urc->code); + + if (strncmp(buf, urc->code, strlen(urc->code)) == 0) { + urc->cb(urc->arg, buf); + return 1; + } + + return 0; +} + +void at_process_urc(at_dev_t *dev, uint32_t timeout) +{ + char buf[AT_BUF_SIZE]; + + DEBUG("Processing URC (timeout=%" PRIu32 "us)\n", timeout); + + ssize_t res; + /* keep reading while received data are shorter than EOL */ + while ((res = at_readline(dev, buf, sizeof(buf), true, timeout)) < + (ssize_t)sizeof(AT_RECV_EOL_1 AT_RECV_EOL_2) - 1) { + if (res < 0) { + return; + } + } + clist_foreach(&dev->urc_list, _check_urc, buf); +} +#endif diff --git a/drivers/include/at.h b/drivers/include/at.h index 7f8d02848f..3d1808d7f2 100644 --- a/drivers/include/at.h +++ b/drivers/include/at.h @@ -39,6 +39,7 @@ #include "isrpipe.h" #include "periph/uart.h" +#include "clist.h" #ifdef __cplusplus extern "C" { @@ -77,12 +78,41 @@ extern "C" { #define AT_RECV_ERROR "ERROR" #endif +#if defined(MODULE_AT_URC) || DOXYGEN +#ifndef AT_BUF_SIZE +/** Internal buffer size used to process unsolicited result code data */ +#define AT_BUF_SIZE (128) +#endif + +/** + * @brief Unsolicited result code callback + * + * @param[in] arg optional argument + * @param[in] code urc string received from the device + */ +typedef void (*at_urc_cb_t)(void *arg, const char *code); + +/** + * @brief Unsolicited result code data structure + */ +typedef struct { + clist_node_t list_node; /**< node list */ + at_urc_cb_t cb; /**< callback */ + const char *code; /**< URC string which must match */ + void *arg; /**< optional argument */ +} at_urc_t; + +#endif /* MODULE_AT_URC */ + /** * @brief AT device structure */ typedef struct { isrpipe_t isrpipe; /**< isrpipe used for getting data from uart */ uart_t uart; /**< UART device where the AT device is attached */ +#ifdef MODULE_AT_URC + clist_node_t urc_list; /**< list to keep track of all registered urc's */ +#endif } at_dev_t; /** @@ -226,6 +256,32 @@ ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, ui */ void at_drain(at_dev_t *dev); +#if defined(MODULE_AT_URC) || DOXYGEN +/** + * @brief Add a callback for an unsolicited response code + * + * @param[in] dev device to operate on + * @param[in] urc unsolicited result code to register + */ +void at_add_urc(at_dev_t *dev, at_urc_t *urc); + +/** + * @brief Remove an unsolicited response code from the list + * + * @param[in] dev device to operate on + * @param[in] urc unsolicited result code to remove + */ +void at_remove_urc(at_dev_t *dev, at_urc_t *urc); + +/** + * @brief Process out-of-band data received from the device + * + * @param[in] dev device to operate on + * @param[in] timeout timeout (in usec) + */ +void at_process_urc(at_dev_t *dev, uint32_t timeout); +#endif + #ifdef __cplusplus } #endif diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 1e3d319898..9e65ffa650 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -1,3 +1,4 @@ +PSEUDOMODULES += at_urc PSEUDOMODULES += auto_init_gnrc_rpl PSEUDOMODULES += can_mbox PSEUDOMODULES += can_pm