diff options
author | Alan Cox <alan@redhat.com> | 2008-07-22 06:18:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:03:28 -0400 |
commit | 9e98966c7bb94355689478bc84cc3e0c190f977e (patch) | |
tree | 928aebbfee524a48aa94a3d3def5249c8846a79a /drivers/char/tty_io.c | |
parent | abbe629ae4011d2020047f41bea9f9e4b0ec4361 (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.c | 71 |
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 | ||
2850 | static int send_break(struct tty_struct *tty, unsigned int duration) | 2850 | static 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); | ||
2869 | out: | ||
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 |