diff options
Diffstat (limited to 'sys/sys')
-rw-r--r-- | sys/sys/tty.h | 10 | ||||
-rw-r--r-- | sys/sys/ttydevsw.h | 4 | ||||
-rw-r--r-- | sys/sys/ttydisc.h | 34 | ||||
-rw-r--r-- | sys/sys/ttyhook.h | 147 |
4 files changed, 157 insertions, 38 deletions
diff --git a/sys/sys/tty.h b/sys/sys/tty.h index 54d487cb495f..2250cbc2b1fd 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -80,6 +80,7 @@ struct tty { #define TF_EXCLUDE 0x1000 /* Exclusive access. */ #define TF_BYPASS 0x2000 /* Optimized input path. */ #define TF_ZOMBIE 0x4000 /* Modem disconnect received. */ +#define TF_HOOK 0x8000 /* TTY has hook attached. */ unsigned int t_revokecnt; /* (t) revoke() count. */ /* Buffering mechanisms. */ @@ -112,13 +113,15 @@ struct tty { struct termios t_termios_lock_out; /* cua%s.lock. */ struct ttydevsw *t_devsw; /* (c) Driver hooks. */ + struct ttyhook *t_hook; /* (t) Capture/inject hook. */ /* Process signal delivery. */ struct pgrp *t_pgrp; /* (t) Foreground process group. */ struct session *t_session; /* (t) Associated session. */ unsigned int t_sessioncnt; /* (t) Backpointing sessions. */ - void *t_softc; /* (c) Soft config, for drivers. */ + void *t_devswsoftc; /* (c) Soft config, for drivers. */ + void *t_hooksoftc; /* (t) Soft config, for hooks. */ struct cdev *t_dev; /* (c) Primary character device. */ }; @@ -181,7 +184,7 @@ void tty_hiwat_in_unblock(struct tty *tp); dev_t tty_udev(struct tty *tp); #define tty_opened(tp) ((tp)->t_flags & TF_OPENED) #define tty_gone(tp) ((tp)->t_flags & TF_GONE) -#define tty_softc(tp) ((tp)->t_softc) +#define tty_softc(tp) ((tp)->t_devswsoftc) #define tty_devname(tp) devtoname((tp)->t_dev) /* Status line printing. */ @@ -192,8 +195,9 @@ int pts_alloc_external(int fd, struct thread *td, struct file *fp, struct cdev *dev, const char *name); /* Drivers and line disciplines also need to call these. */ -#include <sys/ttydevsw.h> #include <sys/ttydisc.h> +#include <sys/ttydevsw.h> +#include <sys/ttyhook.h> #endif /* _KERNEL */ #endif /* !_SYS_TTY_H_ */ diff --git a/sys/sys/ttydevsw.h b/sys/sys/ttydevsw.h index 842143d6d911..e2278c3ab432 100644 --- a/sys/sys/ttydevsw.h +++ b/sys/sys/ttydevsw.h @@ -97,9 +97,7 @@ ttydevsw_outwakeup(struct tty *tp) MPASS(!tty_gone(tp)); /* Prevent spurious wakeups. */ - if (tp->t_flags & TF_STOPPED) - return; - if (ttyoutq_bytesused(&tp->t_outq) == 0) + if (ttydisc_getc_poll(tp) == 0) return; tp->t_devsw->tsw_outwakeup(tp); diff --git a/sys/sys/ttydisc.h b/sys/sys/ttydisc.h index aeaabc6602f6..2ea54666c56a 100644 --- a/sys/sys/ttydisc.h +++ b/sys/sys/ttydisc.h @@ -54,8 +54,10 @@ void ttydisc_modem(struct tty *tp, int open); int ttydisc_rint(struct tty *tp, char c, int flags); size_t ttydisc_rint_bypass(struct tty *tp, const void *buf, size_t len); void ttydisc_rint_done(struct tty *tp); +size_t ttydisc_rint_poll(struct tty *tp); size_t ttydisc_getc(struct tty *tp, void *buf, size_t len); int ttydisc_getc_uio(struct tty *tp, struct uio *uio); +size_t ttydisc_getc_poll(struct tty *tp); /* Error codes for ttydisc_rint(). */ #define TRE_FRAMING 0x01 @@ -81,36 +83,4 @@ ttydisc_write_poll(struct tty *tp) return ttyoutq_bytesleft(&tp->t_outq); } -static __inline size_t -ttydisc_rint_poll(struct tty *tp) -{ - size_t l; - - tty_lock_assert(tp, MA_OWNED); - - /* - * XXX: Still allow character input when there's no space in the - * buffers, but we haven't entered the high watermark. This is - * to allow backspace characters to be inserted when in - * canonical mode. - */ - l = ttyinq_bytesleft(&tp->t_inq); - if (l == 0 && (tp->t_flags & TF_HIWAT_IN) == 0) - return (1); - - return (l); -} - -static __inline size_t -ttydisc_getc_poll(struct tty *tp) -{ - - tty_lock_assert(tp, MA_OWNED); - - if (tp->t_flags & TF_STOPPED) - return (0); - - return ttyoutq_bytesused(&tp->t_outq); -} - #endif /* !_SYS_TTYDISC_H_ */ diff --git a/sys/sys/ttyhook.h b/sys/sys/ttyhook.h new file mode 100644 index 000000000000..7a0a0bc13f52 --- /dev/null +++ b/sys/sys/ttyhook.h @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_TTYHOOK_H_ +#define _SYS_TTYHOOK_H_ + +#ifndef _SYS_TTY_H_ +#error "can only be included through <sys/tty.h>" +#endif /* !_SYS_TTY_H_ */ + +struct tty; + +/* + * Hooks interface, which allows to capture and inject traffic into the + * input and output paths of a TTY. + */ + +typedef int th_rint_t(struct tty *tp, char c, int flags); +typedef size_t th_rint_bypass_t(struct tty *tp, const void *buf, size_t len); +typedef void th_rint_done_t(struct tty *tp); +typedef size_t th_rint_poll_t(struct tty *tp); + +typedef size_t th_getc_inject_t(struct tty *tp, void *buf, size_t len); +typedef void th_getc_capture_t(struct tty *tp, const void *buf, size_t len); +typedef size_t th_getc_poll_t(struct tty *tp); + +typedef void th_close_t(struct tty *tp); + +struct ttyhook { + /* Character input. */ + th_rint_t *th_rint; + th_rint_bypass_t *th_rint_bypass; + th_rint_done_t *th_rint_done; + th_rint_poll_t *th_rint_poll; + + /* Character output. */ + th_getc_inject_t *th_getc_inject; + th_getc_capture_t *th_getc_capture; + th_getc_poll_t *th_getc_poll; + + th_close_t *th_close; +}; + +int ttyhook_register(struct tty **, struct thread *, int, + struct ttyhook *, void *); +void ttyhook_unregister(struct tty *); +#define ttyhook_softc(tp) ((tp)->t_hooksoftc) +#define ttyhook_hashook(tp,hook) ((tp)->t_hook != NULL && \ + (tp)->t_hook->th_ ## hook != NULL) + +static __inline int +ttyhook_rint(struct tty *tp, char c, int flags) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + return tp->t_hook->th_rint(tp, c, flags); +} + +static __inline size_t +ttyhook_rint_bypass(struct tty *tp, const void *buf, size_t len) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + return tp->t_hook->th_rint_bypass(tp, buf, len); +} + +static __inline void +ttyhook_rint_done(struct tty *tp) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + tp->t_hook->th_rint_done(tp); +} + +static __inline size_t +ttyhook_rint_poll(struct tty *tp) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + return tp->t_hook->th_rint_poll(tp); +} + +static __inline size_t +ttyhook_getc_inject(struct tty *tp, void *buf, size_t len) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + return tp->t_hook->th_getc_inject(tp, buf, len); +} + +static __inline void +ttyhook_getc_capture(struct tty *tp, const void *buf, size_t len) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + tp->t_hook->th_getc_capture(tp, buf, len); +} + +static __inline size_t +ttyhook_getc_poll(struct tty *tp) +{ + tty_lock_assert(tp, MA_OWNED); + MPASS(!tty_gone(tp)); + + return tp->t_hook->th_getc_poll(tp); +} + +static __inline void +ttyhook_close(struct tty *tp) +{ + tty_lock_assert(tp, MA_OWNED); + + tp->t_hook->th_close(tp); +} + +#endif /* !_SYS_TTYHOOK_H_ */ |