Home | History | Annotate | Download | only in sys
      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