aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_io.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-22 06:18:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:03:28 -0400
commit9e98966c7bb94355689478bc84cc3e0c190f977e (patch)
tree928aebbfee524a48aa94a3d3def5249c8846a79a /drivers/char/tty_io.c
parentabbe629ae4011d2020047f41bea9f9e4b0ec4361 (diff)
tty: rework break handling
Some hardware needs to do break handling itself and may have partial support only. Make break_ctl return an error code. Add a tty driver flag so you can indicate driver hardware side break support. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r--drivers/char/tty_io.c71
1 files changed, 28 insertions, 43 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index d27a08b374d..d94cd8410c5 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2849,16 +2849,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
2849 2849
2850static int send_break(struct tty_struct *tty, unsigned int duration) 2850static int send_break(struct tty_struct *tty, unsigned int duration)
2851{ 2851{
2852 if (tty_write_lock(tty, 0) < 0) 2852 int retval;
2853 return -EINTR; 2853
2854 tty->ops->break_ctl(tty, -1); 2854 if (tty->ops->break_ctl == NULL)
2855 if (!signal_pending(current)) 2855 return 0;
2856 msleep_interruptible(duration); 2856
2857 tty->ops->break_ctl(tty, 0); 2857 if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
2858 tty_write_unlock(tty); 2858 retval = tty->ops->break_ctl(tty, duration);
2859 if (signal_pending(current)) 2859 else {
2860 return -EINTR; 2860 /* Do the work ourselves */
2861 return 0; 2861 if (tty_write_lock(tty, 0) < 0)
2862 return -EINTR;
2863 retval = tty->ops->break_ctl(tty, -1);
2864 if (retval)
2865 goto out;
2866 if (!signal_pending(current))
2867 msleep_interruptible(duration);
2868 retval = tty->ops->break_ctl(tty, 0);
2869out:
2870 tty_write_unlock(tty);
2871 if (signal_pending(current))
2872 retval = -EINTR;
2873 }
2874 return retval;
2862} 2875}
2863 2876
2864/** 2877/**
@@ -2949,36 +2962,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2949 tty->driver->subtype == PTY_TYPE_MASTER) 2962 tty->driver->subtype == PTY_TYPE_MASTER)
2950 real_tty = tty->link; 2963 real_tty = tty->link;
2951 2964
2952 /*
2953 * Break handling by driver
2954 */
2955
2956 retval = -EINVAL;
2957
2958 if (!tty->ops->break_ctl) {
2959 switch (cmd) {
2960 case TIOCSBRK:
2961 case TIOCCBRK:
2962 if (tty->ops->ioctl)
2963 retval = tty->ops->ioctl(tty, file, cmd, arg);
2964 if (retval != -EINVAL && retval != -ENOIOCTLCMD)
2965 printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
2966 return retval;
2967
2968 /* These two ioctl's always return success; even if */
2969 /* the driver doesn't support them. */
2970 case TCSBRK:
2971 case TCSBRKP:
2972 if (!tty->ops->ioctl)
2973 return 0;
2974 retval = tty->ops->ioctl(tty, file, cmd, arg);
2975 if (retval != -EINVAL && retval != -ENOIOCTLCMD)
2976 printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
2977 if (retval == -ENOIOCTLCMD)
2978 retval = 0;
2979 return retval;
2980 }
2981 }
2982 2965
2983 /* 2966 /*
2984 * Factor out some common prep work 2967 * Factor out some common prep work
@@ -3000,6 +2983,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3000 break; 2983 break;
3001 } 2984 }
3002 2985
2986 /*
2987 * Now do the stuff.
2988 */
3003 switch (cmd) { 2989 switch (cmd) {
3004 case TIOCSTI: 2990 case TIOCSTI:
3005 return tiocsti(tty, p); 2991 return tiocsti(tty, p);
@@ -3043,12 +3029,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3043 */ 3029 */
3044 case TIOCSBRK: /* Turn break on, unconditionally */ 3030 case TIOCSBRK: /* Turn break on, unconditionally */
3045 if (tty->ops->break_ctl) 3031 if (tty->ops->break_ctl)
3046 tty->ops->break_ctl(tty, -1); 3032 return tty->ops->break_ctl(tty, -1);
3047 return 0; 3033 return 0;
3048
3049 case TIOCCBRK: /* Turn break off, unconditionally */ 3034 case TIOCCBRK: /* Turn break off, unconditionally */
3050 if (tty->ops->break_ctl) 3035 if (tty->ops->break_ctl)
3051 tty->ops->break_ctl(tty, 0); 3036 return tty->ops->break_ctl(tty, 0);
3052 return 0; 3037 return 0;
3053 case TCSBRK: /* SVID version: non-zero arg --> no break */ 3038 case TCSBRK: /* SVID version: non-zero arg --> no break */
3054 /* non-zero arg means wait for all output data 3039 /* non-zero arg means wait for all output data