int tty_inproc(uint8_t minor, unsigned char c) { unsigned char oc; struct termios *td; struct s_queue *q = &ttyinq[minor]; int canon; uint16_t pgrp = tty_pgrp[minor]; uint8_t wr; td = &ttydata[minor]; canon = td->c_lflag & ICANON; if (td->c_iflag & ISTRIP) c &= 0x7f; /* Strip off parity */ if (canon && !c) return 1; /* Simply quit if Null character */ #ifdef CONFIG_IDUMP if (c == 0x1a) /* ^Z */ idump(); /* (For debugging) */ #endif #ifdef CONFIG_MONITOR if (c == 0x01) /* ^A */ trap_monitor(); #endif if (c == '\r' && (td->c_iflag & ICRNL)) c = '\n'; if (c == '\n' && (td->c_iflag & INLCR)) c = '\r'; if (td->c_lflag & ISIG) { if (c == td->c_cc[VINTR]) { /* ^C */ sgrpsig(pgrp, SIGINT); clrq(q); stopflag[minor] = flshflag[minor] = false; return 1; } else if (c == td->c_cc[VQUIT]) { /* ^\ */ sgrpsig(pgrp, SIGQUIT); clrq(q); stopflag[minor] = flshflag[minor] = false; return 1; } } if (c == td->c_cc[VDISCARD]) { /* ^O */ flshflag[minor] = !flshflag[minor]; return 1; } if (td->c_iflag & IXON) { if (c == td->c_cc[VSTOP]) { /* ^S */ stopflag[minor] = true; return 1; } if (c == td->c_cc[VSTART]) { /* ^Q */ stopflag[minor] = false; wakeup(&stopflag[minor]); return 1; } } if (canon) { if (c == td->c_cc[VERASE]) { if (uninsq(q, &oc)) { if (oc == '\n' || oc == td->c_cc[VEOL]) insq(q, oc); /* Don't erase past nl */ else if (td->c_lflag & ECHOE) tty_erase(minor); return 1; } else if (c == td->c_cc[VKILL]) { while (uninsq(q, &oc)) { if (oc == '\n' || oc == td->c_cc[VEOL]) { insq(q, oc); /* Don't erase past nl */ break; } if (td->c_lflag & ECHOK) tty_erase(minor); } return 1; } } } /* All modes come here */ if (c == '\n') { if ((td->c_oflag & OPOST | ONLCR) == OPOST | ONLCR) tty_echo(minor, '\r'); } wr = insq(q, c); if (wr) tty_echo(minor, c); else if (minor < PTY_OFFSET) tty_putc_wait(minor, '\007'); /* Beep if no more room */ if (!canon || c == td->c_cc[VEOL] || c == '\n' || c == td->c_cc[VEOF]) wakeup(q); return wr; }
/* This routine processes a character in response to an interrupt. It * adds the character to the tty input queue, echoing and processing * backspace and carriage return. If the queue contains a full line, * it wakes up anything waiting on it. If it is totally full, it beeps * at the user. * UZI180 - This routine is called from the raw Hardware read routine, * either interrupt or polled, to process the input character. HFB */ int tty_inproc(uint8_t minor, unsigned char c) { unsigned char oc; int canon; uint8_t wr; struct tty *t = &ttydata[minor]; struct s_queue *q = &ttyinq[minor]; canon = t->termios.c_lflag & ICANON; if (t->termios.c_iflag & ISTRIP) c &= 0x7f; /* Strip off parity */ if (canon && !c) return 1; /* Simply quit if Null character */ #ifdef CONFIG_IDUMP if (c == 0x1a) /* ^Z */ idump(); /* (For debugging) */ #endif #ifdef CONFIG_MONITOR if (c == 0x01) /* ^A */ trap_monitor(); #endif if (c == '\r' && (t->termios.c_iflag & ICRNL)) c = '\n'; if (c == '\n' && (t->termios.c_iflag & INLCR)) c = '\r'; if (t->termios.c_lflag & ISIG) { if (c == t->termios.c_cc[VINTR]) { /* ^C */ wr = SIGINT; goto sigout; } else if (c == t->termios.c_cc[VQUIT]) { /* ^\ */ wr = SIGQUIT; sigout: sgrpsig(t->pgrp, wr); clrq(q); t->flag &= ~(TTYF_STOP | TTYF_DISCARD); return 1; } } if (c == t->termios.c_cc[VDISCARD]) { /* ^O */ t->flag ^= TTYF_DISCARD; return 1; } if (t->termios.c_iflag & IXON) { if (c == t->termios.c_cc[VSTOP]) { /* ^S */ t->flag |= TTYF_STOP; return 1; } if (c == t->termios.c_cc[VSTART]) { /* ^Q */ t->flag &= ~TTYF_STOP; wakeup(&t->flag); return 1; } } if (canon) { if (c == t->termios.c_cc[VERASE]) { wr = ECHOE; goto eraseout; } else if (c == t->termios.c_cc[VKILL]) { wr = ECHOK; goto eraseout; } } /* All modes come here */ if (c == '\n') { if ((t->termios.c_oflag & (OPOST | ONLCR)) == (OPOST | ONLCR)) tty_echo(minor, '\r'); } wr = insq(q, c); if (wr) tty_echo(minor, c); else tty_putc(minor, '\007'); /* Beep if no more room */ if (!canon || c == t->termios.c_cc[VEOL] || c == '\n' || c == t->termios.c_cc[VEOF]) wakeup(q); return wr; eraseout: while (uninsq(q, &oc)) { if (oc == '\n' || oc == t->termios.c_cc[VEOL]) { insq(q, oc); /* Don't erase past nl */ break; } if (t->termios.c_lflag & wr) tty_erase(minor); if (wr == ECHOE) break; } return 1; }