1/*-
2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#ifndef _SYS_TTYHOOK_H_
30#define	_SYS_TTYHOOK_H_
31
32#ifndef _SYS_TTY_H_
33#error "can only be included through <sys/tty.h>"
34#endif /* !_SYS_TTY_H_ */
35
36struct tty;
37
38/*
39 * Hooks interface, which allows to capture and inject traffic into the
40 * input and output paths of a TTY.
41 */
42
43typedef int th_rint_t(struct tty *tp, char c, int flags);
44typedef size_t th_rint_bypass_t(struct tty *tp, const void *buf, size_t len);
45typedef void th_rint_done_t(struct tty *tp);
46typedef size_t th_rint_poll_t(struct tty *tp);
47
48typedef size_t th_getc_inject_t(struct tty *tp, void *buf, size_t len);
49typedef void th_getc_capture_t(struct tty *tp, const void *buf, size_t len);
50typedef size_t th_getc_poll_t(struct tty *tp);
51
52typedef void th_close_t(struct tty *tp);
53
54struct ttyhook {
55	/* Character input. */
56	th_rint_t		*th_rint;
57	th_rint_bypass_t	*th_rint_bypass;
58	th_rint_done_t		*th_rint_done;
59	th_rint_poll_t		*th_rint_poll;
60
61	/* Character output. */
62	th_getc_inject_t	*th_getc_inject;
63	th_getc_capture_t	*th_getc_capture;
64	th_getc_poll_t		*th_getc_poll;
65
66	th_close_t		*th_close;
67};
68
69int	ttyhook_register(struct tty **, struct proc *, int,
70    struct ttyhook *, void *);
71void	ttyhook_unregister(struct tty *);
72#define	ttyhook_softc(tp)		((tp)->t_hooksoftc)
73#define	ttyhook_hashook(tp,hook)	((tp)->t_hook != NULL && \
74					(tp)->t_hook->th_ ## hook != NULL)
75
76static __inline int
77ttyhook_rint(struct tty *tp, char c, int flags)
78{
79	tty_lock_assert(tp, MA_OWNED);
80	MPASS(!tty_gone(tp));
81
82	return tp->t_hook->th_rint(tp, c, flags);
83}
84
85static __inline size_t
86ttyhook_rint_bypass(struct tty *tp, const void *buf, size_t len)
87{
88	tty_lock_assert(tp, MA_OWNED);
89	MPASS(!tty_gone(tp));
90
91	return tp->t_hook->th_rint_bypass(tp, buf, len);
92}
93
94static __inline void
95ttyhook_rint_done(struct tty *tp)
96{
97	tty_lock_assert(tp, MA_OWNED);
98	MPASS(!tty_gone(tp));
99
100	tp->t_hook->th_rint_done(tp);
101}
102
103static __inline size_t
104ttyhook_rint_poll(struct tty *tp)
105{
106	tty_lock_assert(tp, MA_OWNED);
107	MPASS(!tty_gone(tp));
108
109	return tp->t_hook->th_rint_poll(tp);
110}
111
112static __inline size_t
113ttyhook_getc_inject(struct tty *tp, void *buf, size_t len)
114{
115	tty_lock_assert(tp, MA_OWNED);
116	MPASS(!tty_gone(tp));
117
118	return tp->t_hook->th_getc_inject(tp, buf, len);
119}
120
121static __inline void
122ttyhook_getc_capture(struct tty *tp, const void *buf, size_t len)
123{
124	tty_lock_assert(tp, MA_OWNED);
125	MPASS(!tty_gone(tp));
126
127	tp->t_hook->th_getc_capture(tp, buf, len);
128}
129
130static __inline size_t
131ttyhook_getc_poll(struct tty *tp)
132{
133	tty_lock_assert(tp, MA_OWNED);
134	MPASS(!tty_gone(tp));
135
136	return tp->t_hook->th_getc_poll(tp);
137}
138
139static __inline void
140ttyhook_close(struct tty *tp)
141{
142	tty_lock_assert(tp, MA_OWNED);
143
144	tp->t_hook->th_close(tp);
145}
146
147#endif /* !_SYS_TTYHOOK_H_ */
148