uart: Add driver for posix arch
Added a new UART driver for posix arch boards. The driver can be configured to either attach to a new pseudo-terminal, or to connect to the invoking shell stdin-out. Signed-off-by: Alberto Escolar Piedras <alpi@oticon.com>
This commit is contained in:
parent
3e41ac5f04
commit
013f279111
9 changed files with 461 additions and 21 deletions
|
@ -23,7 +23,7 @@ if (CONFIG_ASAN)
|
||||||
zephyr_ld_options(-fsanitize=address)
|
zephyr_ld_options(-fsanitize=address)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
zephyr_compile_definitions(_POSIX_C_SOURCE=200809 _XOPEN_SOURCE _XOPEN_SOURCE_EXTENDED)
|
zephyr_compile_definitions(_POSIX_C_SOURCE=200809 _XOPEN_SOURCE=600 _XOPEN_SOURCE_EXTENDED)
|
||||||
|
|
||||||
zephyr_ld_options(
|
zephyr_ld_options(
|
||||||
-ldl
|
-ldl
|
||||||
|
|
|
@ -38,10 +38,17 @@ endchoice
|
||||||
|
|
||||||
endif # BT_HCI
|
endif # BT_HCI
|
||||||
|
|
||||||
|
if SERIAL
|
||||||
|
|
||||||
|
config UART_NATIVE_POSIX
|
||||||
|
def_bool y
|
||||||
|
|
||||||
|
endif # SERIAL
|
||||||
|
|
||||||
if LOG
|
if LOG
|
||||||
|
|
||||||
config LOG_BACKEND_NATIVE_POSIX
|
config LOG_BACKEND_NATIVE_POSIX
|
||||||
def_bool y
|
def_bool y if !SERIAL
|
||||||
|
|
||||||
# For native_posix we can log immediately without any problem
|
# For native_posix we can log immediately without any problem
|
||||||
# Doing so will be nicer for debugging
|
# Doing so will be nicer for debugging
|
||||||
|
@ -55,4 +62,14 @@ config LOG_PROCESS_THREAD
|
||||||
|
|
||||||
endif # LOG
|
endif # LOG
|
||||||
|
|
||||||
|
if CONSOLE
|
||||||
|
|
||||||
|
config NATIVE_POSIX_CONSOLE
|
||||||
|
def_bool y if !SERIAL
|
||||||
|
|
||||||
|
config UART_CONSOLE
|
||||||
|
def_bool y if SERIAL
|
||||||
|
|
||||||
|
endif #CONSOLE
|
||||||
|
|
||||||
endif # BOARD_NATIVE_POSIX
|
endif # BOARD_NATIVE_POSIX
|
||||||
|
|
|
@ -19,6 +19,9 @@ you use native host tools for compiling, debugging, and analyzing your
|
||||||
Zephyr application, eliminating the need for architecture-specific
|
Zephyr application, eliminating the need for architecture-specific
|
||||||
target hardware in the early phases of development.
|
target hardware in the early phases of development.
|
||||||
|
|
||||||
|
This board provides a few peripherals such as an Ethernet driver and UART.
|
||||||
|
See `Peripherals`_ for more information.
|
||||||
|
|
||||||
Host system dependencies
|
Host system dependencies
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -458,8 +461,8 @@ The following peripherals are currently provided with this board:
|
||||||
``stdout``.
|
``stdout``.
|
||||||
|
|
||||||
- Feed any input from the native application ``stdin`` to a possible
|
- Feed any input from the native application ``stdin`` to a possible
|
||||||
running :ref:`Shell`. For more information refer to the section
|
running legacy shell. For more information refer to the section
|
||||||
`Shell support`_.
|
`Legacy shell support`_.
|
||||||
|
|
||||||
**Clock, timer and system tick model**
|
**Clock, timer and system tick model**
|
||||||
This model provides the system tick timer. By default
|
This model provides the system tick timer. By default
|
||||||
|
@ -538,11 +541,40 @@ The following peripherals are currently provided with this board:
|
||||||
must be powered down and support Bluetooth Low Energy (i.e. support the
|
must be powered down and support Bluetooth Low Energy (i.e. support the
|
||||||
Bluetooth specification version 4.0 or greater).
|
Bluetooth specification version 4.0 or greater).
|
||||||
|
|
||||||
Shell support
|
**UART**
|
||||||
*************
|
An optional UART driver can be compiled with native_posix.
|
||||||
|
For more information refer to the section `UART`_.
|
||||||
|
|
||||||
When the :ref:`Shell` subsystem is compiled with your application, the native
|
|
||||||
standard input (``stdin``) will be redirected to the shell.
|
UART
|
||||||
|
*****
|
||||||
|
|
||||||
|
This driver can be configured to either create and link the UART to a new
|
||||||
|
pseudoterminal (i.e. ``/dev/pts<nbr>``), or to map the UART input and
|
||||||
|
output to the executable's ``stdin`` and ``stdout``.
|
||||||
|
This is chosen by selecting either
|
||||||
|
:option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` or
|
||||||
|
:option:`CONFIG_NATIVE_UART_0_ON_STDINOUT`
|
||||||
|
Note that for interactive use, the first option should be chosen. The
|
||||||
|
second option is only intended for automated testing or feeding/piping other
|
||||||
|
processes output to the UART.
|
||||||
|
|
||||||
|
When :option:`CONFIG_NATIVE_UART_0_ON_OWN_PTY` is chosen, the name of the
|
||||||
|
newly created UART pseudo-terminal will be displayed in the console.
|
||||||
|
You may also chose to automatically attach a terminal emulator to it by
|
||||||
|
passing the command line option ``-attach_uart`` to the executable.
|
||||||
|
The command used for attaching to the new shell can be set with the command line
|
||||||
|
option ``-attach_uart_cmd=<"cmd">``. Where the default command is given by
|
||||||
|
:option:`CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD`.
|
||||||
|
Note that the default command assumes both ``xterm`` and ``screen`` are
|
||||||
|
installed in the system.
|
||||||
|
|
||||||
|
|
||||||
|
Legacy shell support
|
||||||
|
********************
|
||||||
|
|
||||||
|
When the legacy :ref:`Shell` subsystem is compiled with your application,
|
||||||
|
the native standard input (``stdin``) will be redirected to the shell.
|
||||||
You may use the shell interactively through the console,
|
You may use the shell interactively through the console,
|
||||||
by piping another process output to it, or by feeding it a file.
|
by piping another process output to it, or by feeding it a file.
|
||||||
|
|
||||||
|
@ -580,16 +612,8 @@ These directives are:
|
||||||
Use example
|
Use example
|
||||||
===========
|
===========
|
||||||
|
|
||||||
For example, you can build the shell sample app:
|
For example, after you have built an application with the legacy shell, you
|
||||||
|
can feed it the following set of commands through a pipe:
|
||||||
.. zephyr-app-commands::
|
|
||||||
:zephyr-app: samples/subsys/shell/shell_module
|
|
||||||
:host-os: unix
|
|
||||||
:board: native_posix
|
|
||||||
:goals: build
|
|
||||||
:compact:
|
|
||||||
|
|
||||||
And feed it the following set of commands through a pipe:
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,4 @@ CONFIG_ARCH_POSIX=y
|
||||||
CONFIG_SOC_POSIX=y
|
CONFIG_SOC_POSIX=y
|
||||||
CONFIG_BOARD_NATIVE_POSIX=y
|
CONFIG_BOARD_NATIVE_POSIX=y
|
||||||
CONFIG_CONSOLE=y
|
CONFIG_CONSOLE=y
|
||||||
CONFIG_SERIAL=y
|
|
||||||
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000
|
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000
|
||||||
|
|
|
@ -255,7 +255,6 @@ config NATIVE_POSIX_CONSOLE
|
||||||
bool "Use the host terminal for console"
|
bool "Use the host terminal for console"
|
||||||
depends on ARCH_POSIX
|
depends on ARCH_POSIX
|
||||||
select CONSOLE_HAS_DRIVER
|
select CONSOLE_HAS_DRIVER
|
||||||
default y
|
|
||||||
help
|
help
|
||||||
Use the host terminal (where the native_posix binary was launched) for the
|
Use the host terminal (where the native_posix binary was launched) for the
|
||||||
Zephyr console
|
Zephyr console
|
||||||
|
@ -263,7 +262,7 @@ config NATIVE_POSIX_CONSOLE
|
||||||
config NATIVE_POSIX_STDIN_CONSOLE
|
config NATIVE_POSIX_STDIN_CONSOLE
|
||||||
bool "Use the host terminal stdin"
|
bool "Use the host terminal stdin"
|
||||||
depends on NATIVE_POSIX_CONSOLE
|
depends on NATIVE_POSIX_CONSOLE
|
||||||
default y
|
default y if !NATIVE_UART_0_ON_STDINOUT
|
||||||
help
|
help
|
||||||
Feed the host terminal stdin to the Zephyr console/shell.
|
Feed the host terminal stdin to the Zephyr console/shell.
|
||||||
|
|
||||||
|
|
|
@ -26,3 +26,8 @@ zephyr_library_sources_if_kconfig(usart_mcux_lpc.c)
|
||||||
zephyr_library_sources_if_kconfig(uart_psoc6.c)
|
zephyr_library_sources_if_kconfig(uart_psoc6.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c)
|
||||||
|
|
||||||
|
if(CONFIG_UART_NATIVE_POSIX)
|
||||||
|
zephyr_library_compile_definitions(NO_POSIX_CHEATS)
|
||||||
|
zephyr_library_sources(uart_native_posix.c)
|
||||||
|
endif()
|
||||||
|
|
|
@ -71,6 +71,8 @@ source "drivers/serial/Kconfig.imx"
|
||||||
|
|
||||||
source "drivers/serial/Kconfig.stellaris"
|
source "drivers/serial/Kconfig.stellaris"
|
||||||
|
|
||||||
|
source "drivers/serial/Kconfig.native_posix"
|
||||||
|
|
||||||
source "drivers/serial/Kconfig.nsim"
|
source "drivers/serial/Kconfig.nsim"
|
||||||
|
|
||||||
source "drivers/serial/Kconfig.usart_sam"
|
source "drivers/serial/Kconfig.usart_sam"
|
||||||
|
|
59
drivers/serial/Kconfig.native_posix
Normal file
59
drivers/serial/Kconfig.native_posix
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
config UART_NATIVE_POSIX
|
||||||
|
bool "UART driver for native_posix"
|
||||||
|
select SERIAL_HAS_DRIVER
|
||||||
|
depends on ARCH_POSIX
|
||||||
|
help
|
||||||
|
This enables a UART driver for the POSIX ARCH. The driver can be configured
|
||||||
|
to either connect to the terminal from which native_posix was run, or into
|
||||||
|
one decicated pseudoterminal for this UART.
|
||||||
|
|
||||||
|
if UART_NATIVE_POSIX
|
||||||
|
|
||||||
|
config UART_NATIVE_POSIX_PORT_0_NAME
|
||||||
|
string "Port 0 Device Name"
|
||||||
|
default "UART_0"
|
||||||
|
depends on UART_NATIVE_POSIX
|
||||||
|
help
|
||||||
|
This is the device name for UART, and is included in the device
|
||||||
|
struct.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Native UART Port 0 connection"
|
||||||
|
default NATIVE_UART_0_ON_OWN_PTY
|
||||||
|
|
||||||
|
config NATIVE_UART_0_ON_OWN_PTY
|
||||||
|
bool "Connect the UART to its own pseudo terminal"
|
||||||
|
help
|
||||||
|
Connect the UART to its own pseudoterminal. This is the preferred option
|
||||||
|
for users who want to use Zephyr's shell.
|
||||||
|
Moreover this option does not conflict with any other native_posix backend
|
||||||
|
which may use the calling shell standard input/output.
|
||||||
|
|
||||||
|
config NATIVE_UART_0_ON_STDINOUT
|
||||||
|
bool "Connect the UART to the invoking shell stdin/stdout"
|
||||||
|
help
|
||||||
|
Connect the UART to the stdin & stdout of the calling shell/terminal which
|
||||||
|
invoked the native_posix executable. This is good enough for automated
|
||||||
|
testing, or when feeding from a file/pipe.
|
||||||
|
Note that other, non UART messages, will also be printed to the terminal.
|
||||||
|
This option should NOT be used in conjunction with the legacy shell
|
||||||
|
native_posix backend (NATIVE_POSIX_STDIN_CONSOLE)
|
||||||
|
It is strongly discouraged to try to use this option with the new shell
|
||||||
|
interactively, as the default terminal configuration is NOT appropriate
|
||||||
|
for interactive use.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config NATIVE_UART_AUTOATTACH_DEFAULT_CMD
|
||||||
|
string "Default command to attach the UART to a new terminal"
|
||||||
|
default "xterm -e screen %s &"
|
||||||
|
help
|
||||||
|
If the native_posix executable is called with the --attach_uart command line
|
||||||
|
option, this will be the default command which will be run to attach a new
|
||||||
|
terminal to it.
|
||||||
|
Note that this command must have one, and only one, '%s' as placeholder for
|
||||||
|
the pseudoterminal device name (e.g. /dev/pts/35)
|
||||||
|
This is only applicable if a UART is configured to use its own PTY with
|
||||||
|
NATIVE_UART_x_ON_OWN_PTY.
|
||||||
|
|
||||||
|
endif #UART_NATIVE_POSIX
|
335
drivers/serial/uart_native_posix.c
Normal file
335
drivers/serial/uart_native_posix.c
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pty.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include "cmdline.h" /* native_posix command line options header */
|
||||||
|
#include "soc.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UART driver for POSIX ARCH based boards.
|
||||||
|
* It can either be connected to the process STDIN+STDOUT
|
||||||
|
* OR
|
||||||
|
* to a dedicated pseudo terminal
|
||||||
|
*
|
||||||
|
* The 2nd option is the recommended one for interactive use, as the pseudo
|
||||||
|
* terminal driver will be configured in "raw" mode, and will therefore behave
|
||||||
|
* more like a real UART.
|
||||||
|
*
|
||||||
|
* When connected to its own pseudo terminal, it may also auto attach a terminal
|
||||||
|
* emulator to it, if set so from command line.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int np_uart_stdin_poll_in(struct device *dev, unsigned char *p_char);
|
||||||
|
static int np_uart_tty_poll_in(struct device *dev, unsigned char *p_char);
|
||||||
|
static unsigned char np_uart_poll_out(struct device *dev,
|
||||||
|
unsigned char out_char);
|
||||||
|
|
||||||
|
static bool auto_attach;
|
||||||
|
static const char default_cmd[] = CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD;
|
||||||
|
static char *auto_attach_cmd;
|
||||||
|
|
||||||
|
static struct uart_driver_api np_uart_driver_api = {
|
||||||
|
.poll_out = np_uart_poll_out,
|
||||||
|
.poll_in = np_uart_tty_poll_in,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct native_uart_status {
|
||||||
|
int out_fd; /* File descriptor used for output */
|
||||||
|
int in_fd; /* File descriptor used for input */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ERROR posix_print_error_and_exit
|
||||||
|
#define WARN posix_print_warning
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to connect a terminal emulator to the slave side of the pty
|
||||||
|
* If -attach_uart_cmd=<cmd> is provided as a command line option, <cmd> will be
|
||||||
|
* used. Otherwise, the default command,
|
||||||
|
* CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD, will be used instead
|
||||||
|
*/
|
||||||
|
static void attach_to_tty(const char *slave_tty)
|
||||||
|
{
|
||||||
|
if (auto_attach_cmd == NULL) {
|
||||||
|
auto_attach_cmd = (char *)default_cmd;
|
||||||
|
}
|
||||||
|
char command[strlen(auto_attach_cmd) + strlen(slave_tty)];
|
||||||
|
|
||||||
|
sprintf(command, auto_attach_cmd, slave_tty);
|
||||||
|
|
||||||
|
int ret = system(command);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
WARN("Could not attach to the UART with \"%s\"\n", command);
|
||||||
|
WARN("The command returned %i\n", WEXITSTATUS(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to allocate and open a new pseudoterminal
|
||||||
|
*
|
||||||
|
* Returns the file descriptor of the master side
|
||||||
|
* If auto_attach was set, it will also attempt to connect a new terminal
|
||||||
|
* emulator to its slave side.
|
||||||
|
*/
|
||||||
|
static int open_tty(void)
|
||||||
|
{
|
||||||
|
int master_pty;
|
||||||
|
char *slave_pty_name;
|
||||||
|
struct termios ter;
|
||||||
|
struct winsize win;
|
||||||
|
int err_nbr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
win.ws_col = 80;
|
||||||
|
win.ws_row = 24;
|
||||||
|
|
||||||
|
master_pty = posix_openpt(O_RDWR | O_NOCTTY);
|
||||||
|
if (master_pty == -1) {
|
||||||
|
ERROR("Could not open a new TTY for the UART\n");
|
||||||
|
}
|
||||||
|
ret = grantpt(master_pty);
|
||||||
|
if (ret == -1) {
|
||||||
|
err_nbr = errno;
|
||||||
|
close(master_pty);
|
||||||
|
ERROR("Could not grant access to the slave PTY side (%i)\n",
|
||||||
|
errno);
|
||||||
|
}
|
||||||
|
ret = unlockpt(master_pty);
|
||||||
|
if (ret == -1) {
|
||||||
|
err_nbr = errno;
|
||||||
|
close(master_pty);
|
||||||
|
ERROR("Could not unlock the slave PTY side (%i)\n", errno);
|
||||||
|
}
|
||||||
|
slave_pty_name = ptsname(master_pty);
|
||||||
|
if (slave_pty_name == NULL) {
|
||||||
|
err_nbr = errno;
|
||||||
|
close(master_pty);
|
||||||
|
ERROR("Error getting slave PTY device name (%i)\n", errno);
|
||||||
|
}
|
||||||
|
/* Set the master PTY as non blocking */
|
||||||
|
fcntl(master_pty, F_SETFL, fcntl(master_pty, F_GETFL) | O_NONBLOCK);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set terminal in "raw" mode:
|
||||||
|
* Not canonical (no line input)
|
||||||
|
* No signal generation from Ctr+{C|Z..}
|
||||||
|
* No echoing, no input or output processing
|
||||||
|
* No replacing of NL or CR
|
||||||
|
* No flow control
|
||||||
|
*/
|
||||||
|
ret = tcgetattr(master_pty, &ter);
|
||||||
|
if (ret == -1) {
|
||||||
|
ERROR("Could not read terminal driver settings\n");
|
||||||
|
}
|
||||||
|
ter.c_cc[VMIN] = 0;
|
||||||
|
ter.c_cc[VTIME] = 0;
|
||||||
|
ter.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO);
|
||||||
|
ter.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK
|
||||||
|
| ISTRIP | IXON | PARMRK);
|
||||||
|
ter.c_oflag &= ~OPOST;
|
||||||
|
ret = tcsetattr(master_pty, TCSANOW, &ter);
|
||||||
|
if (ret == -1) {
|
||||||
|
ERROR("Could not change terminal driver settings\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
posix_print_trace("UART connected to pseudotty: %s\n", slave_pty_name);
|
||||||
|
|
||||||
|
if (auto_attach) {
|
||||||
|
attach_to_tty(slave_pty_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return master_pty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the native_posix serial port
|
||||||
|
*
|
||||||
|
* @param dev UART device struct
|
||||||
|
*
|
||||||
|
* @return 0 (if it fails catastrophically, the execution is terminated)
|
||||||
|
*/
|
||||||
|
static int np_uart_init(struct device *dev)
|
||||||
|
{
|
||||||
|
struct native_uart_status *d;
|
||||||
|
|
||||||
|
d = (struct native_uart_status *)dev->driver_data;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) {
|
||||||
|
int tty_fn = open_tty();
|
||||||
|
|
||||||
|
d->in_fd = tty_fn;
|
||||||
|
d->out_fd = tty_fn;
|
||||||
|
np_uart_driver_api.poll_in = np_uart_tty_poll_in;
|
||||||
|
} else { /* NATIVE_UART_0_ON_STDINOUT */
|
||||||
|
d->in_fd = STDIN_FILENO;
|
||||||
|
d->out_fd = STDOUT_FILENO;
|
||||||
|
np_uart_driver_api.poll_in = np_uart_stdin_poll_in;
|
||||||
|
|
||||||
|
if (isatty(STDIN_FILENO)) {
|
||||||
|
WARN("The UART dirver has been configured to map to the"
|
||||||
|
" process stdin&out (NATIVE_UART_0_ON_STDINOUT), "
|
||||||
|
"but stdin seems to be left attached to the shell."
|
||||||
|
" This will most likely NOT behave as you want it "
|
||||||
|
"to. This option is NOT meant for interactive use "
|
||||||
|
"but for piping/feeding from/to files to the UART"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->driver_api = &np_uart_driver_api;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Output a character towards the serial port
|
||||||
|
*
|
||||||
|
* @param dev UART device struct
|
||||||
|
* @param out_char Character to send.
|
||||||
|
*/
|
||||||
|
static unsigned char np_uart_poll_out(struct device *dev,
|
||||||
|
unsigned char out_char)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct native_uart_status *d;
|
||||||
|
|
||||||
|
d = (struct native_uart_status *)dev->driver_data;
|
||||||
|
ret = write(d->out_fd, &out_char, 1);
|
||||||
|
|
||||||
|
if (ret != 1) {
|
||||||
|
WARN("%s: a character could not be output\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Poll the device for input.
|
||||||
|
*
|
||||||
|
* @param dev UART device structure.
|
||||||
|
* @param p_char Pointer to character.
|
||||||
|
*
|
||||||
|
* @retval 0 If a character arrived and was stored in p_char
|
||||||
|
* @retval -1 If no character was available to read
|
||||||
|
*/
|
||||||
|
static int np_uart_stdin_poll_in(struct device *dev, unsigned char *p_char)
|
||||||
|
{
|
||||||
|
static bool disconnected;
|
||||||
|
|
||||||
|
if (disconnected || feof(stdin)) {
|
||||||
|
/*
|
||||||
|
* The stdinput is fed from a file which finished or the user
|
||||||
|
* pressed Crtl+D
|
||||||
|
*/
|
||||||
|
disconnected = true;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = -1;
|
||||||
|
int in_f = ((struct native_uart_status *)dev->driver_data)->in_fd;
|
||||||
|
|
||||||
|
int ready;
|
||||||
|
fd_set readfds;
|
||||||
|
static struct timeval timeout; /* just zero */
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(in_f, &readfds);
|
||||||
|
|
||||||
|
ready = select(in_f+1, &readfds, NULL, NULL, &timeout);
|
||||||
|
|
||||||
|
if (ready == 0) {
|
||||||
|
return -1;
|
||||||
|
} else if (ready == -1) {
|
||||||
|
ERROR("%s: Error on select ()\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = read(in_f, p_char, 1);
|
||||||
|
if (n == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Poll the device for input.
|
||||||
|
*
|
||||||
|
* @param dev UART device structure.
|
||||||
|
* @param p_char Pointer to character.
|
||||||
|
*
|
||||||
|
* @retval 0 If a character arrived and was stored in p_char
|
||||||
|
* @retval -1 If no character was available to read
|
||||||
|
*/
|
||||||
|
static int np_uart_tty_poll_in(struct device *dev, unsigned char *p_char)
|
||||||
|
{
|
||||||
|
int n = -1;
|
||||||
|
int in_f = ((struct native_uart_status *)dev->driver_data)->in_fd;
|
||||||
|
|
||||||
|
n = read(in_f, p_char, 1);
|
||||||
|
if (n == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct native_uart_status native_uart_status_0;
|
||||||
|
|
||||||
|
DEVICE_INIT(uart_native_posix0,
|
||||||
|
CONFIG_UART_NATIVE_POSIX_PORT_0_NAME, &np_uart_init,
|
||||||
|
(void *)&native_uart_status_0, NULL,
|
||||||
|
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||||
|
|
||||||
|
static void np_add_uart_options(void)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct args_struct_t uart_options[] = {
|
||||||
|
/*
|
||||||
|
* Fields:
|
||||||
|
* manual, mandatory, switch,
|
||||||
|
* option_name, var_name ,type,
|
||||||
|
* destination, callback,
|
||||||
|
* description
|
||||||
|
*/
|
||||||
|
{false, false, true,
|
||||||
|
"attach_uart", "", 'b',
|
||||||
|
(void *)&auto_attach, NULL,
|
||||||
|
"Automatically attach to the UART terminal"},
|
||||||
|
{false, false, false,
|
||||||
|
"attach_uart_cmd", "\"cmd\"", 's',
|
||||||
|
(void *)&auto_attach_cmd, NULL,
|
||||||
|
"Command used to automatically attach to the terminal, by "
|
||||||
|
"default: '" CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD "'"},
|
||||||
|
|
||||||
|
ARG_TABLE_ENDMARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
native_add_command_line_opts(uart_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void np_cleanup_uart(void)
|
||||||
|
{
|
||||||
|
if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) {
|
||||||
|
if (native_uart_status_0.in_fd != 0) {
|
||||||
|
close(native_uart_status_0.in_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NATIVE_TASK(np_add_uart_options, PRE_BOOT_1, 11);
|
||||||
|
NATIVE_TASK(np_cleanup_uart, ON_EXIT, 99);
|
Loading…
Add table
Add a link
Reference in a new issue