aboutsummaryrefslogtreecommitdiff
path: root/sys/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys/sys')
-rw-r--r--sys/sys/tty.h10
-rw-r--r--sys/sys/ttydevsw.h4
-rw-r--r--sys/sys/ttydisc.h34
-rw-r--r--sys/sys/ttyhook.h147
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_ */