xref: /netbsd/sys/dev/wscons/wsemul_dumb.c (revision a8a5c538)
1 /* $NetBSD: wsemul_dumb.c,v 1.18 2018/09/03 16:29:34 riastradh 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.18 2018/09/03 16:29:34 riastradh 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 	.name = "dumb",
59 	.cnattach = wsemul_dumb_cnattach,
60 	.attach = wsemul_dumb_attach,
61 	.output = wsemul_dumb_output,
62 	.translate = wsemul_dumb_translate,
63 	.detach = wsemul_dumb_detach,
64 	.reset = wsemul_dumb_resetop,
65 	.getmsgattrs = NULL,
66 	.setmsgattrs = NULL,
67 	.resize = NULL,
68 };
69 
70 struct wsemul_dumb_emuldata {
71 	const struct wsdisplay_emulops *emulops;
72 	void *emulcookie;
73 	void *cbcookie;
74 	u_int nrows, ncols, crow, ccol;
75 	long defattr;
76 };
77 
78 struct wsemul_dumb_emuldata wsemul_dumb_console_emuldata;
79 
80 void *
wsemul_dumb_cnattach(const struct wsscreen_descr * type,void * cookie,int ccol,int crow,long defattr)81 wsemul_dumb_cnattach(const struct wsscreen_descr *type, void *cookie,
82 	int ccol, int crow, long defattr)
83 {
84 	struct wsemul_dumb_emuldata *edp;
85 
86 	edp = &wsemul_dumb_console_emuldata;
87 
88 	edp->emulops = type->textops;
89 	edp->emulcookie = cookie;
90 	edp->nrows = type->nrows;
91 	edp->ncols = type->ncols;
92 	edp->crow = crow;
93 	edp->ccol = ccol;
94 	edp->defattr = defattr;
95 	edp->cbcookie = NULL;
96 
97 	return (edp);
98 }
99 
100 void *
wsemul_dumb_attach(int console,const struct wsscreen_descr * type,void * cookie,int ccol,int crow,void * cbcookie,long defattr)101 wsemul_dumb_attach(int console, const struct wsscreen_descr *type,
102 	void *cookie, int ccol, int crow, void *cbcookie, long defattr)
103 {
104 	struct wsemul_dumb_emuldata *edp;
105 
106 	if (console)
107 		edp = &wsemul_dumb_console_emuldata;
108 	else {
109 		edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
110 
111 		edp->emulops = type->textops;
112 		edp->emulcookie = cookie;
113 		edp->nrows = type->nrows;
114 		edp->ncols = type->ncols;
115 		edp->crow = crow;
116 		edp->ccol = ccol;
117 		edp->defattr = defattr;
118 	}
119 
120 	edp->cbcookie = cbcookie;
121 
122 	return (edp);
123 }
124 
125 void
wsemul_dumb_output(void * cookie,const u_char * data,u_int count,int kernel)126 wsemul_dumb_output(void *cookie, const u_char *data, u_int count,
127     int kernel)
128 {
129 	struct wsemul_dumb_emuldata *edp = cookie;
130 	u_char c;
131 	int n;
132 
133 	/* XXX */
134 	(*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol);
135 	while (count-- > 0) {
136 		c = *data++;
137 		switch (c) {
138 		case ASCII_BEL:
139 			wsdisplay_emulbell(edp->cbcookie);
140 			break;
141 
142 		case ASCII_BS:
143 			if (edp->ccol > 0)
144 				edp->ccol--;
145 			break;
146 
147 		case ASCII_CR:
148 			edp->ccol = 0;
149 			break;
150 
151 		case ASCII_HT:
152 			n = uimin(8 - (edp->ccol & 7),
153 			    edp->ncols - edp->ccol - 1);
154 			(*edp->emulops->erasecols)(edp->emulcookie,
155 			    edp->crow, edp->ccol, n, edp->defattr);
156 			edp->ccol += n;
157 			break;
158 
159 		case ASCII_FF:
160 			(*edp->emulops->eraserows)(edp->emulcookie, 0,
161 			    edp->nrows, edp->defattr);
162 			edp->ccol = 0;
163 			edp->crow = 0;
164 			break;
165 
166 		case ASCII_VT:
167 			if (edp->crow > 0)
168 				edp->crow--;
169 			break;
170 
171 		default:
172 			(*edp->emulops->putchar)(edp->emulcookie, edp->crow,
173 			    edp->ccol, c, edp->defattr);
174 			edp->ccol++;
175 
176 			/* if cur col is still on cur line, done. */
177 			if (edp->ccol < edp->ncols)
178 				break;
179 
180 			/* wrap the column around. */
181 			edp->ccol = 0;
182 
183                 	/* FALLTHRU */
184 
185 		case ASCII_LF:
186 	                /* if the cur line isn't the last, incr and leave. */
187 			if (edp->crow < edp->nrows - 1) {
188 				edp->crow++;
189 				break;
190 			}
191 			n = 1;		/* number of lines to scroll */
192 			(*edp->emulops->copyrows)(edp->emulcookie, n, 0,
193 			    edp->nrows - n);
194 			(*edp->emulops->eraserows)(edp->emulcookie,
195 			    edp->nrows - n, n, edp->defattr);
196 			edp->crow -= n - 1;
197 			break;
198 		}
199 	}
200 	/* XXX */
201 	(*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol);
202 }
203 
204 int
wsemul_dumb_translate(void * cookie,keysym_t in,const char ** out)205 wsemul_dumb_translate(void *cookie, keysym_t in,
206     const char **out)
207 {
208 	static char c;
209 
210 	if (KS_GROUP(in) == KS_GROUP_Plain) {
211 		/* allow ISO-1 */
212 		c = KS_VALUE(in);
213 		*out = &c;
214 		return (1);
215 	}
216 	return (0);
217 }
218 
219 void
wsemul_dumb_detach(void * cookie,u_int * crowp,u_int * ccolp)220 wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp)
221 {
222 	struct wsemul_dumb_emuldata *edp = cookie;
223 
224 	*crowp = edp->crow;
225 	*ccolp = edp->ccol;
226 	if (edp != &wsemul_dumb_console_emuldata)
227 		free(edp, M_DEVBUF);
228 }
229 
230 void
wsemul_dumb_resetop(void * cookie,enum wsemul_resetops op)231 wsemul_dumb_resetop(void *cookie, enum wsemul_resetops op)
232 {
233 	struct wsemul_dumb_emuldata *edp = cookie;
234 
235 	switch (op) {
236 	case WSEMUL_CLEARSCREEN:
237 		(*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows,
238 					   edp->defattr);
239 		edp->ccol = edp->crow = 0;
240 		(*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0);
241 		break;
242 	default:
243 		break;
244 	}
245 }
246