From ec19f7ffdc262007a4b438c1bc105128039b2bd9 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 21 Feb 2011 14:32:24 -0800 Subject: [PATCH] compat: backport tty_set_termios This code is copied from the kernel sources. Signed-off-by: Hauke Mehrtens --- compat/Makefile | 1 + compat/compat-2.6.39.c | 111 ++++++++++++++++++++++++++++++++++ include/linux/compat-2.6.39.h | 7 +++ 3 files changed, 119 insertions(+) create mode 100644 compat/compat-2.6.39.c diff --git a/compat/Makefile b/compat/Makefile index 9c042caa0da1..f87b024ac10b 100644 --- a/compat/Makefile +++ b/compat/Makefile @@ -29,3 +29,4 @@ compat-$(CONFIG_COMPAT_KERNEL_35) += compat-2.6.35.o compat-$(CONFIG_COMPAT_KERNEL_36) += compat-2.6.36.o compat-$(CONFIG_COMPAT_KERNEL_37) += compat-2.6.37.o compat-$(CONFIG_COMPAT_KERNEL_38) += compat-2.6.38.o +compat-$(CONFIG_COMPAT_KERNEL_39) += compat-2.6.39.o diff --git a/compat/compat-2.6.39.c b/compat/compat-2.6.39.c new file mode 100644 index 000000000000..c2966f714724 --- /dev/null +++ b/compat/compat-2.6.39.c @@ -0,0 +1,111 @@ +/* + * Copyright 2011 Hauke Mehrtens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Compatibility file for Linux wireless for kernels 2.6.39. + */ + +#include +#include + +/* + * Termios Helper Methods + */ +static void unset_locked_termios(struct ktermios *termios, + struct ktermios *old, + struct ktermios *locked) +{ + int i; + +#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z))) + + if (!locked) { + printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n"); + return; + } + + NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag); + NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag); + NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); + NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag); + termios->c_line = locked->c_line ? old->c_line : termios->c_line; + for (i = 0; i < NCCS; i++) + termios->c_cc[i] = locked->c_cc[i] ? + old->c_cc[i] : termios->c_cc[i]; + /* FIXME: What should we do for i/ospeed */ +} + +/** + * 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; +} +EXPORT_SYMBOL_GPL(tty_set_termios); + diff --git a/include/linux/compat-2.6.39.h b/include/linux/compat-2.6.39.h index c0c98fdb6d61..1c7b322c9b50 100644 --- a/include/linux/compat-2.6.39.h +++ b/include/linux/compat-2.6.39.h @@ -5,6 +5,8 @@ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) +#include + /* * This is not part of The 2.6.37 kernel yet but we * we use it to optimize the backport code we @@ -22,6 +24,11 @@ #define br_port_exists(dev) (dev->br_port) #endif +#define tiocmget(tty) tiocmget(tty, NULL) +#define tiocmset(tty, set, clear) tiocmset(tty, NULL, set, clear) + +extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt); + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) */ #endif /* LINUX_26_39_COMPAT_H */ -- 2.30.2