make serial use ANSI code recognition in terminfo.mod

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-05-06 21:32:58 +02:00
parent e903ddec1c
commit 82e32bc310
4 changed files with 30 additions and 121 deletions

View file

@ -25,7 +25,7 @@ kernel_img_SOURCES = kern/i386/ieee1275/startup.S \
term/terminfo.c term/tparm.c \ term/terminfo.c term/tparm.c \
disk/ieee1275/ofdisk.c \ disk/ieee1275/ofdisk.c \
symlist.c symlist.c
kernel_img_HEADERS += ieee1275/ieee1275.h kernel_img_HEADERS += ieee1275/ieee1275.h terminfo.h
kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic

View file

@ -23,18 +23,18 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/term.h> #include <grub/term.h>
char *grub_terminfo_get_current (void); char *EXPORT_FUNC(grub_terminfo_get_current) (void);
grub_err_t grub_terminfo_set_current (const char *); grub_err_t EXPORT_FUNC(grub_terminfo_set_current) (const char *);
void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y, void EXPORT_FUNC(grub_terminfo_gotoxy) (grub_uint8_t x, grub_uint8_t y,
grub_term_output_t oterm); grub_term_output_t oterm);
void grub_terminfo_cls (grub_term_output_t oterm); void EXPORT_FUNC(grub_terminfo_cls) (grub_term_output_t oterm);
void grub_terminfo_reverse_video_on (grub_term_output_t oterm); void EXPORT_FUNC(grub_terminfo_reverse_video_on) (grub_term_output_t oterm);
void grub_terminfo_reverse_video_off (grub_term_output_t oterm); void EXPORT_FUNC(grub_terminfo_reverse_video_off) (grub_term_output_t oterm);
void grub_terminfo_cursor_on (grub_term_output_t oterm); void EXPORT_FUNC(grub_terminfo_cursor_on) (grub_term_output_t oterm);
void grub_terminfo_cursor_off (grub_term_output_t oterm); void EXPORT_FUNC(grub_terminfo_cursor_off) (grub_term_output_t oterm);
#define GRUB_TERMINFO_READKEY_MAX_LEN 4 #define GRUB_TERMINFO_READKEY_MAX_LEN 4
void grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)); void EXPORT_FUNC(grub_terminfo_readkey) (int *keys, int *len, int (*readkey) (void));
#endif /* ! GRUB_TERMINFO_HEADER */ #endif /* ! GRUB_TERMINFO_HEADER */

View file

@ -166,12 +166,12 @@ static int
grub_ofconsole_checkkey (void) grub_ofconsole_checkkey (void)
{ {
if (grub_buflen) if (grub_buflen)
return 1; return grub_keybuf[0];
grub_terminfo_readkey (grub_keybuf, &grub_buflen, readkey); grub_terminfo_readkey (grub_keybuf, &grub_buflen, readkey);
if (grub_buflen) if (grub_buflen)
return 1; return grub_keybuf[0];
return -1; return -1;
} }

View file

@ -35,8 +35,8 @@ static unsigned int keep_track = 1;
static unsigned int registered = 0; static unsigned int registered = 0;
/* An input buffer. */ /* An input buffer. */
static char input_buf[8]; static int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN];
static unsigned int npending = 0; static int npending = 0;
static struct grub_term_output grub_serial_term_output; static struct grub_term_output grub_serial_term_output;
@ -114,98 +114,6 @@ serial_hw_put (const int c)
grub_outb (c, serial_settings.port + UART_TX); grub_outb (c, serial_settings.port + UART_TX);
} }
static void
serial_translate_key_sequence (void)
{
unsigned int i;
static struct
{
char key;
char ascii;
}
three_code_table[] =
{
{'A', 16},
{'B', 14},
{'C', 6},
{'D', 2},
{'F', 5},
{'H', 1},
{'4', 4}
};
static struct
{
short key;
char ascii;
}
four_code_table[] =
{
{('1' | ('~' << 8)), 1},
{('3' | ('~' << 8)), 4},
{('5' | ('~' << 8)), 7},
{('6' | ('~' << 8)), 3}
};
if (npending < 3)
return;
/* The buffer must start with "ESC [". */
if (input_buf[0] != '\e' || input_buf[1] != '[')
return;
for (i = 0; i < ARRAY_SIZE (three_code_table); i++)
if (three_code_table[i].key == input_buf[2])
{
input_buf[0] = three_code_table[i].ascii;
npending -= 2;
grub_memmove (input_buf + 1, input_buf + 3, npending - 1);
return;
}
if (npending >= 4)
{
short key = input_buf[3] | (input_buf[4] << 8);
for (i = 0; i < ARRAY_SIZE (four_code_table); i++)
if (four_code_table[i].key == key)
{
input_buf[0] = four_code_table[i].ascii;
npending -= 3;
grub_memmove (input_buf + 1, input_buf + 4, npending - 1);
return;
}
}
}
static int
fill_input_buf (const int nowait)
{
int i;
for (i = 0; i < 10000 && npending < sizeof (input_buf); i++)
{
int c;
c = serial_hw_fetch ();
if (c >= 0)
{
input_buf[npending++] = c;
/* Reset the counter to zero, to wait for the same interval. */
i = 0;
}
if (nowait)
break;
}
/* Translate some key sequences. */
serial_translate_key_sequence ();
return npending;
}
/* Convert speed to divisor. */ /* Convert speed to divisor. */
static unsigned short static unsigned short
serial_get_divisor (unsigned int speed) serial_get_divisor (unsigned int speed)
@ -248,9 +156,14 @@ serial_get_divisor (unsigned int speed)
static int static int
grub_serial_checkkey (void) grub_serial_checkkey (void)
{ {
if (fill_input_buf (1)) if (npending)
return input_buf[0]; return input_buf[0];
else
grub_terminfo_readkey (input_buf, &npending, serial_hw_fetch);
if (npending)
return input_buf[0];
return -1; return -1;
} }
@ -258,18 +171,14 @@ grub_serial_checkkey (void)
static int static int
grub_serial_getkey (void) grub_serial_getkey (void)
{ {
int c; int ret;
while (! npending)
grub_terminfo_readkey (input_buf, &npending, serial_hw_fetch);
while (! fill_input_buf (0)) ret = input_buf[0];
; npending--;
grub_memmove (input_buf, input_buf + 1, npending);
c = input_buf[0]; return ret;
if (c == 0x7f)
c = GRUB_TERM_BACKSPACE;
grub_memmove (input_buf, input_buf + 1, --npending);
return c;
} }
/* Initialize a serial device. PORT is the port number for a serial device. /* Initialize a serial device. PORT is the port number for a serial device.