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); }