302 lines
8.4 KiB
C
302 lines
8.4 KiB
C
/****************************************************************************
|
|
* drivers/serial/uart_hostfs.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/clock.h>
|
|
#include <nuttx/fs/hostfs.h>
|
|
#include <nuttx/serial/serial.h>
|
|
#include <nuttx/wdog.h>
|
|
|
|
#include <debug.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define UART_WDOG_DELAY USEC2TICK(CONFIG_UART_HOSTFS_DELAY_USEC)
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
struct uart_hostfs_priv_s
|
|
{
|
|
int fd;
|
|
bool rxint;
|
|
struct wdog_s wdog;
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
static int uart_hostfs_setup(FAR struct uart_dev_s *dev);
|
|
static void uart_hostfs_shutdown(FAR struct uart_dev_s *dev);
|
|
static int uart_hostfs_attach(FAR struct uart_dev_s *dev);
|
|
static void uart_hostfs_detach(FAR struct uart_dev_s *dev);
|
|
static int uart_hostfs_ioctl(FAR struct file *filep, int cmd,
|
|
unsigned long arg);
|
|
static void uart_hostfs_rxint(FAR struct uart_dev_s *dev, bool enable);
|
|
static bool uart_hostfs_rxavailable(FAR struct uart_dev_s *dev);
|
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
|
static bool uart_hostfs_rxflowcontrol(FAR struct uart_dev_s *dev,
|
|
unsigned int nbuffered, bool upper);
|
|
#endif
|
|
static void uart_hostfs_dmatxavail(FAR struct uart_dev_s *dev);
|
|
static void uart_hostfs_dmasend(FAR struct uart_dev_s *dev);
|
|
static void uart_hostfs_dmarxfree(FAR struct uart_dev_s *dev);
|
|
static void uart_hostfs_dmareceive(FAR struct uart_dev_s *dev);
|
|
static void uart_hostfs_send(FAR struct uart_dev_s *dev, int ch);
|
|
static void uart_hostfs_txint(FAR struct uart_dev_s *dev, bool enable);
|
|
static bool uart_hostfs_txready(FAR struct uart_dev_s *dev);
|
|
static bool uart_hostfs_txempty(FAR struct uart_dev_s *dev);
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static const struct uart_ops_s g_uart_hostfs_ops =
|
|
{
|
|
.setup = uart_hostfs_setup,
|
|
.shutdown = uart_hostfs_shutdown,
|
|
.attach = uart_hostfs_attach,
|
|
.detach = uart_hostfs_detach,
|
|
.ioctl = uart_hostfs_ioctl,
|
|
.rxint = uart_hostfs_rxint,
|
|
.rxavailable = uart_hostfs_rxavailable,
|
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
|
.rxflowcontrol = uart_hostfs_rxflowcontrol,
|
|
#endif
|
|
.dmatxavail = uart_hostfs_dmatxavail,
|
|
.dmasend = uart_hostfs_dmasend,
|
|
.dmarxfree = uart_hostfs_dmarxfree,
|
|
.dmareceive = uart_hostfs_dmareceive,
|
|
.send = uart_hostfs_send,
|
|
.txint = uart_hostfs_txint,
|
|
.txready = uart_hostfs_txready,
|
|
.txempty = uart_hostfs_txempty,
|
|
};
|
|
|
|
static char g_uart_hostfs_rxbuf[CONFIG_UART_HOSTFS_RXBUFSIZE];
|
|
static char g_uart_hostfs_txbuf[CONFIG_UART_HOSTFS_TXBUFSIZE];
|
|
|
|
static struct uart_hostfs_priv_s g_uart_hostfs_priv;
|
|
|
|
static struct uart_dev_s g_uart_hostfs_dev =
|
|
{
|
|
.ops = &g_uart_hostfs_ops,
|
|
.priv = &g_uart_hostfs_priv,
|
|
.xmit =
|
|
{
|
|
.size = CONFIG_UART_HOSTFS_TXBUFSIZE,
|
|
.buffer = g_uart_hostfs_txbuf,
|
|
},
|
|
.recv =
|
|
{
|
|
.size = CONFIG_UART_HOSTFS_RXBUFSIZE,
|
|
.buffer = g_uart_hostfs_rxbuf,
|
|
},
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
static int uart_hostfs_setup(FAR struct uart_dev_s *dev)
|
|
{
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
|
|
priv->fd = host_open(CONFIG_UART_HOSTFS_DEVPATH, O_RDWR | O_NONBLOCK,
|
|
0666);
|
|
return priv->fd;
|
|
}
|
|
|
|
static void uart_hostfs_shutdown(FAR struct uart_dev_s *dev)
|
|
{
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
|
|
if (priv->fd > 0)
|
|
{
|
|
host_close(priv->fd);
|
|
priv->fd = -1;
|
|
}
|
|
}
|
|
|
|
static int uart_hostfs_attach(FAR struct uart_dev_s *dev)
|
|
{
|
|
return OK;
|
|
}
|
|
|
|
static void uart_hostfs_detach(FAR struct uart_dev_s *dev)
|
|
{
|
|
}
|
|
|
|
static int uart_hostfs_ioctl(FAR struct file *filep, int cmd,
|
|
unsigned long arg)
|
|
{
|
|
return -ENOTTY;
|
|
}
|
|
|
|
static void uart_hostfs_wdog(wdparm_t arg)
|
|
{
|
|
FAR struct uart_dev_s *dev = (FAR struct uart_dev_s *)arg;
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
|
|
if (priv->rxint)
|
|
{
|
|
uart_dmarxfree(dev);
|
|
}
|
|
|
|
wd_start(&priv->wdog, UART_WDOG_DELAY, uart_hostfs_wdog, (wdparm_t)dev);
|
|
}
|
|
|
|
static void uart_hostfs_rxint(FAR struct uart_dev_s *dev, bool enable)
|
|
{
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
|
|
priv->rxint = enable;
|
|
if (enable)
|
|
{
|
|
wd_start(&priv->wdog, 0, uart_hostfs_wdog, (wdparm_t)dev);
|
|
}
|
|
else
|
|
{
|
|
wd_cancel(&priv->wdog);
|
|
}
|
|
}
|
|
|
|
static bool uart_hostfs_rxavailable(FAR struct uart_dev_s *dev)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
|
static bool uart_hostfs_rxflowcontrol(FAR struct uart_dev_s *dev,
|
|
unsigned int nbuffered, bool upper)
|
|
{
|
|
FAR struct uart_buffer_s *rxbuf = &dev->recv;
|
|
|
|
return nbuffered == rxbuf->size;
|
|
}
|
|
#endif
|
|
|
|
static void uart_hostfs_dmatxavail(FAR struct uart_dev_s *dev)
|
|
{
|
|
uart_xmitchars_dma(dev);
|
|
}
|
|
|
|
static void uart_hostfs_dmasend(FAR struct uart_dev_s *dev)
|
|
{
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
FAR struct uart_dmaxfer_s *xfer = &dev->dmatx;
|
|
int ret;
|
|
|
|
xfer->nbytes = 0;
|
|
ret = host_write(priv->fd, xfer->buffer, xfer->length);
|
|
if (ret > 0)
|
|
{
|
|
xfer->nbytes = ret;
|
|
|
|
if (ret == xfer->length && xfer->nlength > 0)
|
|
{
|
|
ret = host_write(priv->fd, xfer->nbuffer, xfer->nlength);
|
|
if (ret > 0)
|
|
{
|
|
xfer->nbytes += ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
uart_xmitchars_done(dev);
|
|
}
|
|
|
|
static void uart_hostfs_dmarxfree(FAR struct uart_dev_s *dev)
|
|
{
|
|
uart_recvchars_dma(dev);
|
|
}
|
|
|
|
static void uart_hostfs_dmareceive(FAR struct uart_dev_s *dev)
|
|
{
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
FAR struct uart_dmaxfer_s *xfer = &dev->dmarx;
|
|
ssize_t ret;
|
|
|
|
xfer->nbytes = 0;
|
|
ret = host_read(priv->fd, xfer->buffer, xfer->length);
|
|
if (ret > 0)
|
|
{
|
|
xfer->nbytes = ret;
|
|
|
|
if (ret == xfer->length && xfer->nlength > 0)
|
|
{
|
|
ret = host_read(priv->fd, xfer->nbuffer, xfer->nlength);
|
|
if (ret > 0)
|
|
{
|
|
xfer->nbytes += ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
uart_recvchars_done(dev);
|
|
}
|
|
|
|
static void uart_hostfs_send(FAR struct uart_dev_s *dev, int ch)
|
|
{
|
|
FAR struct uart_hostfs_priv_s *priv = dev->priv;
|
|
char c = ch;
|
|
|
|
host_write(priv->fd, &c, 1);
|
|
}
|
|
|
|
static void uart_hostfs_txint(FAR struct uart_dev_s *dev, bool enable)
|
|
{
|
|
}
|
|
|
|
static bool uart_hostfs_txready(FAR struct uart_dev_s *dev)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool uart_hostfs_txempty(FAR struct uart_dev_s *dev)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
void uart_hostfs_init(void)
|
|
{
|
|
uart_register("/dev/console", &g_uart_hostfs_dev);
|
|
}
|
|
|
|
void up_putc(int ch)
|
|
{
|
|
FAR struct uart_dev_s *dev = &g_uart_hostfs_dev;
|
|
|
|
uart_hostfs_send(dev, ch);
|
|
}
|