1 /* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved 4 * Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 * 6 * Permission is hereby granted, free of charge, to any person 7 * obtaining a copy of this software and associated documentation 8 * files (the "Software"), to deal in the Software without 9 * restriction, including without limitation the rights to use, 10 * copy, modify, merge, publish, distribute, sublicense, and/or 11 * sell copies of the Software, and to permit persons to whom 12 * the Software is furnished to do so, subject to the following 13 * conditions: 14 * 15 * The above copyright notice and this permission notice shall 16 * be included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * ----------------------------------------------------------------------- */ 28 29 /* 30 * vesacon_write.c 31 * 32 * Write to the screen using ANSI control codes (about as capable as 33 * DOS' ANSI.SYS.) 34 */ 35 36 #include <errno.h> 37 #include <string.h> 38 #include <com32.h> 39 #include <minmax.h> 40 #include <colortbl.h> 41 #include <console.h> 42 #include <klibc/compiler.h> 43 #include <syslinux/config.h> 44 #include "ansi.h" 45 #include "file.h" 46 #include "vesa/video.h" 47 48 static void vesacon_erase(const struct term_state *, int, int, int, int); 49 static void vesacon_write_char(int, int, uint8_t, const struct term_state *); 50 static void vesacon_showcursor(const struct term_state *); 51 static void vesacon_setcursor(int x, int y, bool visible); 52 static void vesacon_scroll_up(const struct term_state *); 53 54 static struct term_state ts; 55 static struct ansi_ops op = { 56 .erase = vesacon_erase, 57 .write_char = vesacon_write_char, 58 .showcursor = vesacon_showcursor, 59 .set_cursor = vesacon_setcursor, 60 .scroll_up = vesacon_scroll_up, 61 .beep = __ansicon_beep, 62 }; 63 64 static struct term_info ti = { 65 .disabled = 0, 66 .ts = &ts, 67 .op = &op 68 }; 69 70 /* Reference counter to the screen, to keep track of if we need 71 reinitialization. */ 72 static int vesacon_counter = 0; 73 74 static struct { 75 int x, y; 76 } vesacon_resolution = { 77 .x = DEFAULT_VESA_X_SIZE, 78 .y = DEFAULT_VESA_Y_SIZE, 79 }; 80 81 /* Set desired resolution - requires a full close/open cycle */ 82 void vesacon_set_resolution(int x, int y) 83 { 84 vesacon_resolution.x = x; 85 vesacon_resolution.y = y; 86 } 87 88 /* Common setup */ 89 int __vesacon_open(struct file_info *fp) 90 { 91 (void)fp; 92 93 if (!vesacon_counter) { 94 /* Are we disabled? */ 95 if (syslinux_serial_console_info()->flowctl & 0x8000) { 96 ti.disabled = 1; 97 ti.rows = 25; 98 ti.cols = 80; 99 } else { 100 /* Switch mode */ 101 /* Deal with a resolution different from default build */ 102 if (__vesacon_init(&vesacon_resolution.x, &vesacon_resolution.y)) { 103 vesacon_counter = -1; 104 return EAGAIN; 105 } 106 107 /* Initial state */ 108 __ansi_init(&ti); 109 ti.rows = __vesacon_text_rows; 110 ti.cols = __vesacon_text_cols; 111 } 112 } else if (vesacon_counter == -1) { 113 return EAGAIN; 114 } 115 116 fp->o.rows = ti.rows; 117 fp->o.cols = ti.cols; 118 119 vesacon_counter++; 120 return 0; 121 } 122 123 int __vesacon_close(struct file_info *fp) 124 { 125 (void)fp; 126 127 vesacon_counter--; 128 return 0; 129 } 130 131 /* Erase a region of the screen */ 132 static void vesacon_erase(const struct term_state *st, 133 int x0, int y0, int x1, int y1) 134 { 135 __vesacon_erase(x0, y0, x1, y1, st->cindex); 136 } 137 138 /* Draw text on the screen */ 139 static void vesacon_write_char(int x, int y, uint8_t ch, 140 const struct term_state *st) 141 { 142 __vesacon_write_char(x, y, ch, st->cindex); 143 } 144 145 /* Show or hide the cursor */ 146 static bool cursor_enabled = true; 147 void vesacon_cursor_enable(bool enabled) 148 { 149 cursor_enabled = enabled; 150 } 151 static void vesacon_showcursor(const struct term_state *st) 152 { 153 vesacon_setcursor(st->xy.x, st->xy.y, st->cursor); 154 } 155 static void vesacon_setcursor(int x, int y, bool visible) 156 { 157 __vesacon_set_cursor(x, y, visible && cursor_enabled); 158 } 159 160 static void vesacon_scroll_up(const struct term_state *st) 161 { 162 __vesacon_scroll_up(1, st->cindex); 163 } 164 165 ssize_t __vesacon_write(struct file_info *fp, const void *buf, size_t count) 166 { 167 const unsigned char *bufp = buf; 168 size_t n = 0; 169 170 (void)fp; 171 172 if (ti.disabled) 173 return count; /* Nothing to do */ 174 175 /* This only updates the shadow text buffer... */ 176 while (count--) { 177 __ansi_putchar(&ti, *bufp++); 178 n++; 179 } 180 181 /* This actually draws it */ 182 __vesacon_doit(); 183 184 return n; 185 } 186 187 const struct output_dev dev_vesacon_w = { 188 .dev_magic = __DEV_MAGIC, 189 .flags = __DEV_TTY | __DEV_OUTPUT, 190 .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 191 .write = __vesacon_write, 192 .close = __vesacon_close, 193 .open = __vesacon_open, 194 .fallback = &dev_ansicon_w, 195 }; 196