From d85f0e0bc0ba2ccd3ef351c4db9ad99600211d47 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 7 Aug 2010 15:32:18 +0200 Subject: [PATCH] compat: backport n_tty_ioctl_helper This function is needed by some bluetooth drivers Signed-off-by: Hauke Mehrtens --- compat/compat-2.6.28.c | 128 ++++++++++++++++++++++++++++++++++ include/linux/compat-2.6.28.h | 6 ++ 2 files changed, 134 insertions(+) diff --git a/compat/compat-2.6.28.c b/compat/compat-2.6.28.c index 115bd23a719d..bfb645a8099d 100644 --- a/compat/compat-2.6.28.c +++ b/compat/compat-2.6.28.c @@ -13,6 +13,8 @@ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) #include +#include +#include /* 2.6.28 compat code goes here */ @@ -370,4 +372,130 @@ void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, } EXPORT_SYMBOL(skb_add_rx_frag); +void tty_write_unlock(struct tty_struct *tty) +{ + mutex_unlock(&tty->atomic_write_lock); + wake_up_interruptible_poll(&tty->write_wait, POLLOUT); +} + +int tty_write_lock(struct tty_struct *tty, int ndelay) +{ + if (!mutex_trylock(&tty->atomic_write_lock)) { + if (ndelay) + return -EAGAIN; + if (mutex_lock_interruptible(&tty->atomic_write_lock)) + return -ERESTARTSYS; + } + return 0; +} + +/** + * send_prio_char - send priority character + * + * Send a high priority character to the tty even if stopped + * + * Locking: none for xchar method, write ordering for write method. + */ + +static int send_prio_char(struct tty_struct *tty, char ch) +{ + int was_stopped = tty->stopped; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + if (tty->ops->send_xchar) { + tty->ops->send_xchar(tty, ch); +#else + if (tty->driver->send_xchar) { + tty->driver->send_xchar(tty, ch); +#endif + return 0; + } + + if (tty_write_lock(tty, 0) < 0) + return -ERESTARTSYS; + + if (was_stopped) + start_tty(tty); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + tty->ops->write(tty, &ch, 1); +#else + tty->driver->write(tty, &ch, 1); +#endif + if (was_stopped) + stop_tty(tty); + tty_write_unlock(tty); + return 0; +} + +int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + unsigned long flags; +#endif + int retval; + + switch (cmd) { + case TCXONC: + retval = tty_check_change(tty); + if (retval) + return retval; + switch (arg) { + case TCOOFF: + if (!tty->flow_stopped) { + tty->flow_stopped = 1; + stop_tty(tty); + } + break; + case TCOON: + if (tty->flow_stopped) { + tty->flow_stopped = 0; + start_tty(tty); + } + break; + case TCIOFF: + if (STOP_CHAR(tty) != __DISABLED_CHAR) + return send_prio_char(tty, STOP_CHAR(tty)); + break; + case TCION: + if (START_CHAR(tty) != __DISABLED_CHAR) + return send_prio_char(tty, START_CHAR(tty)); + break; + default: + return -EINVAL; + } + return 0; + case TCFLSH: + return tty_perform_flush(tty, arg); + case TIOCPKT: + { + int pktmode; + + if (tty->driver->type != TTY_DRIVER_TYPE_PTY || + tty->driver->subtype != PTY_TYPE_MASTER) + return -ENOTTY; + if (get_user(pktmode, (int __user *) arg)) + return -EFAULT; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + spin_lock_irqsave(&tty->ctrl_lock, flags); +#endif + if (pktmode) { + if (!tty->packet) { + tty->packet = 1; + tty->link->ctrl_status = 0; + } + } else + tty->packet = 0; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + spin_unlock_irqrestore(&tty->ctrl_lock, flags); +#endif + return 0; + } + default: + /* Try the mode commands */ + return tty_mode_ioctl(tty, file, cmd, arg); + } +} +EXPORT_SYMBOL(n_tty_ioctl_helper); + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) */ diff --git a/include/linux/compat-2.6.28.h b/include/linux/compat-2.6.28.h index 716054888fbd..649fbbc3183c 100644 --- a/include/linux/compat-2.6.28.h +++ b/include/linux/compat-2.6.28.h @@ -230,6 +230,12 @@ unsigned long round_jiffies_up(unsigned long j); extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, int size); +#define wake_up_interruptible_poll(x, m) \ + __wake_up(x, TASK_INTERRUPTIBLE, 1, (void *) (m)) + +extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) */ #endif /* LINUX_26_28_COMPAT_H */ -- 2.30.2