Add keyboard layouts support.

* Makefile.util.def (grub-mklayout): New file.
	(grub-kbdcomp): New script.
	* grub-core/Makefile.am (KERNEL_HEADER_FILES) [COND_mips_yeeloong]:
	Add keyboard_layouts.h.
	* grub-core/Makefile.core.def (kernel): Add commands/keylayouts.c and
	commands/boot.c on yeeloong.
	(keylayouts): New module.
	* grub-core/bus/usb/ohci.c
	* grub-core/bus/usb/uhci.c
	* grub-core/bus/usb/usbhub.c (rescan): New variable.
	(grub_usb_add_hub): Poll interrupt pipe for device handling.
	(attach_root_port): Likewise.
	(poll_nonroot_hub): Likewise.
	(grub_usb_poll_devices): Likewise.
	(detach_device): Close transfer.
	* grub-core/bus/usb/usbtrans.c (grub_usb_execute_and_wait_transfer): New
	function.
	(grub_usb_bulk_setup_readwrite): Likewise.
	(grub_usb_bulk_finish_readwrite): Likewise.
	* grub-core/commands/keylayouts.c: New file.
	* grub-core/commands/keystatus.c (grub_getkeystatus): New function.
	* grub-core/commands/menuentry.c (hotkey_aliases): All several new
	aliases.
	* grub-core/term/at_keyboard.c: Restructured to use keylayouts and
	support scancode 2.
	* grub-core/term/usb_keyboard.c: Restructured to use keylayouts.
	* include/grub/keyboard_layouts.h: New file.
	* util/grub-mklayout.c: New file.
	* util/grub-kbdcomp.in: Likewise.

	Also-By: Aleš Nesrsta <starous@volny.cz>

	Also-By: Vladimir Serbinenko <phcoder@gmail.com>
This commit is contained in:
Carles Pina i Estany 2010-09-19 01:01:35 +02:00 committed by Vladimir 'phcoder' Serbinenko
commit 1a9130dd3f
41 changed files with 3067 additions and 1459 deletions

View file

@ -102,49 +102,18 @@ grub_ncurses_setcolorstate (struct grub_term_output *term,
}
}
static int saved_char = ERR;
static int
grub_ncurses_checkkey (struct grub_term_input *term __attribute__ ((unused)))
{
int c;
/* Check for SAVED_CHAR. This should not be true, because this
means checkkey is called twice continuously. */
if (saved_char != ERR)
return saved_char;
wtimeout (stdscr, 100);
c = getch ();
/* If C is not ERR, then put it back in the input queue. */
if (c != ERR)
{
saved_char = c;
return c;
}
return -1;
}
static int
grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
int c;
/* If checkkey has already got a character, then return it. */
if (saved_char != ERR)
{
c = saved_char;
saved_char = ERR;
}
else
{
wtimeout (stdscr, -1);
c = getch ();
}
wtimeout (stdscr, 100);
c = getch ();
switch (c)
{
case ERR:
return -1;
case KEY_LEFT:
c = GRUB_TERM_LEFT;
break;
@ -288,7 +257,6 @@ grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused)))
static struct grub_term_input grub_ncurses_term_input =
{
.name = "console",
.checkkey = grub_ncurses_checkkey,
.getkey = grub_ncurses_getkey,
};

View file

