[SeaBIOS] [RFC PATCH 2/2] serial console, input

Kevin O'Connor kevin at koconnor.net
Fri Jul 1 20:07:41 CEST 2016


On Fri, Jul 01, 2016 at 01:07:39PM -0400, Kevin O'Connor wrote:
> If I understand correctly, most keys are sent on the serial port as
> single bytes, but there are a few keys that are sent as multi-byte
> sequences.  There's a lot of complexity to implement buffering for
> that unusual case.  I wonder if the buffer could be avoided - I played
> with it a little and came up with the below (totally untested).  I'm
> not sure if it's an improvement.

The version below might be slightly easier to understand (still
totally untested).

-Kevin


u8 multibyte_read_count VARLOW;
u8 multibyte_read_pos VARLOW;

void
sercon_check_event(void)
{
    u16 addr = GET_LOW(sercon_port);
    ...

    // read and process data
    int readdata = 0;
    while (inb(addr + SEROFF_LSR) & 0x01) {
        u8 byte = inb(addr + SEROFF_DATA);
        readdata = 1;
        int ret = sercon_check_multibyte(byte);
        if (ret)
            // byte part of multi-byte sequence
            continue;
        if (byte == 0x1b) {
            // Start multi-byte sequence check
            SET_LOW(multibyte_read_count, 1);
            continue;
        }
        // Send normal key
        sercon_sendkey(GET_LOW(termchr[chr].scancode), GET_LOW(termchr[chr].flags));
    }

    if (!readdata && GET_LOW(multibyte_read_count))
        // Too long to read multi-byte sequence - must flush
        dump_multibyte_sequence();
}

static int
sercon_check_multibyte(u8 byte)
{
    int mb_count = GET_LOW(multibyte_read_count);
    if (!mb_count)
        // Not in a multi-byte sequence
        return 0;
    int mb_pos = GET_LOW(multibyte_read_pos);
    while (GET_GLOBAL(termseq[mb_pos].seq[mb_count-1]) != byte) {
        // Byte didn't match this sequence - find a sequence that does
        mb_pos++;
        if (mb_pos >= ARRAY_SIZE(termseq)
            || memcmp_far(GLOBAL_SEG, termseq[mb_pos-1].seq
                          , GLOBAL_SEG, termseq[mb_pos].seq, mb_count-1) != 0)
            // No match - must flush previusly queued keys
            dump_multibyte_sequence();
            return 0;
        }
    }
    mb_count++;
    if (!GET_GLOBAL(termseq[mb_pos].seq[mb_count-1])) {
        // sequence complete - send key
        sercon_sendkey(GET_GLOBAL(termseq[seq].scancode), 0);
        mb_count = mb_pos = 0;
    }
    SET_LOW(multibyte_read_count, mb_count);
    SET_LOW(multibyte_read_pos, mb_pos);
    return 1;
}

static void
dump_multibyte_sequence(void)
{
    sercon_sendkey(GET_LOW(termchr[0x1b].scancode), GET_LOW(termchr[0x1b].flags));
    int i, mb_count = GET_LOW(multibyte_read_count);
    for (i=0; i<mb_count-1; i++) {
        u8 key = GET_GLOBAL(termseq[mb_pos].seq[i]);
        sercon_sendkey(GET_LOW(termchr[key].scancode), GET_LOW(termchr[key].flags));
    }
    SET_LOW(multibyte_read_count, 0);
    SET_LOW(multibyte_read_pos, 0);
}



More information about the SeaBIOS mailing list