merge mainline to ia64
This commit is contained in:
commit
0f35c665e6
595 changed files with 62746 additions and 9109 deletions
|
@ -22,18 +22,13 @@
|
|||
#include <grub/cpu/io.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/keyboard_layouts.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/loader.h>
|
||||
|
||||
static short at_keyboard_status = 0;
|
||||
static int pending_key = -1;
|
||||
|
||||
#define KEYBOARD_STATUS_SHIFT_L (1 << 0)
|
||||
#define KEYBOARD_STATUS_SHIFT_R (1 << 1)
|
||||
#define KEYBOARD_STATUS_ALT_L (1 << 2)
|
||||
#define KEYBOARD_STATUS_ALT_R (1 << 3)
|
||||
#define KEYBOARD_STATUS_CTRL_L (1 << 4)
|
||||
#define KEYBOARD_STATUS_CTRL_R (1 << 5)
|
||||
#define KEYBOARD_STATUS_CAPS_LOCK (1 << 6)
|
||||
#define KEYBOARD_STATUS_NUM_LOCK (1 << 7)
|
||||
static int e0_received = 0;
|
||||
static int f0_received = 0;
|
||||
|
||||
static grub_uint8_t led_status;
|
||||
|
||||
|
@ -41,36 +36,179 @@ static grub_uint8_t led_status;
|
|||
#define KEYBOARD_LED_NUM (1 << 1)
|
||||
#define KEYBOARD_LED_CAPS (1 << 2)
|
||||
|
||||
static char keyboard_map[128] =
|
||||
{
|
||||
'\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
||||
'o', 'p', '[', ']', '\n', '\0', 'a', 's',
|
||||
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
||||
'\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
|
||||
'b', 'n', 'm', ',', '.', '/', '\0', '*',
|
||||
'\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_HOME,
|
||||
GRUB_TERM_UP, GRUB_TERM_NPAGE, '-', GRUB_TERM_LEFT, '\0', GRUB_TERM_RIGHT, '+', GRUB_TERM_END,
|
||||
GRUB_TERM_DOWN, GRUB_TERM_PPAGE, '\0', GRUB_TERM_DC, '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT,
|
||||
OLPC_RIGHT
|
||||
};
|
||||
|
||||
static char keyboard_map_shift[128] =
|
||||
{
|
||||
'\0', '\0', '!', '@', '#', '$', '%', '^',
|
||||
'&', '*', '(', ')', '_', '+', '\0', '\0',
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
|
||||
'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
|
||||
'\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', '<', '>', '?'
|
||||
};
|
||||
|
||||
static grub_uint8_t grub_keyboard_controller_orig;
|
||||
static grub_uint8_t grub_keyboard_orig_set;
|
||||
static grub_uint8_t current_set;
|
||||
|
||||
static const grub_uint8_t set1_mapping[128] =
|
||||
{
|
||||
/* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE,
|
||||
/* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2,
|
||||
/* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4,
|
||||
/* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6,
|
||||
/* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8,
|
||||
/* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0,
|
||||
/* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL,
|
||||
/* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB,
|
||||
/* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W,
|
||||
/* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R,
|
||||
/* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y,
|
||||
/* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I,
|
||||
/* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P,
|
||||
/* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET,
|
||||
/* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL,
|
||||
/* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S,
|
||||
/* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F,
|
||||
/* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H,
|
||||
/* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K,
|
||||
/* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON,
|
||||
/* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE,
|
||||
/* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH,
|
||||
/* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X,
|
||||
/* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V,
|
||||
/* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N,
|
||||
/* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA,
|
||||
/* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH,
|
||||
/* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL,
|
||||
/* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE,
|
||||
/* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1,
|
||||
/* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3,
|
||||
/* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5,
|
||||
/* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7,
|
||||
/* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9,
|
||||
/* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK,
|
||||
/* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7,
|
||||
/* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9,
|
||||
/* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4,
|
||||
/* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6,
|
||||
/* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1,
|
||||
/* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3,
|
||||
/* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT,
|
||||
/* 0x54 */ 0, 0,
|
||||
/* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11,
|
||||
/* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0,
|
||||
/* 0x5a */ 0, 0,
|
||||
/* 0x5c */ 0, 0,
|
||||
/* 0x5e */ 0, 0,
|
||||
/* 0x60 */ 0, 0,
|
||||
/* 0x62 */ 0, 0,
|
||||
/* OLPC keys. Just mapped to normal keys. */
|
||||
/* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP,
|
||||
/* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT,
|
||||
/* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
grub_uint8_t from, to;
|
||||
} set1_e0_mapping[] =
|
||||
{
|
||||
{0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
|
||||
{0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
|
||||
{0x35, GRUB_KEYBOARD_KEY_NUMSLASH },
|
||||
{0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
|
||||
{0x47, GRUB_KEYBOARD_KEY_HOME},
|
||||
{0x48, GRUB_KEYBOARD_KEY_UP},
|
||||
{0x49, GRUB_KEYBOARD_KEY_NPAGE},
|
||||
{0x4b, GRUB_KEYBOARD_KEY_LEFT},
|
||||
{0x4d, GRUB_KEYBOARD_KEY_RIGHT},
|
||||
{0x4f, GRUB_KEYBOARD_KEY_END},
|
||||
{0x50, GRUB_KEYBOARD_KEY_DOWN},
|
||||
{0x51, GRUB_KEYBOARD_KEY_PPAGE},
|
||||
{0x52, GRUB_KEYBOARD_KEY_INSERT},
|
||||
{0x53, GRUB_KEYBOARD_KEY_DELETE},
|
||||
};
|
||||
|
||||
static const grub_uint8_t set2_mapping[256] =
|
||||
{
|
||||
/* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9,
|
||||
/* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5,
|
||||
/* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1,
|
||||
/* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12,
|
||||
/* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10,
|
||||
/* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6,
|
||||
/* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB,
|
||||
/* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0,
|
||||
/* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT,
|
||||
/* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0,
|
||||
/* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q,
|
||||
/* 0x16 */ GRUB_KEYBOARD_KEY_1, 0,
|
||||
/* 0x18 */ 0, 0,
|
||||
/* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S,
|
||||
/* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W,
|
||||
/* 0x1e */ GRUB_KEYBOARD_KEY_2, 0,
|
||||
/* 0x20 */ 0, GRUB_KEYBOARD_KEY_C,
|
||||
/* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D,
|
||||
/* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4,
|
||||
/* 0x26 */ GRUB_KEYBOARD_KEY_3, 0,
|
||||
/* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE,
|
||||
/* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F,
|
||||
/* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R,
|
||||
/* 0x2e */ GRUB_KEYBOARD_KEY_5, 0,
|
||||
/* 0x30 */ 0, GRUB_KEYBOARD_KEY_N,
|
||||
/* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H,
|
||||
/* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y,
|
||||
/* 0x36 */ GRUB_KEYBOARD_KEY_6, 0,
|
||||
/* 0x38 */ 0, 0,
|
||||
/* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J,
|
||||
/* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7,
|
||||
/* 0x3e */ GRUB_KEYBOARD_KEY_8, 0,
|
||||
/* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA,
|
||||
/* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I,
|
||||
/* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0,
|
||||
/* 0x46 */ GRUB_KEYBOARD_KEY_9, 0,
|
||||
/* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT,
|
||||
/* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L,
|
||||
/* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P,
|
||||
/* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0,
|
||||
/* 0x50 */ 0, 0,
|
||||
/* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0,
|
||||
/* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL,
|
||||
/* 0x56 */ 0, 0,
|
||||
/* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
|
||||
/* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET,
|
||||
/* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH,
|
||||
/* 0x5e */ 0, 0,
|
||||
/* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND,
|
||||
/* 0x62 */ 0, 0,
|
||||
/* 0x64 */ 0, 0,
|
||||
/* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0,
|
||||
/* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1,
|
||||
/* 0x6a */ 0, GRUB_KEYBOARD_KEY_NUM4,
|
||||
/* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, 0,
|
||||
/* 0x6e */ 0, 0,
|
||||
/* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0,
|
||||
/* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5,
|
||||
/* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8,
|
||||
/* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK,
|
||||
/* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS,
|
||||
/* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS,
|
||||
/* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9,
|
||||
/* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
|
||||
/* 0x80 */ 0, 0,
|
||||
/* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7,
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
grub_uint8_t from, to;
|
||||
} set2_e0_mapping[] =
|
||||
{
|
||||
{0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
|
||||
{0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
|
||||
{0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
|
||||
{0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
|
||||
{0x69, GRUB_KEYBOARD_KEY_END},
|
||||
{0x6b, GRUB_KEYBOARD_KEY_LEFT},
|
||||
{0x6c, GRUB_KEYBOARD_KEY_HOME},
|
||||
{0x70, GRUB_KEYBOARD_KEY_INSERT},
|
||||
{0x71, GRUB_KEYBOARD_KEY_DELETE},
|
||||
{0x72, GRUB_KEYBOARD_KEY_DOWN},
|
||||
{0x74, GRUB_KEYBOARD_KEY_RIGHT},
|
||||
{0x75, GRUB_KEYBOARD_KEY_UP},
|
||||
{0x7a, GRUB_KEYBOARD_KEY_NPAGE},
|
||||
{0x7d, GRUB_KEYBOARD_KEY_PPAGE},
|
||||
};
|
||||
|
||||
static void
|
||||
keyboard_controller_wait_until_ready (void)
|
||||
|
@ -78,22 +216,137 @@ keyboard_controller_wait_until_ready (void)
|
|||
while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
|
||||
}
|
||||
|
||||
static grub_uint8_t
|
||||
wait_ack (void)
|
||||
{
|
||||
grub_uint64_t endtime;
|
||||
grub_uint8_t ack;
|
||||
|
||||
endtime = grub_get_time_ms () + 20;
|
||||
do
|
||||
ack = grub_inb (KEYBOARD_REG_DATA);
|
||||
while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
|
||||
&& grub_get_time_ms () < endtime);
|
||||
return ack;
|
||||
}
|
||||
|
||||
static int
|
||||
at_command (grub_uint8_t data)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < GRUB_AT_TRIES; i++)
|
||||
{
|
||||
grub_uint8_t ack;
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_outb (data, KEYBOARD_REG_STATUS);
|
||||
ack = wait_ack ();
|
||||
if (ack == GRUB_AT_NACK)
|
||||
continue;
|
||||
if (ack == GRUB_AT_ACK)
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
return (i != GRUB_AT_TRIES);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_keyboard_controller_write (grub_uint8_t c)
|
||||
{
|
||||
at_command (KEYBOARD_COMMAND_WRITE);
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS);
|
||||
grub_outb (c, KEYBOARD_REG_DATA);
|
||||
}
|
||||
|
||||
#if !defined (GRUB_MACHINE_MIPS_YEELOONG) && !defined (GRUB_MACHINE_QEMU)
|
||||
|
||||
static grub_uint8_t
|
||||
grub_keyboard_controller_read (void)
|
||||
{
|
||||
at_command (KEYBOARD_COMMAND_READ);
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_outb (KEYBOARD_COMMAND_READ, KEYBOARD_REG_STATUS);
|
||||
return grub_inb (KEYBOARD_REG_DATA);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
write_mode (int mode)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < GRUB_AT_TRIES; i++)
|
||||
{
|
||||
grub_uint8_t ack;
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_outb (0xf0, KEYBOARD_REG_DATA);
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_outb (mode, KEYBOARD_REG_DATA);
|
||||
keyboard_controller_wait_until_ready ();
|
||||
ack = wait_ack ();
|
||||
if (ack == GRUB_AT_NACK)
|
||||
continue;
|
||||
if (ack == GRUB_AT_ACK)
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (i != GRUB_AT_TRIES);
|
||||
}
|
||||
|
||||
static int
|
||||
query_mode (void)
|
||||
{
|
||||
grub_uint8_t ret;
|
||||
int e;
|
||||
|
||||
e = write_mode (0);
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
keyboard_controller_wait_until_ready ();
|
||||
|
||||
do
|
||||
ret = grub_inb (KEYBOARD_REG_DATA);
|
||||
while (ret == GRUB_AT_ACK);
|
||||
|
||||
/* QEMU translates the set even in no-translate mode. */
|
||||
if (ret == 0x43 || ret == 1)
|
||||
return 1;
|
||||
if (ret == 0x41 || ret == 2)
|
||||
return 2;
|
||||
if (ret == 0x3f || ret == 3)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_scancodes (void)
|
||||
{
|
||||
/* You must have visited computer museum. Keyboard without scancode set
|
||||
knowledge. Assume XT. */
|
||||
if (!grub_keyboard_orig_set)
|
||||
{
|
||||
grub_dprintf ("atkeyb", "No sets support assumed\n");
|
||||
current_set = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
grub_keyboard_controller_write (grub_keyboard_controller_orig
|
||||
& ~KEYBOARD_AT_TRANSLATE);
|
||||
|
||||
write_mode (2);
|
||||
current_set = query_mode ();
|
||||
grub_dprintf ("atkeyb", "returned set %d\n", current_set);
|
||||
if (current_set == 2)
|
||||
return;
|
||||
|
||||
write_mode (1);
|
||||
current_set = query_mode ();
|
||||
grub_dprintf ("atkeyb", "returned set %d\n", current_set);
|
||||
if (current_set == 1)
|
||||
return;
|
||||
grub_printf ("No supported scancode set found\n");
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_controller_led (grub_uint8_t leds)
|
||||
{
|
||||
|
@ -103,195 +356,276 @@ keyboard_controller_led (grub_uint8_t leds)
|
|||
grub_outb (leds & 0x7, KEYBOARD_REG_DATA);
|
||||
}
|
||||
|
||||
static int
|
||||
fetch_key (int *is_break)
|
||||
{
|
||||
int was_ext = 0;
|
||||
grub_uint8_t at_key;
|
||||
int ret = 0;
|
||||
|
||||
if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
|
||||
return -1;
|
||||
at_key = grub_inb (KEYBOARD_REG_DATA);
|
||||
if (at_key == 0xe0)
|
||||
{
|
||||
e0_received = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((current_set == 2 || current_set == 3) && at_key == 0xf0)
|
||||
{
|
||||
f0_received = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setting LEDs may generate ACKs. */
|
||||
if (at_key == GRUB_AT_ACK)
|
||||
return -1;
|
||||
|
||||
was_ext = e0_received;
|
||||
e0_received = 0;
|
||||
|
||||
switch (current_set)
|
||||
{
|
||||
case 1:
|
||||
*is_break = !!(at_key & 0x80);
|
||||
if (!was_ext)
|
||||
ret = set1_mapping[at_key & 0x7f];
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
|
||||
if (set1_e0_mapping[i].from == (at_key & 0x7f))
|
||||
{
|
||||
ret = set1_e0_mapping[i].to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
*is_break = f0_received;
|
||||
f0_received = 0;
|
||||
if (!was_ext)
|
||||
ret = set2_mapping[at_key];
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
|
||||
if (set2_e0_mapping[i].from == at_key)
|
||||
{
|
||||
ret = set2_e0_mapping[i].to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
if (was_ext)
|
||||
grub_printf ("Unknown key 0xe0+0x%02x from set %d\n",
|
||||
at_key, current_set);
|
||||
else
|
||||
grub_printf ("Unknown key 0x%02x from set %d\n",
|
||||
at_key, current_set);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: This should become an interrupt service routine. For now
|
||||
it's just used to catch events from control keys. */
|
||||
static void
|
||||
grub_keyboard_isr (char key)
|
||||
static int
|
||||
grub_keyboard_isr (grub_keyboard_key_t key, int is_break)
|
||||
{
|
||||
char is_make = KEYBOARD_ISMAKE (key);
|
||||
key = KEYBOARD_SCANCODE (key);
|
||||
if (is_make)
|
||||
if (!is_break)
|
||||
switch (key)
|
||||
{
|
||||
case SHIFT_L:
|
||||
at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L;
|
||||
break;
|
||||
case SHIFT_R:
|
||||
at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R;
|
||||
break;
|
||||
case CTRL:
|
||||
at_keyboard_status |= KEYBOARD_STATUS_CTRL_L;
|
||||
break;
|
||||
case ALT:
|
||||
at_keyboard_status |= KEYBOARD_STATUS_ALT_L;
|
||||
break;
|
||||
default:
|
||||
/* Skip grub_dprintf. */
|
||||
return;
|
||||
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
|
||||
at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
|
||||
at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
|
||||
at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
|
||||
at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
|
||||
at_keyboard_status |= GRUB_TERM_STATUS_RALT;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_LEFT_ALT:
|
||||
at_keyboard_status |= GRUB_TERM_STATUS_LALT;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
switch (key)
|
||||
{
|
||||
case SHIFT_L:
|
||||
at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L;
|
||||
break;
|
||||
case SHIFT_R:
|
||||
at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R;
|
||||
break;
|
||||
case CTRL:
|
||||
at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L;
|
||||
break;
|
||||
case ALT:
|
||||
at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L;
|
||||
break;
|
||||
default:
|
||||
/* Skip grub_dprintf. */
|
||||
return;
|
||||
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
|
||||
at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
|
||||
at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
|
||||
at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
|
||||
at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
|
||||
at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
|
||||
return 1;
|
||||
case GRUB_KEYBOARD_KEY_LEFT_ALT:
|
||||
at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#ifdef DEBUG_AT_KEYBOARD
|
||||
grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If there is a raw key pending, return it; otherwise return -1. */
|
||||
static int
|
||||
grub_keyboard_getkey (void)
|
||||
{
|
||||
grub_uint8_t key;
|
||||
if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
|
||||
int key;
|
||||
int is_break;
|
||||
|
||||
key = fetch_key (&is_break);
|
||||
if (key == -1)
|
||||
return -1;
|
||||
key = grub_inb (KEYBOARD_REG_DATA);
|
||||
/* FIXME */ grub_keyboard_isr (key);
|
||||
if (! KEYBOARD_ISMAKE (key))
|
||||
|
||||
if (grub_keyboard_isr (key, is_break))
|
||||
return -1;
|
||||
return (KEYBOARD_SCANCODE (key));
|
||||
if (is_break)
|
||||
return -1;
|
||||
return key;
|
||||
}
|
||||
|
||||
/* If there is a character pending, return it; otherwise return -1. */
|
||||
/* If there is a character pending, return it;
|
||||
otherwise return GRUB_TERM_NO_KEY. */
|
||||
static int
|
||||
grub_at_keyboard_getkey_noblock (void)
|
||||
grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
int code, key;
|
||||
int code;
|
||||
code = grub_keyboard_getkey ();
|
||||
if (code == -1)
|
||||
return -1;
|
||||
return GRUB_TERM_NO_KEY;
|
||||
#ifdef DEBUG_AT_KEYBOARD
|
||||
grub_dprintf ("atkeyb", "Detected key 0x%x\n", key);
|
||||
#endif
|
||||
switch (code)
|
||||
{
|
||||
case CAPS_LOCK:
|
||||
at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK;
|
||||
case GRUB_KEYBOARD_KEY_CAPS_LOCK:
|
||||
at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
|
||||
led_status ^= KEYBOARD_LED_CAPS;
|
||||
keyboard_controller_led (led_status);
|
||||
|
||||
#ifdef DEBUG_AT_KEYBOARD
|
||||
grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK));
|
||||
#endif
|
||||
key = -1;
|
||||
break;
|
||||
case NUM_LOCK:
|
||||
at_keyboard_status ^= KEYBOARD_STATUS_NUM_LOCK;
|
||||
return GRUB_TERM_NO_KEY;
|
||||
case GRUB_KEYBOARD_KEY_NUM_LOCK:
|
||||
at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
|
||||
led_status ^= KEYBOARD_LED_NUM;
|
||||
keyboard_controller_led (led_status);
|
||||
|
||||
#ifdef DEBUG_AT_KEYBOARD
|
||||
grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK));
|
||||
#endif
|
||||
key = -1;
|
||||
break;
|
||||
case SCROLL_LOCK:
|
||||
/* For scroll lock we don't keep track of status. Only update its led. */
|
||||
return GRUB_TERM_NO_KEY;
|
||||
case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
|
||||
at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
|
||||
led_status ^= KEYBOARD_LED_SCROLL;
|
||||
keyboard_controller_led (led_status);
|
||||
key = -1;
|
||||
break;
|
||||
return GRUB_TERM_NO_KEY;
|
||||
default:
|
||||
if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R))
|
||||
key = keyboard_map[code] - 'a' + 1;
|
||||
else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R))
|
||||
&& keyboard_map_shift[code])
|
||||
key = keyboard_map_shift[code];
|
||||
else
|
||||
key = keyboard_map[code];
|
||||
|
||||
if (key == 0)
|
||||
grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code);
|
||||
|
||||
if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)
|
||||
{
|
||||
if ((key >= 'a') && (key <= 'z'))
|
||||
key += 'A' - 'a';
|
||||
else if ((key >= 'A') && (key <= 'Z'))
|
||||
key += 'a' - 'A';
|
||||
}
|
||||
return grub_term_map_key (code, at_keyboard_status);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_at_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
if (pending_key != -1)
|
||||
return 1;
|
||||
|
||||
pending_key = grub_at_keyboard_getkey_noblock ();
|
||||
|
||||
if (pending_key != -1)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
int key;
|
||||
if (pending_key != -1)
|
||||
{
|
||||
key = pending_key;
|
||||
pending_key = -1;
|
||||
return key;
|
||||
}
|
||||
do
|
||||
{
|
||||
key = grub_at_keyboard_getkey_noblock ();
|
||||
} while (key == -1);
|
||||
return key;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
pending_key = -1;
|
||||
at_keyboard_status = 0;
|
||||
/* Drain input buffer. */
|
||||
while (1)
|
||||
{
|
||||
keyboard_controller_wait_until_ready ();
|
||||
if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
|
||||
break;
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_inb (KEYBOARD_REG_DATA);
|
||||
}
|
||||
#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_QEMU)
|
||||
grub_keyboard_controller_orig = 0;
|
||||
grub_keyboard_orig_set = 2;
|
||||
#else
|
||||
grub_keyboard_controller_orig = grub_keyboard_controller_read ();
|
||||
grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1);
|
||||
grub_keyboard_orig_set = query_mode ();
|
||||
#endif
|
||||
set_scancodes ();
|
||||
keyboard_controller_led (led_status);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
if (grub_keyboard_orig_set)
|
||||
write_mode (grub_keyboard_orig_set);
|
||||
grub_keyboard_controller_write (grub_keyboard_controller_orig);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_at_fini_hw (int noreturn __attribute__ ((unused)))
|
||||
{
|
||||
return grub_keyboard_controller_fini (NULL);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_at_restore_hw (void)
|
||||
{
|
||||
/* Drain input buffer. */
|
||||
while (1)
|
||||
{
|
||||
keyboard_controller_wait_until_ready ();
|
||||
if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
|
||||
break;
|
||||
keyboard_controller_wait_until_ready ();
|
||||
grub_inb (KEYBOARD_REG_DATA);
|
||||
}
|
||||
set_scancodes ();
|
||||
keyboard_controller_led (led_status);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static struct grub_term_input grub_at_keyboard_term =
|
||||
{
|
||||
.name = "at_keyboard",
|
||||
.init = grub_keyboard_controller_init,
|
||||
.fini = grub_keyboard_controller_fini,
|
||||
.checkkey = grub_at_keyboard_checkkey,
|
||||
.getkey = grub_at_keyboard_getkey,
|
||||
.getkey = grub_at_keyboard_getkey
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(at_keyboard)
|
||||
{
|
||||
grub_term_register_input ("at_keyboard", &grub_at_keyboard_term);
|
||||
grub_loader_register_preboot_hook (grub_at_fini_hw, grub_at_restore_hw,
|
||||
GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(at_keyboard)
|
||||
{
|
||||
grub_keyboard_controller_fini (NULL);
|
||||
grub_term_unregister_input (&grub_at_keyboard_term);
|
||||
}
|
||||
|
|
|
@ -24,12 +24,6 @@
|
|||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/console.h>
|
||||
|
||||
static const grub_uint8_t
|
||||
grub_console_standard_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_YELLOW,
|
||||
GRUB_EFI_BACKGROUND_BLACK);
|
||||
|
||||
static int read_key = -1;
|
||||
|
||||
static grub_uint32_t
|
||||
map_char (grub_uint32_t c)
|
||||
{
|
||||
|
@ -103,8 +97,19 @@ grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
|
|||
efi_call_2 (o->output_string, o, str);
|
||||
}
|
||||
|
||||
const unsigned efi_codes[] =
|
||||
{
|
||||
0, GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_RIGHT,
|
||||
GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_END, GRUB_TERM_KEY_INSERT,
|
||||
GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
|
||||
GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
|
||||
GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
|
||||
GRUB_TERM_KEY_F10, 0, 0, '\e'
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
grub_efi_simple_input_interface_t *i;
|
||||
grub_efi_input_key_t key;
|
||||
|
@ -113,129 +118,18 @@ grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused)))
|
|||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
if (read_key >= 0)
|
||||
return 1;
|
||||
|
||||
i = grub_efi_system_table->con_in;
|
||||
status = efi_call_2 (i->read_key_stroke, i, &key);
|
||||
#if 0
|
||||
switch (status)
|
||||
{
|
||||
case GRUB_EFI_SUCCESS:
|
||||
{
|
||||
grub_uint16_t xy;
|
||||
|
||||
xy = grub_getxy ();
|
||||
grub_gotoxy (0, 0);
|
||||
grub_printf ("scan_code=%x,unicode_char=%x ",
|
||||
(unsigned) key.scan_code,
|
||||
(unsigned) key.unicode_char);
|
||||
grub_gotoxy (xy >> 8, xy & 0xff);
|
||||
}
|
||||
break;
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
case GRUB_EFI_NOT_READY:
|
||||
//grub_printf ("not ready ");
|
||||
break;
|
||||
if (key.scan_code == 0)
|
||||
return key.unicode_char;
|
||||
else if (key.scan_code < ARRAY_SIZE (efi_codes))
|
||||
return efi_codes[key.scan_code];
|
||||
|
||||
default:
|
||||
//grub_printf ("device error ");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status == GRUB_EFI_SUCCESS)
|
||||
{
|
||||
switch (key.scan_code)
|
||||
{
|
||||
case 0x00:
|
||||
read_key = key.unicode_char;
|
||||
break;
|
||||
case 0x01:
|
||||
read_key = GRUB_TERM_UP;
|
||||
break;
|
||||
case 0x02:
|
||||
read_key = GRUB_TERM_DOWN;
|
||||
break;
|
||||
case 0x03:
|
||||
read_key = GRUB_TERM_RIGHT;
|
||||
break;
|
||||
case 0x04:
|
||||
read_key = GRUB_TERM_LEFT;
|
||||
break;
|
||||
case 0x05:
|
||||
read_key = GRUB_TERM_HOME;
|
||||
break;
|
||||
case 0x06:
|
||||
read_key = GRUB_TERM_END;
|
||||
break;
|
||||
case 0x07:
|
||||
break;
|
||||
case 0x08:
|
||||
read_key = GRUB_TERM_DC;
|
||||
break;
|
||||
case 0x09:
|
||||
break;
|
||||
case 0x0a:
|
||||
break;
|
||||
case 0x0b:
|
||||
read_key = 24;
|
||||
break;
|
||||
case 0x0c:
|
||||
read_key = 1;
|
||||
break;
|
||||
case 0x0d:
|
||||
read_key = 5;
|
||||
break;
|
||||
case 0x0e:
|
||||
read_key = 3;
|
||||
break;
|
||||
case 0x17:
|
||||
read_key = '\e';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return read_key;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_console_getkey (struct grub_term_input *term)
|
||||
{
|
||||
grub_efi_simple_input_interface_t *i;
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_uintn_t index;
|
||||
grub_efi_status_t status;
|
||||
int key;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
if (read_key >= 0)
|
||||
{
|
||||
key = read_key;
|
||||
read_key = -1;
|
||||
return key;
|
||||
}
|
||||
|
||||
i = grub_efi_system_table->con_in;
|
||||
b = grub_efi_system_table->boot_services;
|
||||
|
||||
do
|
||||
{
|
||||
status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return -1;
|
||||
|
||||
grub_console_checkkey (term);
|
||||
}
|
||||
while (read_key < 0);
|
||||
|
||||
key = read_key;
|
||||
read_key = -1;
|
||||
return key;
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
static grub_uint16_t
|
||||
|
@ -310,13 +204,14 @@ grub_console_setcolorstate (struct grub_term_output *term,
|
|||
|
||||
switch (state) {
|
||||
case GRUB_TERM_COLOR_STANDARD:
|
||||
efi_call_2 (o->set_attributes, o, grub_console_standard_color);
|
||||
efi_call_2 (o->set_attributes, o, GRUB_TERM_DEFAULT_STANDARD_COLOR
|
||||
& 0x7f);
|
||||
break;
|
||||
case GRUB_TERM_COLOR_NORMAL:
|
||||
efi_call_2 (o->set_attributes, o, term->normal_color);
|
||||
efi_call_2 (o->set_attributes, o, term->normal_color & 0x7f);
|
||||
break;
|
||||
case GRUB_TERM_COLOR_HIGHLIGHT:
|
||||
efi_call_2 (o->set_attributes, o, term->highlight_color);
|
||||
efi_call_2 (o->set_attributes, o, term->highlight_color & 0x7f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -353,7 +248,6 @@ grub_efi_console_fini (struct grub_term_output *term)
|
|||
static struct grub_term_input grub_console_term_input =
|
||||
{
|
||||
.name = "console",
|
||||
.checkkey = grub_console_checkkey,
|
||||
.getkey = grub_console_getkey,
|
||||
};
|
||||
|
||||
|
@ -369,10 +263,8 @@ static struct grub_term_output grub_console_term_output =
|
|||
.cls = grub_console_cls,
|
||||
.setcolorstate = grub_console_setcolorstate,
|
||||
.setcursor = grub_console_setcursor,
|
||||
.normal_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_LIGHTGRAY,
|
||||
GRUB_EFI_BACKGROUND_BLACK),
|
||||
.highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_BLACK,
|
||||
GRUB_EFI_BACKGROUND_LIGHTGRAY),
|
||||
.normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
||||
.highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
||||
.flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS
|
||||
};
|
||||
|
||||
|
|
|
@ -1113,11 +1113,10 @@ static const struct grub_arg_option background_image_cmd_options[] =
|
|||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)),
|
||||
int argc,
|
||||
char **args)
|
||||
grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt,
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
|
||||
/* Check that we have video adapter active. */
|
||||
if (grub_video_get_info(NULL) != GRUB_ERR_NONE)
|
||||
|
@ -1208,8 +1207,7 @@ GRUB_MOD_INIT(gfxterm)
|
|||
grub_term_register_output ("gfxterm", &grub_video_term);
|
||||
background_image_cmd_handle =
|
||||
grub_register_extcmd ("background_image",
|
||||
grub_gfxterm_background_image_cmd,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
grub_gfxterm_background_image_cmd, 0,
|
||||
N_("[-m (stretch|normal)] FILE"),
|
||||
N_("Load background image for active terminal."),
|
||||
background_image_cmd_options);
|
||||
|
|
|
@ -24,33 +24,18 @@
|
|||
static const struct grub_machine_bios_data_area *bios_data_area =
|
||||
(struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR;
|
||||
|
||||
#define KEYBOARD_LEFT_SHIFT (1 << 0)
|
||||
#define KEYBOARD_RIGHT_SHIFT (1 << 1)
|
||||
#define KEYBOARD_CTRL (1 << 2)
|
||||
#define KEYBOARD_ALT (1 << 3)
|
||||
|
||||
static int
|
||||
grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
grub_uint8_t status = bios_data_area->keyboard_flag_lower;
|
||||
int mods = 0;
|
||||
|
||||
if (status & (KEYBOARD_LEFT_SHIFT | KEYBOARD_RIGHT_SHIFT))
|
||||
mods |= GRUB_TERM_STATUS_SHIFT;
|
||||
if (status & KEYBOARD_CTRL)
|
||||
mods |= GRUB_TERM_STATUS_CTRL;
|
||||
if (status & KEYBOARD_ALT)
|
||||
mods |= GRUB_TERM_STATUS_ALT;
|
||||
|
||||
return mods;
|
||||
/* conveniently GRUB keystatus is modelled after BIOS one. */
|
||||
return bios_data_area->keyboard_flag_lower & ~0x80;
|
||||
}
|
||||
|
||||
static struct grub_term_input grub_console_term_input =
|
||||
{
|
||||
.name = "console",
|
||||
.checkkey = grub_console_checkkey,
|
||||
.getkey = grub_console_getkey,
|
||||
.getkeystatus = grub_console_getkeystatus,
|
||||
.getkeystatus = grub_console_getkeystatus
|
||||
};
|
||||
|
||||
static struct grub_term_output grub_console_term_output =
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2007, 2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -27,18 +27,18 @@
|
|||
|
||||
static int grub_curr_x, grub_curr_y;
|
||||
|
||||
#define VGA_TEXT_SCREEN 0xb8000
|
||||
#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb8000)
|
||||
|
||||
static void
|
||||
screen_write_char (int x, int y, short c)
|
||||
{
|
||||
((short *) VGA_TEXT_SCREEN)[y * COLS + x] = c;
|
||||
VGA_TEXT_SCREEN[y * COLS + x] = c;
|
||||
}
|
||||
|
||||
static short
|
||||
screen_read_char (int x, int y)
|
||||
{
|
||||
return ((short *) VGA_TEXT_SCREEN)[y * COLS + x];
|
||||
return VGA_TEXT_SCREEN[y * COLS + x];
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -120,7 +120,7 @@ grub_vga_text_cls (struct grub_term_output *term)
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < ROWS * COLS; i++)
|
||||
((short *) VGA_TEXT_SCREEN)[i] = ' ' | (grub_console_cur_color << 8);
|
||||
VGA_TEXT_SCREEN[i] = ' ' | (grub_console_cur_color << 8);
|
||||
grub_vga_text_gotoxy (term, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
static grub_ieee1275_ihandle_t stdout_ihandle;
|
||||
static grub_ieee1275_ihandle_t stdin_ihandle;
|
||||
|
||||
static grub_uint8_t grub_ofconsole_width;
|
||||
static grub_uint8_t grub_ofconsole_height;
|
||||
extern struct grub_terminfo_output_state grub_ofconsole_terminfo_output;
|
||||
|
||||
struct color
|
||||
{
|
||||
|
@ -91,7 +90,8 @@ grub_ofconsole_dimensions (void)
|
|||
|
||||
if (! grub_ieee1275_get_property (options, "screen-#columns",
|
||||
val, lval, 0))
|
||||
grub_ofconsole_width = (grub_uint8_t) grub_strtoul (val, 0, 10);
|
||||
grub_ofconsole_terminfo_output.width
|
||||
= (grub_uint8_t) grub_strtoul (val, 0, 10);
|
||||
}
|
||||
if (! grub_ieee1275_get_property_length (options, "screen-#rows", &lval)
|
||||
&& lval >= 0 && lval < 1024)
|
||||
|
@ -99,27 +99,27 @@ grub_ofconsole_dimensions (void)
|
|||
char val[lval];
|
||||
if (! grub_ieee1275_get_property (options, "screen-#rows",
|
||||
val, lval, 0))
|
||||
grub_ofconsole_height = (grub_uint8_t) grub_strtoul (val, 0, 10);
|
||||
grub_ofconsole_terminfo_output.height
|
||||
= (grub_uint8_t) grub_strtoul (val, 0, 10);
|
||||
}
|
||||
}
|
||||
|
||||
/* Use a small console by default. */
|
||||
if (! grub_ofconsole_width)
|
||||
grub_ofconsole_width = 80;
|
||||
if (! grub_ofconsole_height)
|
||||
grub_ofconsole_height = 24;
|
||||
}
|
||||
|
||||
static grub_uint16_t
|
||||
grub_ofconsole_getwh (struct grub_term_output *term __attribute__ ((unused)))
|
||||
{
|
||||
return (grub_ofconsole_width << 8) | grub_ofconsole_height;
|
||||
if (! grub_ofconsole_terminfo_output.width)
|
||||
grub_ofconsole_terminfo_output.width = 80;
|
||||
if (! grub_ofconsole_terminfo_output.height)
|
||||
grub_ofconsole_terminfo_output.height = 24;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_ofconsole_setcursor (struct grub_term_output *term __attribute__ ((unused)),
|
||||
grub_ofconsole_setcursor (struct grub_term_output *term,
|
||||
int on)
|
||||
{
|
||||
grub_terminfo_setcursor (term, on);
|
||||
|
||||
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF))
|
||||
return;
|
||||
|
||||
/* Understood by the Open Firmware flavour in OLPC. */
|
||||
if (on)
|
||||
grub_ieee1275_interpret ("cursor-on", 0);
|
||||
|
@ -182,14 +182,15 @@ struct grub_terminfo_input_state grub_ofconsole_terminfo_input =
|
|||
|
||||
struct grub_terminfo_output_state grub_ofconsole_terminfo_output =
|
||||
{
|
||||
.put = put
|
||||
.put = put,
|
||||
.width = 80,
|
||||
.height = 24
|
||||
};
|
||||
|
||||
static struct grub_term_input grub_ofconsole_term_input =
|
||||
{
|
||||
.name = "ofconsole",
|
||||
.init = grub_ofconsole_init_input,
|
||||
.checkkey = grub_terminfo_checkkey,
|
||||
.getkey = grub_terminfo_getkey,
|
||||
.data = &grub_ofconsole_terminfo_input
|
||||
};
|
||||
|
@ -200,7 +201,7 @@ static struct grub_term_output grub_ofconsole_term_output =
|
|||
.init = grub_ofconsole_init_output,
|
||||
.putchar = grub_terminfo_putchar,
|
||||
.getxy = grub_terminfo_getxy,
|
||||
.getwh = grub_ofconsole_getwh,
|
||||
.getwh = grub_terminfo_getwh,
|
||||
.gotoxy = grub_terminfo_gotoxy,
|
||||
.cls = grub_terminfo_cls,
|
||||
.setcolorstate = grub_terminfo_setcolorstate,
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/serial.h>
|
||||
#include <grub/ns8250.h>
|
||||
#include <grub/types.h>
|
||||
|
@ -24,8 +23,10 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
#include <grub/machine/memory.h>
|
||||
static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR;
|
||||
#define GRUB_SERIAL_PORT_NUM 4
|
||||
#else
|
||||
|
@ -90,6 +91,8 @@ do_real_config (struct grub_serial_port *port)
|
|||
if (port->configured)
|
||||
return;
|
||||
|
||||
port->broken = 0;
|
||||
|
||||
divisor = serial_get_divisor (port->config.speed);
|
||||
|
||||
/* Turn off the interrupt. */
|
||||
|
@ -145,18 +148,30 @@ serial_hw_fetch (struct grub_serial_port *port)
|
|||
static void
|
||||
serial_hw_put (struct grub_serial_port *port, const int c)
|
||||
{
|
||||
unsigned int timeout = 100000;
|
||||
grub_uint64_t endtime;
|
||||
|
||||
do_real_config (port);
|
||||
|
||||
if (port->broken > 5)
|
||||
endtime = grub_get_time_ms ();
|
||||
else if (port->broken > 1)
|
||||
endtime = grub_get_time_ms () + 50;
|
||||
else
|
||||
endtime = grub_get_time_ms () + 200;
|
||||
/* Wait until the transmitter holding register is empty. */
|
||||
while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
|
||||
{
|
||||
if (--timeout == 0)
|
||||
/* There is something wrong. But what can I do? */
|
||||
return;
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
port->broken++;
|
||||
/* There is something wrong. But what can I do? */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (port->broken)
|
||||
port->broken--;
|
||||
|
||||
grub_outb (c, port->port + UART_TX);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,14 +55,6 @@ struct grub_serial_input_state
|
|||
struct grub_serial_port *port;
|
||||
};
|
||||
|
||||
static grub_uint16_t
|
||||
grub_serial_getwh (struct grub_term_output *term __attribute__ ((unused)))
|
||||
{
|
||||
const grub_uint8_t TEXT_WIDTH = 80;
|
||||
const grub_uint8_t TEXT_HEIGHT = 24;
|
||||
return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
|
||||
}
|
||||
|
||||
static void
|
||||
serial_put (grub_term_output_t term, const int c)
|
||||
{
|
||||
|
@ -77,7 +69,7 @@ serial_fetch (grub_term_input_t term)
|
|||
return data->port->driver->fetch (data->port);
|
||||
}
|
||||
|
||||
struct grub_serial_input_state grub_serial_terminfo_input =
|
||||
const struct grub_serial_input_state grub_serial_terminfo_input_template =
|
||||
{
|
||||
.tinfo =
|
||||
{
|
||||
|
@ -85,21 +77,26 @@ struct grub_serial_input_state grub_serial_terminfo_input =
|
|||
}
|
||||
};
|
||||
|
||||
struct grub_serial_output_state grub_serial_terminfo_output =
|
||||
const struct grub_serial_output_state grub_serial_terminfo_output_template =
|
||||
{
|
||||
.tinfo =
|
||||
{
|
||||
.put = serial_put
|
||||
.put = serial_put,
|
||||
.width = 80,
|
||||
.height = 24
|
||||
}
|
||||
};
|
||||
|
||||
struct grub_serial_input_state grub_serial_terminfo_input;
|
||||
|
||||
struct grub_serial_output_state grub_serial_terminfo_output;
|
||||
|
||||
int registered = 0;
|
||||
|
||||
static struct grub_term_input grub_serial_term_input =
|
||||
{
|
||||
.name = "serial",
|
||||
.init = grub_terminfo_input_init,
|
||||
.checkkey = grub_terminfo_checkkey,
|
||||
.getkey = grub_terminfo_getkey,
|
||||
.data = &grub_serial_terminfo_input
|
||||
};
|
||||
|
@ -108,7 +105,7 @@ static struct grub_term_output grub_serial_term_output =
|
|||
{
|
||||
.name = "serial",
|
||||
.putchar = grub_terminfo_putchar,
|
||||
.getwh = grub_serial_getwh,
|
||||
.getwh = grub_terminfo_getwh,
|
||||
.getxy = grub_terminfo_getxy,
|
||||
.gotoxy = grub_terminfo_gotoxy,
|
||||
.cls = grub_terminfo_cls,
|
||||
|
@ -150,9 +147,9 @@ grub_serial_find (char *name)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_serial (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
char pname[40];
|
||||
char *name = NULL;
|
||||
struct grub_serial_port *port;
|
||||
|
@ -223,6 +220,8 @@ grub_cmd_serial (grub_extcmd_t cmd, int argc, char **args)
|
|||
{
|
||||
if (!registered)
|
||||
{
|
||||
grub_terminfo_output_register (&grub_serial_term_output, "vt100");
|
||||
|
||||
grub_term_register_input ("serial", &grub_serial_term_input);
|
||||
grub_term_register_output ("serial", &grub_serial_term_output);
|
||||
}
|
||||
|
@ -341,10 +340,17 @@ static grub_extcmd_t cmd;
|
|||
|
||||
GRUB_MOD_INIT(serial)
|
||||
{
|
||||
cmd = grub_register_extcmd ("serial", grub_cmd_serial,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0,
|
||||
N_("[OPTIONS...]"),
|
||||
N_("Configure serial port."), options);
|
||||
grub_memcpy (&grub_serial_terminfo_output,
|
||||
&grub_serial_terminfo_output_template,
|
||||
sizeof (grub_serial_terminfo_output));
|
||||
|
||||
grub_memcpy (&grub_serial_terminfo_input,
|
||||
&grub_serial_terminfo_input_template,
|
||||
sizeof (grub_serial_terminfo_input));
|
||||
|
||||
#ifndef GRUB_MACHINE_EMU
|
||||
grub_ns8250_init ();
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <grub/term.h>
|
||||
#include <grub/terminfo.h>
|
||||
#include <grub/tparm.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
|
@ -358,6 +358,15 @@ grub_terminfo_putchar (struct grub_term_output *term,
|
|||
data->put (term, c->base);
|
||||
}
|
||||
|
||||
grub_uint16_t
|
||||
grub_terminfo_getwh (struct grub_term_output *term)
|
||||
{
|
||||
struct grub_terminfo_output_state *data
|
||||
= (struct grub_terminfo_output_state *) term->data;
|
||||
|
||||
return (data->width << 8) | data->height;
|
||||
}
|
||||
|
||||
#define ANSI_C0 0x9b
|
||||
|
||||
static void
|
||||
|
@ -403,34 +412,34 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
|
|||
static struct
|
||||
{
|
||||
char key;
|
||||
char ascii;
|
||||
unsigned ascii;
|
||||
}
|
||||
three_code_table[] =
|
||||
{
|
||||
{'4', GRUB_TERM_DC},
|
||||
{'A', GRUB_TERM_UP},
|
||||
{'B', GRUB_TERM_DOWN},
|
||||
{'C', GRUB_TERM_RIGHT},
|
||||
{'D', GRUB_TERM_LEFT},
|
||||
{'F', GRUB_TERM_END},
|
||||
{'H', GRUB_TERM_HOME},
|
||||
{'K', GRUB_TERM_END},
|
||||
{'P', GRUB_TERM_DC},
|
||||
{'?', GRUB_TERM_PPAGE},
|
||||
{'/', GRUB_TERM_NPAGE}
|
||||
{'4', GRUB_TERM_KEY_DC},
|
||||
{'A', GRUB_TERM_KEY_UP},
|
||||
{'B', GRUB_TERM_KEY_DOWN},
|
||||
{'C', GRUB_TERM_KEY_RIGHT},
|
||||
{'D', GRUB_TERM_KEY_LEFT},
|
||||
{'F', GRUB_TERM_KEY_END},
|
||||
{'H', GRUB_TERM_KEY_HOME},
|
||||
{'K', GRUB_TERM_KEY_END},
|
||||
{'P', GRUB_TERM_KEY_DC},
|
||||
{'?', GRUB_TERM_KEY_PPAGE},
|
||||
{'/', GRUB_TERM_KEY_NPAGE}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
char key;
|
||||
char ascii;
|
||||
unsigned ascii;
|
||||
}
|
||||
four_code_table[] =
|
||||
{
|
||||
{'1', GRUB_TERM_HOME},
|
||||
{'3', GRUB_TERM_DC},
|
||||
{'5', GRUB_TERM_PPAGE},
|
||||
{'6', GRUB_TERM_NPAGE}
|
||||
{'1', GRUB_TERM_KEY_HOME},
|
||||
{'3', GRUB_TERM_KEY_DC},
|
||||
{'5', GRUB_TERM_KEY_PPAGE},
|
||||
{'6', GRUB_TERM_KEY_NPAGE}
|
||||
};
|
||||
unsigned i;
|
||||
|
||||
|
@ -467,39 +476,30 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
|
|||
#undef CONTINUE_READ
|
||||
}
|
||||
|
||||
/* The terminfo version of checkkey. */
|
||||
int
|
||||
grub_terminfo_checkkey (struct grub_term_input *termi)
|
||||
{
|
||||
struct grub_terminfo_input_state *data
|
||||
= (struct grub_terminfo_input_state *) (termi->data);
|
||||
if (data->npending)
|
||||
return data->input_buf[0];
|
||||
|
||||
grub_terminfo_readkey (termi, data->input_buf,
|
||||
&data->npending, data->readkey);
|
||||
|
||||
if (data->npending)
|
||||
return data->input_buf[0];
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The terminfo version of getkey. */
|
||||
int
|
||||
grub_terminfo_getkey (struct grub_term_input *termi)
|
||||
{
|
||||
struct grub_terminfo_input_state *data
|
||||
= (struct grub_terminfo_input_state *) (termi->data);
|
||||
int ret;
|
||||
while (! data->npending)
|
||||
grub_terminfo_readkey (termi, data->input_buf, &data->npending,
|
||||
data->readkey);
|
||||
if (data->npending)
|
||||
{
|
||||
data->npending--;
|
||||
grub_memmove (data->input_buf, data->input_buf + 1, data->npending);
|
||||
return data->input_buf[0];
|
||||
}
|
||||
|
||||
ret = data->input_buf[0];
|
||||
data->npending--;
|
||||
grub_memmove (data->input_buf, data->input_buf + 1, data->npending);
|
||||
return ret;
|
||||
grub_terminfo_readkey (termi, data->input_buf,
|
||||
&data->npending, data->readkey);
|
||||
|
||||
if (data->npending)
|
||||
{
|
||||
data->npending--;
|
||||
grub_memmove (data->input_buf, data->input_buf + 1, data->npending);
|
||||
return data->input_buf[0];
|
||||
}
|
||||
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
|
@ -546,85 +546,96 @@ print_terminfo (void)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"ascii", 'a', 0, N_("Terminal is ASCII-only [default]."), 0, ARG_TYPE_NONE},
|
||||
{"utf8", 'u', 0, N_("Terminal is logical-ordered UTF-8."), 0, ARG_TYPE_NONE},
|
||||
{"visual-utf8", 'v', 0, N_("Terminal is visually-ordered UTF-8."), 0,
|
||||
ARG_TYPE_NONE},
|
||||
{"geometry", 'g', 0, N_("Terminal has given geometry."),
|
||||
N_("WIDTHxHEIGHT."), ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
OPTION_ASCII,
|
||||
OPTION_UTF8,
|
||||
OPTION_VISUAL_UTF8,
|
||||
OPTION_GEOMETRY
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_terminfo (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
grub_cmd_terminfo (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_term_output *cur;
|
||||
int encoding = GRUB_TERM_CODE_TYPE_ASCII;
|
||||
int i;
|
||||
char *name = NULL, *type = NULL;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
int w = 0, h = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return print_terminfo ();
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
if (state[OPTION_ASCII].set)
|
||||
encoding = GRUB_TERM_CODE_TYPE_ASCII;
|
||||
|
||||
if (state[OPTION_UTF8].set)
|
||||
encoding = GRUB_TERM_CODE_TYPE_UTF8_LOGICAL;
|
||||
|
||||
if (state[OPTION_VISUAL_UTF8].set)
|
||||
encoding = GRUB_TERM_CODE_TYPE_UTF8_VISUAL;
|
||||
|
||||
if (state[OPTION_GEOMETRY].set)
|
||||
{
|
||||
if (grub_strcmp (args[i], "-a") == 0
|
||||
|| grub_strcmp (args[i], "--ascii") == 0)
|
||||
{
|
||||
encoding = GRUB_TERM_CODE_TYPE_ASCII;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[i], "-u") == 0
|
||||
|| grub_strcmp (args[i], "--utf8") == 0)
|
||||
{
|
||||
encoding = GRUB_TERM_CODE_TYPE_UTF8_LOGICAL;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[i], "-v") == 0
|
||||
|| grub_strcmp (args[i], "--visual-utf8") == 0)
|
||||
{
|
||||
encoding = GRUB_TERM_CODE_TYPE_UTF8_VISUAL;
|
||||
continue;
|
||||
}
|
||||
if (!name)
|
||||
{
|
||||
name = args[i];
|
||||
continue;
|
||||
}
|
||||
if (!type)
|
||||
{
|
||||
type = args[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters");
|
||||
char *ptr = state[OPTION_GEOMETRY].arg;
|
||||
w = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != 'x')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"incorrect geometry specification");
|
||||
ptr++;
|
||||
h = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few parameters");
|
||||
|
||||
for (cur = terminfo_outputs; cur;
|
||||
cur = ((struct grub_terminfo_output_state *) cur->data)->next)
|
||||
if (grub_strcmp (name, cur->name) == 0)
|
||||
if (grub_strcmp (args[0], cur->name) == 0)
|
||||
{
|
||||
cur->flags = (cur->flags & ~GRUB_TERM_CODE_TYPE_MASK) | encoding;
|
||||
if (!type)
|
||||
|
||||
if (w && h)
|
||||
{
|
||||
struct grub_terminfo_output_state *data
|
||||
= (struct grub_terminfo_output_state *) cur->data;
|
||||
data->width = w;
|
||||
data->height = h;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
return grub_terminfo_set_current (cur, type);
|
||||
return grub_terminfo_set_current (cur, args[1]);
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no terminal %s found or it's not handled by terminfo",
|
||||
name);
|
||||
args[0]);
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(terminfo)
|
||||
{
|
||||
cmd = grub_register_command ("terminfo", grub_cmd_terminfo,
|
||||
N_("[[-a|-u|-v] TERM [TYPE]]"),
|
||||
N_("Set terminfo type of TERM to TYPE.\n"
|
||||
"-a, --ascii Terminal is ASCII-only [default].\n"
|
||||
"-u, --utf8 Terminal is logical-ordered UTF-8.\n"
|
||||
"-v, --visual-utf8 Terminal is visually-ordered UTF-8.")
|
||||
|
||||
);
|
||||
cmd = grub_register_extcmd ("terminfo", grub_cmd_terminfo, 0,
|
||||
N_("[[-a|-u|-v] [-g WxH] TERM [TYPE]]"),
|
||||
N_("Set terminfo type of TERM to TYPE.\n"),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(terminfo)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
|
@ -25,36 +25,26 @@
|
|||
#include <grub/usb.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/keyboard_layouts.h>
|
||||
|
||||
|
||||
static char keyboard_map[128] =
|
||||
|
||||
enum
|
||||
{
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd',
|
||||
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
|
||||
'3', '4', '5', '6', '7', '8', '9', '0',
|
||||
'\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[',
|
||||
']', '\\', '#', ';', '\'', '`', ',', '.',
|
||||
'/', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT,
|
||||
GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP
|
||||
KEY_NO_KEY = 0x00,
|
||||
KEY_ERR_BUFFER = 0x01,
|
||||
KEY_ERR_POST = 0x02,
|
||||
KEY_ERR_UNDEF = 0x03,
|
||||
KEY_CAPS_LOCK = 0x39,
|
||||
KEY_NUM_LOCK = 0x53,
|
||||
};
|
||||
|
||||
static char keyboard_map_shift[128] =
|
||||
enum
|
||||
{
|
||||
'\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D',
|
||||
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||
'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
|
||||
'#', '$', '%', '^', '&', '*', '(', ')',
|
||||
'\n', '\0', '\0', '\0', ' ', '_', '+', '{',
|
||||
'}', '|', '#', ':', '"', '`', '<', '>',
|
||||
'?'
|
||||
LED_NUM_LOCK = 0x01,
|
||||
LED_CAPS_LOCK = 0x02
|
||||
};
|
||||
|
||||
|
||||
/* Valid values for bRequest. See HID definition version 1.11 section 7.2. */
|
||||
#define USB_HID_GET_REPORT 0x01
|
||||
#define USB_HID_GET_IDLE 0x02
|
||||
|
@ -66,28 +56,65 @@ static char keyboard_map_shift[128] =
|
|||
#define USB_HID_BOOT_SUBCLASS 0x01
|
||||
#define USB_HID_KBD_PROTOCOL 0x01
|
||||
|
||||
static int grub_usb_keyboard_checkkey (struct grub_term_input *term);
|
||||
static int grub_usb_keyboard_getkey (struct grub_term_input *term);
|
||||
static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term);
|
||||
|
||||
static struct grub_term_input grub_usb_keyboard_term =
|
||||
{
|
||||
.checkkey = grub_usb_keyboard_checkkey,
|
||||
.getkey = grub_usb_keyboard_getkey,
|
||||
.getkeystatus = grub_usb_keyboard_getkeystatus,
|
||||
.next = 0
|
||||
};
|
||||
#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01
|
||||
#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02
|
||||
#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04
|
||||
#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10
|
||||
#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20
|
||||
#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40
|
||||
|
||||
struct grub_usb_keyboard_data
|
||||
{
|
||||
grub_usb_device_t usbdev;
|
||||
grub_uint8_t status;
|
||||
int key;
|
||||
grub_uint16_t mods;
|
||||
int interfno;
|
||||
struct grub_usb_desc_endp *endp;
|
||||
grub_usb_transfer_t transfer;
|
||||
grub_uint8_t report[8];
|
||||
int dead;
|
||||
int last_key;
|
||||
grub_uint64_t repeat_time;
|
||||
grub_uint8_t current_report[8];
|
||||
grub_uint8_t last_report[8];
|
||||
int index;
|
||||
int max_index;
|
||||
};
|
||||
|
||||
static int grub_usb_keyboard_getkey (struct grub_term_input *term);
|
||||
static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term);
|
||||
|
||||
static struct grub_term_input grub_usb_keyboard_term =
|
||||
{
|
||||
.getkey = grub_usb_keyboard_getkey,
|
||||
.getkeystatus = grub_usb_keyboard_getkeystatus,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
static struct grub_term_input grub_usb_keyboards[16];
|
||||
|
||||
static int
|
||||
interpret_status (grub_uint8_t data0)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
/* Check Shift, Control, and Alt status. */
|
||||
if (data0 & GRUB_USB_KEYBOARD_LEFT_SHIFT)
|
||||
mods |= GRUB_TERM_STATUS_LSHIFT;
|
||||
if (data0 & GRUB_USB_KEYBOARD_RIGHT_SHIFT)
|
||||
mods |= GRUB_TERM_STATUS_RSHIFT;
|
||||
if (data0 & GRUB_USB_KEYBOARD_LEFT_CTRL)
|
||||
mods |= GRUB_TERM_STATUS_LCTRL;
|
||||
if (data0 & GRUB_USB_KEYBOARD_RIGHT_CTRL)
|
||||
mods |= GRUB_TERM_STATUS_RCTRL;
|
||||
if (data0 & GRUB_USB_KEYBOARD_LEFT_ALT)
|
||||
mods |= GRUB_TERM_STATUS_LALT;
|
||||
if (data0 & GRUB_USB_KEYBOARD_RIGHT_ALT)
|
||||
mods |= GRUB_TERM_STATUS_RALT;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_usb_keyboard_detach (grub_usb_device_t usbdev,
|
||||
int config __attribute__ ((unused)),
|
||||
|
@ -104,6 +131,9 @@ grub_usb_keyboard_detach (grub_usb_device_t usbdev,
|
|||
if (data->usbdev != usbdev)
|
||||
continue;
|
||||
|
||||
if (data->transfer)
|
||||
grub_usb_cancel_transfer (data->transfer);
|
||||
|
||||
grub_term_unregister_input (&grub_usb_keyboards[i]);
|
||||
grub_free ((char *) grub_usb_keyboards[i].name);
|
||||
grub_usb_keyboards[i].name = NULL;
|
||||
|
@ -163,15 +193,19 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
}
|
||||
|
||||
data->usbdev = usbdev;
|
||||
data->interfno = interfno;
|
||||
data->endp = endp;
|
||||
|
||||
/* Configure device */
|
||||
grub_usb_set_configuration (usbdev, configno + 1);
|
||||
|
||||
/* Place the device in boot mode. */
|
||||
grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT,
|
||||
USB_HID_SET_PROTOCOL, 0, 0, 0, 0);
|
||||
USB_HID_SET_PROTOCOL, 0, interfno, 0, 0);
|
||||
|
||||
/* Reports every time an event occurs and not more often than that. */
|
||||
grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT,
|
||||
USB_HID_SET_IDLE, 0<<8, 0, 0, 0);
|
||||
USB_HID_SET_IDLE, 0<<8, interfno, 0, 0);
|
||||
|
||||
grub_memcpy (&grub_usb_keyboards[curnum], &grub_usb_keyboard_term,
|
||||
sizeof (grub_usb_keyboards[curnum]));
|
||||
|
@ -185,24 +219,41 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Test showed that getting report may make the keyboard go nuts.
|
||||
Moreover since we're reattaching keyboard it usually sends
|
||||
an initial message on interrupt pipe and so we retrieve
|
||||
the same keystatus.
|
||||
*/
|
||||
#if 0
|
||||
{
|
||||
grub_uint8_t report[8];
|
||||
grub_usb_err_t err;
|
||||
grub_memset (report, 0, sizeof (report));
|
||||
err = grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_IN,
|
||||
USB_HID_GET_REPORT, 0x0000, interfno,
|
||||
USB_HID_GET_REPORT, 0x0100, interfno,
|
||||
sizeof (report), (char *) report);
|
||||
if (err)
|
||||
{
|
||||
data->status = 0;
|
||||
data->key = -1;
|
||||
}
|
||||
data->status = 0;
|
||||
else
|
||||
{
|
||||
data->status = report[0];
|
||||
data->key = report[2] ? : -1;
|
||||
}
|
||||
data->status = report[0];
|
||||
}
|
||||
#else
|
||||
data->status = 0;
|
||||
#endif
|
||||
|
||||
data->transfer = grub_usb_bulk_read_background (usbdev,
|
||||
data->endp->endp_addr,
|
||||
sizeof (data->report),
|
||||
(char *) data->report);
|
||||
if (!data->transfer)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
data->last_key = -1;
|
||||
data->mods = 0;
|
||||
data->dead = 0;
|
||||
|
||||
grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]);
|
||||
|
||||
|
@ -211,83 +262,177 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
|
||||
|
||||
|
||||
static int
|
||||
grub_usb_keyboard_checkkey (struct grub_term_input *term)
|
||||
static void
|
||||
send_leds (struct grub_usb_keyboard_data *termdata)
|
||||
{
|
||||
grub_uint8_t data[8];
|
||||
grub_usb_err_t err;
|
||||
struct grub_usb_keyboard_data *termdata = term->data;
|
||||
grub_size_t actual;
|
||||
|
||||
if (termdata->key != -1)
|
||||
return termdata->key;
|
||||
|
||||
data[2] = 0;
|
||||
/* Poll interrupt pipe. */
|
||||
err = grub_usb_bulk_read_extended (termdata->usbdev,
|
||||
termdata->endp->endp_addr, sizeof (data),
|
||||
(char *) data, 10, &actual);
|
||||
if (err || actual < 1)
|
||||
return -1;
|
||||
|
||||
termdata->status = data[0];
|
||||
|
||||
if (actual < 3 || !data[2])
|
||||
return -1;
|
||||
|
||||
grub_dprintf ("usb_keyboard",
|
||||
"report: 0x%02x 0x%02x 0x%02x 0x%02x"
|
||||
" 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[4], data[5], data[6], data[7]);
|
||||
|
||||
/* Check if the Control or Shift key was pressed. */
|
||||
if (data[0] & 0x01 || data[0] & 0x10)
|
||||
termdata->key = keyboard_map[data[2]] - 'a' + 1;
|
||||
else if (data[0] & 0x02 || data[0] & 0x20)
|
||||
termdata->key = keyboard_map_shift[data[2]];
|
||||
else
|
||||
termdata->key = keyboard_map[data[2]];
|
||||
|
||||
if (termdata->key == 0)
|
||||
grub_printf ("Unknown key 0x%x detected\n", data[2]);
|
||||
|
||||
char report[1];
|
||||
report[0] = 0;
|
||||
if (termdata->mods & GRUB_TERM_STATUS_CAPS)
|
||||
report[0] |= LED_CAPS_LOCK;
|
||||
if (termdata->mods & GRUB_TERM_STATUS_NUM)
|
||||
report[0] |= LED_NUM_LOCK;
|
||||
grub_usb_control_msg (termdata->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT,
|
||||
USB_HID_SET_REPORT, 0x0200, termdata->interfno,
|
||||
sizeof (report), (char *) report);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
return termdata->key;
|
||||
static int
|
||||
parse_keycode (struct grub_usb_keyboard_data *termdata)
|
||||
{
|
||||
int index = termdata->index;
|
||||
int i, keycode;
|
||||
|
||||
/* Sanity check */
|
||||
if (index < 2)
|
||||
index = 2;
|
||||
|
||||
for ( ; index < termdata->max_index; index++)
|
||||
{
|
||||
keycode = termdata->current_report[index];
|
||||
|
||||
if (keycode == KEY_NO_KEY
|
||||
|| keycode == KEY_ERR_BUFFER
|
||||
|| keycode == KEY_ERR_POST
|
||||
|| keycode == KEY_ERR_UNDEF)
|
||||
{
|
||||
/* Don't parse (rest of) this report */
|
||||
termdata->index = 0;
|
||||
if (keycode != KEY_NO_KEY)
|
||||
/* Don't replace last report with current faulty report
|
||||
* in future ! */
|
||||
grub_memcpy (termdata->current_report,
|
||||
termdata->last_report,
|
||||
sizeof (termdata->report));
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
/* Try to find current keycode in last report. */
|
||||
for (i = 2; i < 8; i++)
|
||||
if (keycode == termdata->last_report[i])
|
||||
break;
|
||||
if (i < 8)
|
||||
/* Keycode is in last report, it means it was not released,
|
||||
* ignore it. */
|
||||
continue;
|
||||
|
||||
if (keycode == KEY_CAPS_LOCK)
|
||||
{
|
||||
termdata->mods ^= GRUB_TERM_STATUS_CAPS;
|
||||
send_leds (termdata);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keycode == KEY_NUM_LOCK)
|
||||
{
|
||||
termdata->mods ^= GRUB_TERM_STATUS_NUM;
|
||||
send_leds (termdata);
|
||||
continue;
|
||||
}
|
||||
|
||||
termdata->last_key = grub_term_map_key (keycode,
|
||||
interpret_status (termdata->current_report[0])
|
||||
| termdata->mods);
|
||||
termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL;
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
index++;
|
||||
if (index >= termdata->max_index)
|
||||
termdata->index = 0;
|
||||
else
|
||||
termdata->index = index;
|
||||
|
||||
return termdata->last_key;
|
||||
}
|
||||
|
||||
/* All keycodes parsed */
|
||||
termdata->index = 0;
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_usb_keyboard_getkey (struct grub_term_input *term)
|
||||
{
|
||||
int ret;
|
||||
grub_usb_err_t err;
|
||||
struct grub_usb_keyboard_data *termdata = term->data;
|
||||
grub_size_t actual;
|
||||
int keycode = GRUB_TERM_NO_KEY;
|
||||
|
||||
while (termdata->key == -1)
|
||||
grub_usb_keyboard_checkkey (term);
|
||||
if (termdata->dead)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
ret = termdata->key;
|
||||
if (termdata->index)
|
||||
keycode = parse_keycode (termdata);
|
||||
if (keycode != GRUB_TERM_NO_KEY)
|
||||
return keycode;
|
||||
|
||||
/* Poll interrupt pipe. */
|
||||
err = grub_usb_check_transfer (termdata->transfer, &actual);
|
||||
|
||||
termdata->key = -1;
|
||||
if (err == GRUB_USB_ERR_WAIT)
|
||||
{
|
||||
if (termdata->last_key != -1
|
||||
&& grub_get_time_ms () > termdata->repeat_time)
|
||||
{
|
||||
termdata->repeat_time = grub_get_time_ms ()
|
||||
+ GRUB_TERM_REPEAT_INTERVAL;
|
||||
return termdata->last_key;
|
||||
}
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (!err && (actual >= 3))
|
||||
grub_memcpy (termdata->last_report,
|
||||
termdata->current_report,
|
||||
sizeof (termdata->report));
|
||||
|
||||
grub_memcpy (termdata->current_report,
|
||||
termdata->report,
|
||||
sizeof (termdata->report));
|
||||
|
||||
termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev,
|
||||
termdata->endp->endp_addr,
|
||||
sizeof (termdata->report),
|
||||
(char *) termdata->report);
|
||||
if (!termdata->transfer)
|
||||
{
|
||||
grub_printf ("%s failed. Stopped\n", term->name);
|
||||
termdata->dead = 1;
|
||||
}
|
||||
|
||||
termdata->last_key = -1;
|
||||
|
||||
grub_dprintf ("usb_keyboard",
|
||||
"err = %d, actual = %" PRIuGRUB_SIZE
|
||||
" report: 0x%02x 0x%02x 0x%02x 0x%02x"
|
||||
" 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
err, actual,
|
||||
termdata->current_report[0], termdata->current_report[1],
|
||||
termdata->current_report[2], termdata->current_report[3],
|
||||
termdata->current_report[4], termdata->current_report[5],
|
||||
termdata->current_report[6], termdata->current_report[7]);
|
||||
|
||||
if (err || actual < 1)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
termdata->status = termdata->current_report[0];
|
||||
|
||||
if (actual < 3)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
termdata->index = 2; /* New data received. */
|
||||
termdata->max_index = actual;
|
||||
|
||||
return parse_keycode (termdata);
|
||||
}
|
||||
|
||||
static int
|
||||
grub_usb_keyboard_getkeystatus (struct grub_term_input *term)
|
||||
{
|
||||
struct grub_usb_keyboard_data *termdata = term->data;
|
||||
int mods = 0;
|
||||
|
||||
/* Check Shift, Control, and Alt status. */
|
||||
if (termdata->status & 0x02 || termdata->status & 0x20)
|
||||
mods |= GRUB_TERM_STATUS_SHIFT;
|
||||
if (termdata->status & 0x01 || termdata->status & 0x10)
|
||||
mods |= GRUB_TERM_STATUS_CTRL;
|
||||
if (termdata->status & 0x04 || termdata->status & 0x40)
|
||||
mods |= GRUB_TERM_STATUS_ALT;
|
||||
|
||||
return mods;
|
||||
return interpret_status (termdata->status) | termdata->mods;
|
||||
}
|
||||
|
||||
struct grub_usb_attach_desc attach_hook =
|
||||
|
@ -307,9 +452,18 @@ GRUB_MOD_FINI(usb_keyboard)
|
|||
for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++)
|
||||
if (grub_usb_keyboards[i].data)
|
||||
{
|
||||
struct grub_usb_keyboard_data *data = grub_usb_keyboards[i].data;
|
||||
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
if (data->transfer)
|
||||
grub_usb_cancel_transfer (data->transfer);
|
||||
|
||||
grub_term_unregister_input (&grub_usb_keyboards[i]);
|
||||
grub_free ((char *) grub_usb_keyboards[i].name);
|
||||
grub_usb_keyboards[i].name = NULL;
|
||||
grub_free (grub_usb_keyboards[i].data);
|
||||
grub_usb_keyboards[i].data = 0;
|
||||
}
|
||||
grub_usb_unregister_attach_hook_class (&attach_hook);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue