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