static void change_termios(struct tty_struct * tty, struct termios * new_termios) { int canon_change; struct termios old_termios = *tty->termios; struct tty_ldisc *ld; /* * Perform the actual termios internal changes under lock. */ /* FIXME: we need to decide on some locking/ordering semantics for the set_termios notification eventually */ down(&tty->termios_sem); *tty->termios = *new_termios; unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; if (canon_change) { memset(&tty->read_flags, 0, sizeof tty->read_flags); tty->canon_head = tty->read_tail; tty->canon_data = 0; tty->erasing = 0; } if (canon_change && !L_ICANON(tty) && tty->read_cnt) /* Get characters left over from canonical mode. */ wake_up_interruptible(&tty->read_wait); /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { int old_flow = ((old_termios.c_iflag & IXON) && (old_termios.c_cc[VSTOP] == '\023') && (old_termios.c_cc[VSTART] == '\021')); int new_flow = (I_IXON(tty) && STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if (old_flow != new_flow) { tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) tty->ctrl_status |= TIOCPKT_DOSTOP; else tty->ctrl_status |= TIOCPKT_NOSTOP; wake_up_interruptible(&tty->link->read_wait); } } if (tty->driver->set_termios) (*tty->driver->set_termios)(tty, &old_termios); ld = tty_ldisc_ref(tty); if (ld != NULL) { if (ld->set_termios) (ld->set_termios)(tty, &old_termios); tty_ldisc_deref(ld); } up(&tty->termios_sem); }
/** * tty_set_termios - update termios values * @tty: tty to update * @new_termios: desired new value * * Perform updates to the termios values set on this terminal. There * is a bit of layering violation here with n_tty in terms of the * internal knowledge of this function. * * Locking: termios_mutex */ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) { struct ktermios old_termios; struct tty_ldisc *ld; unsigned long flags; /* * Perform the actual termios internal changes under lock. */ /* FIXME: we need to decide on some locking/ordering semantics for the set_termios notification eventually */ mutex_lock(&tty->termios_mutex); old_termios = *tty->termios; *tty->termios = *new_termios; unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { int extproc = (old_termios.c_lflag & EXTPROC) | (tty->termios->c_lflag & EXTPROC); int old_flow = ((old_termios.c_iflag & IXON) && (old_termios.c_cc[VSTOP] == '\023') && (old_termios.c_cc[VSTART] == '\021')); int new_flow = (I_IXON(tty) && STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if ((old_flow != new_flow) || extproc) { spin_lock_irqsave(&tty->ctrl_lock, flags); if (old_flow != new_flow) { tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) tty->ctrl_status |= TIOCPKT_DOSTOP; else tty->ctrl_status |= TIOCPKT_NOSTOP; } if (extproc) tty->ctrl_status |= TIOCPKT_IOCTL; spin_unlock_irqrestore(&tty->ctrl_lock, flags); wake_up_interruptible(&tty->link->read_wait); } } if (tty->ops->set_termios) (*tty->ops->set_termios)(tty, &old_termios); else tty_termios_copy_hw(tty->termios, &old_termios); ld = tty_ldisc_ref(tty); if (ld != NULL) { if (ld->ops->set_termios) (ld->ops->set_termios)(tty, &old_termios); tty_ldisc_deref(ld); } mutex_unlock(&tty->termios_mutex); return 0; }
static int set_termios_2(struct tty_struct * tty, struct termios * termios) { struct termios old_termios = *tty->termios; int canon_change; canon_change = (old_termios.c_lflag ^ termios->c_lflag) & ICANON; cli(); *tty->termios = *termios; if (canon_change) { memset(&tty->secondary_flags, 0, sizeof tty->secondary_flags); tty->canon_head = tty->secondary.tail; tty->canon_data = 0; tty->erasing = 0; } sti(); if (canon_change && !L_ICANON(tty) && !EMPTY(&tty->secondary)) /* Get characters left over from canonical mode. */ wake_up_interruptible(&tty->secondary.proc_list); /* see if packet mode change of state */ if (tty->link && tty->link->packet) { int old_flow = ((old_termios.c_iflag & IXON) && (old_termios.c_cc[VSTOP] == '\023') && (old_termios.c_cc[VSTART] == '\021')); int new_flow = (I_IXON(tty) && STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if (old_flow != new_flow) { tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) tty->ctrl_status |= TIOCPKT_DOSTOP; else tty->ctrl_status |= TIOCPKT_NOSTOP; wake_up_interruptible(&tty->link->secondary.proc_list); } } unset_locked_termios(tty->termios, &old_termios, termios_locked[tty->line]); if (tty->set_termios) (*tty->set_termios)(tty, &old_termios); return 0; }
static void change_termios(struct tty_struct * tty, struct termios * new_termios) { int canon_change; struct termios old_termios = *tty->termios; local_irq_disable(); // FIXME: is this safe? *tty->termios = *new_termios; unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; if (canon_change) { memset(&tty->read_flags, 0, sizeof tty->read_flags); tty->canon_head = tty->read_tail; tty->canon_data = 0; tty->erasing = 0; } local_irq_enable(); // FIXME: is this safe? if (canon_change && !L_ICANON(tty) && tty->read_cnt) /* Get characters left over from canonical mode. */ wake_up_interruptible(&tty->read_wait); /* see if packet mode change of state */ if (tty->link && tty->link->packet) { int old_flow = ((old_termios.c_iflag & IXON) && (old_termios.c_cc[VSTOP] == '\023') && (old_termios.c_cc[VSTART] == '\021')); int new_flow = (I_IXON(tty) && STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if (old_flow != new_flow) { tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) tty->ctrl_status |= TIOCPKT_DOSTOP; else tty->ctrl_status |= TIOCPKT_NOSTOP; wake_up_interruptible(&tty->link->read_wait); } } if (tty->driver->set_termios) (*tty->driver->set_termios)(tty, &old_termios); if (tty->ldisc.set_termios) (*tty->ldisc.set_termios)(tty, &old_termios); }