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