xref: /netbsd/sys/dev/wscons/wsemul_dumb.c (revision 6550d01e)
1 /* $NetBSD: wsemul_dumb.c,v 1.15 2010/01/28 22:36:19 drochner Exp $ */
2 
3 /*
4  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Christopher G. Demetriou
17  *	for the NetBSD Project.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: wsemul_dumb.c,v 1.15 2010/01/28 22:36:19 drochner Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/time.h>
39 #include <sys/malloc.h>
40 #include <sys/fcntl.h>
41 
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/wscons/wsdisplayvar.h>
44 #include <dev/wscons/wsemulvar.h>
45 #include <dev/wscons/ascii.h>
46 #include <dev/wscons/wsksymdef.h>
47 
48 void	*wsemul_dumb_cnattach(const struct wsscreen_descr *, void *,
49 				   int, int, long);
50 void	*wsemul_dumb_attach(int console, const struct wsscreen_descr *,
51 				 void *, int, int, void *, long);
52 void	wsemul_dumb_output(void *cookie, const u_char *data, u_int count, int);
53 int	wsemul_dumb_translate(void *cookie, keysym_t, const char **);
54 void	wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp);
55 void	wsemul_dumb_resetop(void *, enum wsemul_resetops);
56 
57 const struct wsemul_ops wsemul_dumb_ops = {
58 	"dumb",
59 	wsemul_dumb_cnattach,
60 	wsemul_dumb_attach,
61 	wsemul_dumb_output,
62 	wsemul_dumb_translate,
63 	wsemul_dumb_detach,
64 	wsemul_dumb_resetop,
65 	NULL,	/* getmsgattrs */
66 	NULL,	/* setmsgattrs */
67 };
68 
69 struct wsemul_dumb_emuldata {
70 	const struct wsdisplay_emulops *emulops;
71 	void *emulcookie;
72 	void *cbcookie;
73 	u_int nrows, ncols, crow, ccol;
74 	long defattr;
75 };
76 
77 struct wsemul_dumb_emuldata wsemul_dumb_console_emuldata;
78 
79 void *
80 wsemul_dumb_cnattach(const struct wsscreen_descr *type, void *cookie,
81 	int ccol, int crow, long defattr)
82 {
83 	struct wsemul_dumb_emuldata *edp;
84 
85 	edp = &wsemul_dumb_console_emuldata;
86 
87 	edp->emulops = type->textops;
88 	edp->emulcookie = cookie;
89 	edp->nrows = type->nrows;
90 	edp->ncols = type->ncols;
91 	edp->crow = crow;
92 	edp->ccol = ccol;
93 	edp->defattr = defattr;
94 	edp->cbcookie = NULL;
95 
96 	return (edp);
97 }
98 
99 void *
100 wsemul_dumb_attach(int console, const struct wsscreen_descr *type,
101 	void *cookie, int ccol, int crow, void *cbcookie, long defattr)
102 {
103 	struct wsemul_dumb_emuldata *edp;
104 
105 	if (console)
106 		edp = &wsemul_dumb_console_emuldata;
107 	else {
108 		edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
109 
110 		edp->emulops = type->textops;
111 		edp->emulcookie = cookie;
112 		edp->nrows = type->nrows;
113 		edp->ncols = type->ncols;
114 		edp->crow = crow;
115 		edp->ccol = ccol;
116 		edp->defattr = defattr;
117 	}
118 
119 	edp->cbcookie = cbcookie;
120 
121 	return (edp);
122 }
123 
124 void
125 wsemul_dumb_output(void *cookie, const u_char *data, u_int count,
126     int kernel)
127 {
128 	struct wsemul_dumb_emuldata *edp = cookie;
129 	u_char c;
130 	int n;
131 
132 	/* XXX */
133 	(*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol);
134 	while (count-- > 0) {
135 		c = *data++;
136 		switch (c) {
137 		case ASCII_BEL:
138 			wsdisplay_emulbell(edp->cbcookie);
139 			break;
140 
141 		case ASCII_BS:
142 			if (edp->ccol > 0)
143 				edp->ccol--;
144 			break;
145 
146 		case ASCII_CR:
147 			edp->ccol = 0;
148 			break;
149 
150 		case ASCII_HT:
151 			n = min(8 - (edp->ccol & 7),
152 			    edp->ncols - edp->ccol - 1);
153 			(*edp->emulops->erasecols)(edp->emulcookie,
154 			    edp->crow, edp->ccol, n, edp->defattr);
155 			edp->ccol += n;
156 			break;
157 
158 		case ASCII_FF:
159 			(*edp->emulops->eraserows)(edp->emulcookie, 0,
160 			    edp->nrows, edp->defattr);
161 			edp->ccol = 0;
162 			edp->crow = 0;
163 			break;
164 
165 		case ASCII_VT:
166 			if (edp->crow > 0)
167 				edp->crow--;
168 			break;
169 
170 		default:
171 			(*edp->emulops->putchar)(edp->emulcookie, edp->crow,
172 			    edp->ccol, c, edp->defattr);
173 			edp->ccol++;
174 
175 			/* if cur col is still on cur line, done. */
176 			if (edp->ccol < edp->ncols)
177 				break;
178 
179 			/* wrap the column around. */
180 			edp->ccol = 0;
181 
182                 	/* FALLTHRU */
183 
184 		case ASCII_LF:
185 	                /* if the cur line isn't the last, incr and leave. */
186 			if (edp->crow < edp->nrows - 1) {
187 				edp->crow++;
188 				break;
189 			}
190 			n = 1;		/* number of lines to scroll */
191 			(*edp->emulops->copyrows)(edp->emulcookie, n, 0,
192 			    edp->nrows - n);
193 			(*edp->emulops->eraserows)(edp->emulcookie,
194 			    edp->nrows - n, n, edp->defattr);
195 			edp->crow -= n - 1;
196 			break;
197 		}
198 	}
199 	/* XXX */
200 	(*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol);
201 }
202 
203 int
204 wsemul_dumb_translate(void *cookie, keysym_t in,
205     const char **out)
206 {
207 	static char c;
208 
209 	if (KS_GROUP(in) == KS_GROUP_Plain) {
210 		/* allow ISO-1 */
211 		c = KS_VALUE(in);
212 		*out = &c;
213 		return (1);
214 	}
215 	return (0);
216 }
217 
218 void
219 wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp)
220 {
221 	struct wsemul_dumb_emuldata *edp = cookie;
222 
223 	*crowp = edp->crow;
224 	*ccolp = edp->ccol;
225 	if (edp != &wsemul_dumb_console_emuldata)
226 		free(edp, M_DEVBUF);
227 }
228 
229 void
230 wsemul_dumb_resetop(void *cookie, enum wsemul_resetops op)
231 {
232 	struct wsemul_dumb_emuldata *edp = cookie;
233 
234 	switch (op) {
235 	case WSEMUL_CLEARSCREEN:
236 		(*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows,
237 					   edp->defattr);
238 		edp->ccol = edp->crow = 0;
239 		(*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0);
240 		break;
241 	default:
242 		break;
243 	}
244 }
245