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
48void *wsemul_dumb_cnattach(const struct wsscreen_descr *, void *,
49 int, int, long);
50void *wsemul_dumb_attach(int console, const struct wsscreen_descr *,
51 void *, int, int, void *, long);
52void wsemul_dumb_output(void *cookie, const u_char *data, u_int count, int);
53int wsemul_dumb_translate(void *cookie, keysym_t, const char **);
54void wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp);
55void wsemul_dumb_resetop(void *, enum wsemul_resetops);
56
57const 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
69struct 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
77struct wsemul_dumb_emuldata wsemul_dumb_console_emuldata;
78
79void *
80wsemul_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
99void *
100wsemul_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
124void
125wsemul_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
203int
204wsemul_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
218void
219wsemul_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
229void
230wsemul_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