drivers/pty: support pty write to send signal, like serial driver

The interaction between the shell service in adb and adbd occurs through a pseudo-terminal (pty).
so, when a command is launched through adb shell from a PC, users now have the ability to pause
or kill the launched,application by inputting specific commands CONFIG_TTY_SIGTSTP_CHAR or
CONFIG_TTY_SIGTINT_CHAR, akin to the capabilities provided by nsh.

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2024-01-23 12:25:11 +08:00 committed by Xiang Xiao
parent a78622d7bf
commit d4bbbe0d0b

View File

@ -44,6 +44,7 @@
#include <nuttx/semaphore.h>
#include <nuttx/fs/fs.h>
#include <nuttx/serial/pty.h>
#include <nuttx/signal.h>
#include "pty.h"
@ -77,6 +78,9 @@ struct pty_dev_s
struct file pd_sink; /* Accepts data from write() method (pipe input) */
bool pd_master; /* True: this is the master */
uint8_t pd_escape; /* Number of the character to be escaped */
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
pid_t pd_pid; /* Thread PID to receive signals (-1 if none) */
#endif
tcflag_t pd_iflag; /* Terminal input modes */
tcflag_t pd_lflag; /* Terminal local modes */
tcflag_t pd_oflag; /* Terminal output modes */
@ -540,6 +544,9 @@ static ssize_t pty_write(FAR struct file *filep,
FAR struct pty_dev_s *dev;
ssize_t ntotal;
ssize_t nwritten;
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
pid_t pid;
#endif
size_t i;
char ch;
@ -547,6 +554,14 @@ static ssize_t pty_write(FAR struct file *filep,
dev = inode->i_private;
DEBUGASSERT(dev != NULL);
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
pid = dev->pd_devpair->pp_master.pd_pid;
if (dev->pd_master)
{
pid = dev->pd_devpair->pp_slave.pd_pid;
}
#endif
/* Do output post-processing */
if ((dev->pd_oflag & OPOST) != 0)
@ -599,6 +614,22 @@ static ssize_t pty_write(FAR struct file *filep,
}
}
#ifdef CONFIG_TTY_SIGINT
if (pid > 0 && ch == CONFIG_TTY_SIGINT_CHAR)
{
nxsig_kill(pid, SIGINT);
return 1;
}
#endif
#ifdef CONFIG_TTY_SIGTSTP
if (pid > 0 && ch == CONFIG_TTY_SIGTSTP_CHAR)
{
nxsig_kill(pid, SIGTSTP);
return 1;
}
#endif
/* Transfer the (possibly translated) character.. This will block
* if the sink pipe is full
*
@ -798,6 +829,33 @@ static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
/* Make the controlling terminal of the calling process */
case TIOCSCTTY:
{
/* Save the PID of the recipient of the SIGINT signal. */
if ((int)arg < 0 || dev->pd_pid >= 0)
{
ret = -EINVAL;
}
else
{
dev->pd_pid = (pid_t)arg;
ret = 0;
}
}
break;
case TIOCNOTTY:
{
dev->pd_pid = INVALID_PROCESS_ID;
ret = 0;
}
break;
#endif
/* Any unrecognized IOCTL commands will be passed to the contained
* pipe driver.
*
@ -1017,6 +1075,12 @@ int pty_register2(int minor, bool susv1)
devpair->pp_slave.pd_devpair = devpair;
devpair->pp_slave.pd_oflag = OPOST | ONLCR;
devpair->pp_slave.pd_lflag = ECHO;
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
/* Initialize of the task that will receive SIGINT signals. */
devpair->pp_master.pd_pid = INVALID_PROCESS_ID;
devpair->pp_slave.pd_pid = INVALID_PROCESS_ID;
#endif
/* Register the master device
*