176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- *
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Permission is hereby granted, free of charge, to any person
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   obtaining a copy of this software and associated documentation
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   files (the "Software"), to deal in the Software without
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   restriction, including without limitation the rights to use,
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   copy, modify, merge, publish, distribute, sublicense, and/or
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   sell copies of the Software, and to permit persons to whom
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   the Software is furnished to do so, subject to the following
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   conditions:
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   The above copyright notice and this permission notice shall
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   be included in all copies or substantial portions of the Software.
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   OTHER DEALINGS IN THE SOFTWARE.
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * xserial_write.c
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Raw writing to the serial port; \n -> \r\n translation, and
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * convert \1# sequences.
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h>
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <com32.h>
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <core.h>
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <minmax.h>
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <colortbl.h>
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/config.h>
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "file.h"
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void emit(char ch)
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    write_serial(ch);
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanssize_t __xserial_write(struct file_info *fp, const void *buf, size_t count)
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const char *bufp = buf;
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    size_t n = 0;
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static enum { st_init, st_tbl, st_tblc } state = st_init;
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static int ndigits;
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static int ncolor = 0;
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int num;
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const char *p;
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    (void)fp;
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!syslinux_serial_console_info()->iobase)
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return count;		/* Nothing to do */
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (count--) {
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	unsigned char ch = *bufp++;
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	switch (state) {
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case st_init:
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (ch >= 1 && ch <= 5) {
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		state = st_tbl;
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ndigits = ch;
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    } else if (ch == '\n') {
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		emit('\r');
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		emit('\n');
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    } else {
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		emit(ch);
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case st_tbl:
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (ch == '#') {
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		state = st_tblc;
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ncolor = 0;
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    } else {
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		state = st_init;
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case st_tblc:
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    num = ch - '0';
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (num < 10) {
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ncolor = (ncolor * 10) + num;
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if (--ndigits == 0) {
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    if (ncolor < console_color_table_size) {
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			emit('\033');
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			emit('[');
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			emit('0');
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			emit(';');
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			for (p = console_color_table[ncolor].ansi; *p; p++)
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			    emit(*p);
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			emit('m');
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    }
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    state = st_init;
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		}
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    } else {
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		state = st_init;
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	n++;
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return n;
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
115