From aa5ac49a21f64407ce38a5a75a08e36575bd2360 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Sat, 22 Jul 2023 14:17:50 +0200 Subject: [PATCH] arch/nrf91: convert modem AT interface to serial device --- arch/arm/src/nrf91/nrf91_modem_at.c | 354 +++++++++++++++++++--------- 1 file changed, 237 insertions(+), 117 deletions(-) diff --git a/arch/arm/src/nrf91/nrf91_modem_at.c b/arch/arm/src/nrf91/nrf91_modem_at.c index 917b7644c34..1bab4411e1f 100644 --- a/arch/arm/src/nrf91/nrf91_modem_at.c +++ b/arch/arm/src/nrf91/nrf91_modem_at.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -39,6 +39,7 @@ ****************************************************************************/ #define NRF91_MODEM_AT_RX 255 +#define NRF91_MODEM_AT_TX 255 /**************************************************************************** * Private Types @@ -46,43 +47,89 @@ struct nrf91_modem_at_s { - char rxbuf[NRF91_MODEM_AT_RX]; - size_t rx_i; - sem_t rx_sem; - mutex_t lock; + /* Norificaiton */ + + bool notif_now; + const char *notif; + size_t notif_len; + size_t notif_i; + + /* Response */ + + const char *resp; + bool resp_now; + size_t resp_len; + size_t resp_i; + + /* TX */ + + char txbuf[NRF91_MODEM_AT_TX]; + size_t tx_i; }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static void nrf91_modem_at_notify_handler(const char *notif); -static void nrf91_modem_at_resp_handler(const char *resp); -static ssize_t nrf91_modem_at_read(struct file *filep, char *buffer, - size_t buflen); -static ssize_t nrf91_modem_at_write(struct file *filep, const char *buffer, - size_t buflen); +static int nrf91_modem_at_setup(struct uart_dev_s *dev); +static void nrf91_modem_at_shutdown(struct uart_dev_s *dev); +static int nrf91_modem_at_attach(struct uart_dev_s *dev); +static void nrf91_modem_at_detach(struct uart_dev_s *dev); static int nrf91_modem_at_ioctl(struct file *filep, int cmd, unsigned long arg); +static int nrf91_modem_at_receive(struct uart_dev_s *dev, + unsigned int *status); +static void nrf91_modem_at_rxint(struct uart_dev_s *dev, bool enable); +static bool nrf91_modem_at_rxavailable(struct uart_dev_s *dev); +static void nrf91_modem_at_send(struct uart_dev_s *dev, int ch); +static void nrf91_modem_at_txint(struct uart_dev_s *dev, bool enable); +static bool nrf91_modem_at_txready(struct uart_dev_s *dev); +static bool nrf91_modem_at_txempty(struct uart_dev_s *dev); /**************************************************************************** * Private Data ****************************************************************************/ -static const struct file_operations g_nrf91_modem_at_fops = +static const struct uart_ops_s g_nrf91_modem_at_fops = { - NULL, /* open */ - NULL, /* close */ - nrf91_modem_at_read, /* read */ - nrf91_modem_at_write, /* write */ - NULL, /* seek */ - nrf91_modem_at_ioctl, /* ioctl */ - NULL, /* mmap */ - NULL, /* truncate */ - NULL /* poll */ + .setup = nrf91_modem_at_setup, + .shutdown = nrf91_modem_at_shutdown, + .attach = nrf91_modem_at_attach, + .detach = nrf91_modem_at_detach, + .ioctl = nrf91_modem_at_ioctl, + .receive = nrf91_modem_at_receive, + .rxint = nrf91_modem_at_rxint, + .rxavailable = nrf91_modem_at_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = nrf91_modem_at_send, + .txint = nrf91_modem_at_txint, + .txready = nrf91_modem_at_txready, + .txempty = nrf91_modem_at_txempty, }; -static struct nrf91_modem_at_s g_nrf91_modem_at; +static struct nrf91_modem_at_s g_nrf91_modem_at_priv; + +static char g_modem1rxbuffer[NRF91_MODEM_AT_RX]; +static char g_modem1txbuffer[NRF91_MODEM_AT_TX]; + +static uart_dev_t g_nrf91_modem_at = +{ + .isconsole = false, + .ops = &g_nrf91_modem_at_fops, + .priv = &g_nrf91_modem_at_priv, + .recv = + { + .size = NRF91_MODEM_AT_RX, + .buffer = g_modem1rxbuffer, + }, + .xmit = + { + .size = NRF91_MODEM_AT_TX, + .buffer = g_modem1txbuffer, + }, +}; /**************************************************************************** * Private Functions @@ -94,16 +141,14 @@ static struct nrf91_modem_at_s g_nrf91_modem_at; static void nrf91_modem_at_notify_handler(const char *notif) { - struct nrf91_modem_at_s *dev = &g_nrf91_modem_at; + struct uart_dev_s *dev = &g_nrf91_modem_at; + struct nrf91_modem_at_s *priv = (struct nrf91_modem_at_s *)dev->priv; - /* Copy notify */ + priv->notif_i = 0; + priv->notif = notif; + priv->notif_len = strlen(notif); - strncpy(&dev->rxbuf[dev->rx_i], notif, NRF91_MODEM_AT_RX - dev->rx_i); - dev->rx_i += strlen(notif); - - /* Wake-up any thread waiting in recv */ - - nxsem_post(&dev->rx_sem); + uart_recvchars(dev); } /**************************************************************************** @@ -112,100 +157,60 @@ static void nrf91_modem_at_notify_handler(const char *notif) static void nrf91_modem_at_resp_handler(const char *resp) { - struct nrf91_modem_at_s *dev = &g_nrf91_modem_at; + struct uart_dev_s *dev = &g_nrf91_modem_at; + struct nrf91_modem_at_s *priv = (struct nrf91_modem_at_s *)dev->priv; - /* Copy response */ + priv->resp_i = 0; + priv->resp = resp; + priv->resp_len = strlen(resp); - strncpy(&dev->rxbuf[dev->rx_i], resp, NRF91_MODEM_AT_RX - dev->rx_i); - dev->rx_i += strlen(resp); - - /* Wake-up any thread waiting in recv */ - - nxsem_post(&dev->rx_sem); + uart_recvchars(dev); } /**************************************************************************** - * Name: nrf91_modem_at_read + * Name: nrf91_modem_at_setup ****************************************************************************/ -static ssize_t nrf91_modem_at_read(struct file *filep, char *buffer, - size_t len) +static int nrf91_modem_at_setup(struct uart_dev_s *dev) { - struct nrf91_modem_at_s *dev = NULL; - struct inode *inode = NULL; - int ret = 0; + struct nrf91_modem_at_s *priv = (struct nrf91_modem_at_s *)dev->priv; - DEBUGASSERT(filep); - inode = filep->f_inode; + /* Reset private data */ - DEBUGASSERT(inode && inode->i_private); - dev = (struct nrf91_modem_at_s *)inode->i_private; + memset(priv, 0, sizeof(struct nrf91_modem_at_s)); - ret = nxmutex_lock(&dev->lock); - if (ret < 0) - { - return ret; - } + /* Initialize AT modem */ - if ((filep->f_oflags & O_NONBLOCK) != 0) - { - nxsem_trywait(&dev->rx_sem); - ret = 0; - } - else - { - ret = nxsem_wait(&dev->rx_sem); - } + nrf_modem_at_notif_handler_set(nrf91_modem_at_notify_handler); + nrf_modem_at_cmd_custom_set(NULL, 0); - if (ret < 0) - { - return ret; - } - - /* Get response data */ - - if (len > dev->rx_i) - { - len = dev->rx_i; - } - - strncpy(buffer, dev->rxbuf, len); - dev->rx_i = 0; - ret = len; - - nxmutex_unlock(&dev->lock); - return ret; + return OK; } /**************************************************************************** - * Name: nrf91_modem_at_write + * Name: nrf91_modem_at_shutdown ****************************************************************************/ -static ssize_t nrf91_modem_at_write(struct file *filep, const char *buffer, - size_t len) +static void nrf91_modem_at_shutdown(struct uart_dev_s *dev) { - struct nrf91_modem_at_s *dev = NULL; - struct inode *inode = NULL; - int ret = 0; + nrf_modem_at_notif_handler_set(NULL); +} - DEBUGASSERT(filep); - inode = filep->f_inode; +/**************************************************************************** + * Name: nrf91_modem_at_attach + ****************************************************************************/ - DEBUGASSERT(inode && inode->i_private); - dev = (struct nrf91_modem_at_s *)inode->i_private; +static int nrf91_modem_at_attach(struct uart_dev_s *dev) +{ + return OK; +} - ret = nxmutex_lock(&dev->lock); - if (ret < 0) - { - return ret; - } +/**************************************************************************** + * Name: nrf91_modem_at_detach + ****************************************************************************/ - /* Send AT command */ - - ret = nrf_modem_at_cmd_async(nrf91_modem_at_resp_handler, buffer); - - nxmutex_unlock(&dev->lock); - return ret; +static void nrf91_modem_at_detach(struct uart_dev_s *dev) +{ } /**************************************************************************** @@ -215,7 +220,135 @@ static ssize_t nrf91_modem_at_write(struct file *filep, const char *buffer, static int nrf91_modem_at_ioctl(struct file *filep, int cmd, unsigned long arg) { - return -ENOTTY; + return OK; +} + +/**************************************************************************** + * Name: nrf91_modem_at_receive + ****************************************************************************/ + +static int nrf91_modem_at_receive(struct uart_dev_s *dev, + unsigned int *status) +{ + struct nrf91_modem_at_s *priv = (struct nrf91_modem_at_s *)dev->priv; + char ch = 0; + + *status = 0; + + if (priv->resp != NULL && priv->notif_now == false) + { + priv->resp_now = true; + ch = priv->resp[priv->resp_i++]; + if (priv->resp_i >= priv->resp_len) + { + priv->resp = NULL; + priv->resp_now = false; + } + } + else if (priv->notif != NULL && priv->resp_now == false) + { + priv->notif_now = true; + ch = priv->notif[priv->notif_i++]; + if (priv->notif_i >= priv->notif_len) + { + priv->notif = NULL; + priv->notif_now = false; + } + } + + return (int)ch; +} + +/**************************************************************************** + * Name: nrf91_modem_at_rxint + ****************************************************************************/ + +static void nrf91_modem_at_rxint(struct uart_dev_s *dev, bool enable) +{ +} + +/**************************************************************************** + * Name: nrf91_modem_at_rxavailable + ****************************************************************************/ + +static bool nrf91_modem_at_rxavailable(struct uart_dev_s *dev) +{ + struct nrf91_modem_at_s *priv = (struct nrf91_modem_at_s *)dev->priv; + return priv->notif || priv->resp; +} + +/**************************************************************************** + * Name: nrf91_modem_at_send + ****************************************************************************/ + +static void nrf91_modem_at_send(struct uart_dev_s *dev, int ch) +{ + struct nrf91_modem_at_s *priv = (struct nrf91_modem_at_s *)dev->priv; + int ret = OK; + + if (priv->tx_i + 1 > NRF91_MODEM_AT_TX) + { + _err("no free space in TX buffer\n"); + } + + priv->txbuf[priv->tx_i] = (char)ch; + priv->tx_i += 1; + + /* Special formating Nordic AT interface (escape charactes) */ + + if (ch == '%') + { + priv->txbuf[priv->tx_i] = '%'; + priv->tx_i += 1; + } + + if (priv->txbuf[priv->tx_i - 1] == '\r') + { + priv->txbuf[priv->tx_i - 1] = '\0'; + + /* Send AT command */ + + ret = nrf_modem_at_cmd_async(nrf91_modem_at_resp_handler, priv->txbuf); + if (ret < 0) + { + _err("nrf_modem_at_cmd_async failed %d\n", ret); + } + + /* Reset buffer */ + + memset(priv->txbuf, 0, NRF91_MODEM_AT_TX); + priv->tx_i = 0; + } +} + +/**************************************************************************** + * Name: nrf91_modem_at_txint + ****************************************************************************/ + +static void nrf91_modem_at_txint(struct uart_dev_s *dev, bool enable) +{ + if (enable) + { + uart_xmitchars(dev); + } +} + +/**************************************************************************** + * Name: nrf91_modem_at_txready + ****************************************************************************/ + +static bool nrf91_modem_at_txready(struct uart_dev_s *dev) +{ + return true; +} + +/**************************************************************************** + * Name: nrf91_modem_at_txempty + ****************************************************************************/ + +static bool nrf91_modem_at_txempty(struct uart_dev_s *dev) +{ + return true; } /**************************************************************************** @@ -228,24 +361,11 @@ static int nrf91_modem_at_ioctl(struct file *filep, int cmd, int nrf91_at_register(const char *path) { - struct nrf91_modem_at_s *dev = &g_nrf91_modem_at; - int ret = OK; - - /* Initialize mutex & sem */ - - memset(&g_nrf91_modem_at, 0, sizeof(struct nrf91_modem_at_s)); - - nxmutex_init(&dev->lock); - nxsem_init(&dev->rx_sem, 0, 0); - - /* Initialize AT modem */ - - nrf_modem_at_notif_handler_set(nrf91_modem_at_notify_handler); - nrf_modem_at_cmd_custom_set(NULL, 0); + int ret = OK; /* Register driver */ - ret = register_driver(path, &g_nrf91_modem_at_fops, 0666, dev); + ret = uart_register(path, &g_nrf91_modem_at); if (ret < 0) { nerr("ERROR: register_driver failed: %d\n", ret);