[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