From d4bbbe0d0b96c72dc83998ed8cd1e54f2beb4d97 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Tue, 23 Jan 2024 12:25:11 +0800 Subject: [PATCH] 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 --- drivers/serial/pty.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/serial/pty.c b/drivers/serial/pty.c index 3c668bf38b..6e30277c5d 100644 --- a/drivers/serial/pty.c +++ b/drivers/serial/pty.c @@ -44,6 +44,7 @@ #include #include #include +#include #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 *