@ -576,62 +576,29 @@ FUNCTION(grub_console_putchar)
ret
LOCAL(bypass_table):
.word 0x0100 | '\e',0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r'
.word 0x1c00 | '\n'
LOCAL(bypass_table_end):
/*
* int grub_console_getkey (void)
* if there is a character pending, return it; otherwise return -1
* BIOS call "INT 16H Function 01H" to check whether a character is pending
* Call with %ah = 0x1
* Return:
* If key waiting to be input:
* %ah = keyboard scan code
* %al = ASCII character
* Zero flag = clear
* else
* Zero flag = set
* BIOS call "INT 16H Function 00H" to read character from keyboard
* Call with %ah = 0x0
* Return: %ah = keyboard scan code
* %al = ASCII character
*/
/* this table is used in translate_keycode below */
LOCAL (translation_table):
.word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT
.word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT
.word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP
.word GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN
.word GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME
.word GRUB_CONSOLE_KEY_END, GRUB_TERM_END
.word GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC
.word GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE
.word GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE
.word GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE
.word 0
/*
* translate_keycode translates the key code %dx to an ascii code.
*/
.code16
translate_keycode:
pushw %bx
pushw %si
#ifdef __APPLE__
movw $(ABS(LOCAL (translation_table)) - 0x10000), %si
#else
movw $ABS(LOCAL (translation_table)), %si
#endif
1: lodsw
/* check if this is the end */
testw %ax, %ax
jz 2f
/* load the ascii code into %ax */
movw %ax, %bx
lodsw
/* check if this matches the key code */
cmpw %bx, %dx
jne 1b
/* translate %dx, if successful */
movw %ax, %dx
2: popw %si
popw %bx
ret
.code32
FUNCTION(grub_console_getkey)
pushl %ebp
@ -645,70 +612,54 @@ FUNCTION(grub_console_getkey)
* INT 16/AH = 1 before calling INT 16/AH = 0.
*/
1:
movb $1, %ah
int $0x16
jnz 2f
hlt
jmp 1b
2:
jz notpending
movb $0, %ah
int $0x16
xorl %edx, %edx
movw %ax, %dx /* real_to_prot uses %eax */
call translate_keycode
DATA32 call real_to_prot
.code32
movw %dx, %ax
popl %ebp
ret
/*
* int grub_console_checkkey (void)
* if there is a character pending, return it; otherwise return -1
* BIOS call "INT 16H Function 01H" to check whether a character is pending
* Call with %ah = 0x1
* Return:
* If key waiting to be input:
* %ah = keyboard scan code
* %al = ASCII character
* Zero flag = clear
* else
* Zero flag = set
*/
FUNCTION(grub_console_checkkey)
pushl %ebp
xorl %edx, %edx
call prot_to_real /* enter real mode */
.code16
movb $0x1, %ah
int $0x16
jz notpending
movw %ax, %dx
DATA32 jmp pending
notpending:
decl %edx
pending:
DATA32 call real_to_prot
.code32
movl $0xff, %eax
testl %eax, %edx
jz 1f
andl %edx, %eax
cmp %eax, 0x20
ja 2f
movl %edx, %eax
leal LOCAL(bypass_table), %esi
movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) / 2), %ecx
repne cmpsw
jz 3f
addl $('a' - 1 | GRUB_TERM_CTRL), %eax
jmp 2f
3:
andl $0xff, %eax
jmp 2f
1: movl %edx, %eax
shrl $8, %eax
orl $GRUB_TERM_EXTENDED, %eax
2:
popl %ebp
ret
notpending:
.code16
DATA32 call real_to_prot
.code32
#if GRUB_TERM_NO_KEY != 0
#error Fix this asm code
#endif
jmp 2b
/*
* grub_uint16_t grub_console_getxy (void)

View file

@ -40,6 +40,7 @@ extern void grub_gfxterm_init (void);
extern void grub_at_keyboard_init (void);
extern void grub_serial_init (void);
extern void grub_terminfo_init (void);
extern void grub_keylayouts_init (void);
/* FIXME: use interrupt to count high. */
grub_uint64_t
@ -204,6 +205,7 @@ grub_machine_init (void)
grub_font_init ();
grub_gfxterm_init ();
grub_keylayouts_init ();
grub_at_keyboard_init ();
grub_terminfo_init ();

View file

@ -39,7 +39,7 @@ grub_rescue_read_line (char **line, int cont)
grub_printf ((cont) ? "> " : "grub rescue> ");
grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE);
while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r')
while ((c = grub_getkey ()) != '\n' && c != '\r')
{
if (grub_isprint (c))
{

View file

@ -78,65 +78,48 @@ grub_xputs_dumb (const char *str)
void (*grub_xputs) (const char *str) = grub_xputs_dumb;
int
grub_getkey (void)
{
grub_term_input_t term;
grub_refresh ();
while (1)
{
if (grub_term_poll_usb)
grub_term_poll_usb ();
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->checkkey (term);
if (key != -1)
return term->getkey (term);
}
grub_cpu_idle ();
}
}
static int pending_key = GRUB_TERM_NO_KEY;
int
grub_checkkey (void)
{
grub_term_input_t term;
if (pending_key != GRUB_TERM_NO_KEY)
return pending_key;
if (grub_term_poll_usb)
grub_term_poll_usb ();
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->checkkey (term);
if (key != -1)
return key;
pending_key = term->getkey (term);
if (pending_key != GRUB_TERM_NO_KEY)
return pending_key;
}
return -1;
}
int
grub_getkeystatus (void)
grub_getkey (void)
{
int status = 0;
grub_term_input_t term;
int ret;
if (grub_term_poll_usb)
grub_term_poll_usb ();
grub_refresh ();
FOR_ACTIVE_TERM_INPUTS(term)
{
if (term->getkeystatus)
status |= term->getkeystatus (term);
}
return status;
grub_checkkey ();
while (pending_key == GRUB_TERM_NO_KEY)
{
grub_cpu_idle ();
grub_checkkey ();
}
ret = pending_key;
pending_key = GRUB_TERM_NO_KEY;
return ret;
}
void
grub_refresh (void)
{