Add keyboard testing

This commit is contained in:
Juhani Krekelä 2022-01-23 16:27:08 +02:00
parent b3ee12fcc5
commit 766fc0f052
1 changed files with 134 additions and 1 deletions

135
kernel.c
View File

@ -1,3 +1,4 @@
//#define PORT_DEBUG
/* Based on Bare Bones tutorial on OSDev wiki */
#include <stdbool.h>
@ -112,9 +113,24 @@ void terminal_writestring(const char* data)
terminal_write(data, strlen(data));
}
const char hex[] = "0123456789abcdef";
void terminal_writehex(uint8_t byte) {
terminal_putchar(hex[byte >> 4]);
terminal_putchar(hex[byte & 0xf]);
}
// (out|in)port from sortix, Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen.
void outport8(uint16_t port, uint8_t value)
{
#ifdef PORT_DEBUG
terminal_writestring("<out ");
terminal_writehex(port >> 8);
terminal_writehex(port);
terminal_writestring(" ");
terminal_writehex(value);
terminal_writestring(">");
#endif
asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));
}
@ -122,6 +138,14 @@ uint8_t inport8(uint16_t port)
{
uint8_t result;
asm volatile("inb %1, %0" : "=a" (result) : "dN" (port));
#ifdef PORT_DEBUG
terminal_writestring("<in ");
terminal_writehex(port >> 8);
terminal_writehex(port);
terminal_writestring(" ");
terminal_writehex(result);
terminal_writestring(">");
#endif
return result;
}
@ -232,13 +256,122 @@ void disable_translation(void) {
write_config_8042(config);
}
uint8_t read_keyboard(void) {
while (!(status_8042() & (1<<0)));
return read_8042();
}
void enable_scanning(void) {
write_8042(0xf4);
if (read_keyboard() != 0xfa)
terminal_writestring("Enabling scanning failed\n");
while (status_8042() & (1<<0))
(void) read_8042();
}
void disable_scanning(void) {
write_8042(0xf5);
if (read_keyboard() != 0xfa)
terminal_writestring("Disabling scanning failed\n");
while (status_8042() & (1<<0))
(void) read_8042();
}
void set_scancode_set(uint8_t set) {
write_8042(0xf0);
write_8042(set);
if (read_keyboard() != 0xfa)
terminal_writestring("Setting scancode set failed\n");
while (status_8042() & (1<<0))
(void) read_8042();
}
uint8_t get_scancode_set(void) {
write_8042(0xf0);
write_8042(0);
if (read_keyboard() != 0xfa)
terminal_writestring("Getting scancode set failed\n");
uint8_t set;
while ( (set = read_keyboard()) == 0xfa );
return set;
}
#define KEY_A_SET1 0x1e
#define KEY_A_SET2 0x1c
#define KEY_A_MISINTERPRET 0x03
void print_key(uint8_t code) {
switch (code) {
case KEY_A_SET1: terminal_writestring("Set 1 A"); break;
case KEY_A_SET2: terminal_writestring("Set 2 A"); break;
case KEY_A_MISINTERPRET: terminal_writestring("Set 1 A misinterpreted as set 2 A"); break;
default:
terminal_writestring("Unknown byte ");
terminal_writehex(code);
break;
}
}
void key_prompt(uint8_t expect) {
enable_scanning();
terminal_writestring("Press A... ");
uint8_t code = read_keyboard();
if ( code == expect )
terminal_setcolor(vga_entry_color(VGA_COLOR_GREEN, VGA_COLOR_BLACK));
else
terminal_setcolor(vga_entry_color(VGA_COLOR_RED, VGA_COLOR_BLACK));
print_key(code);
if ( code == expect )
terminal_writestring("\n");
else
terminal_writestring("(!)\n");
terminal_setcolor(vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK));
read_keyboard(); // Key up
disable_scanning();
}
void kernel_main(void)
{
/* Initialize terminal interface */
terminal_initialize();
init_8042();
if (single_channel)
terminal_writestring("Assuming keyboard is channel 1\n");
terminal_writestring("\nTranslation initially ");
if (translation_initially)
terminal_writestring("on\n");
else
terminal_writestring("off\n");
key_prompt(translation_initially ? KEY_A_SET1 : KEY_A_SET2);
disable_translation();
terminal_writestring("\nTranslation off, scancode set initially ");
uint8_t initial_scancode = get_scancode_set();
terminal_writehex(initial_scancode);
terminal_writestring("\n");
key_prompt(initial_scancode == 1 ? KEY_A_SET1 : KEY_A_SET2);
set_scancode_set(1);
terminal_writestring("Translation off, trying set 1... scancode set set to ");
terminal_writehex(get_scancode_set());
terminal_writestring("\n");
key_prompt(KEY_A_SET1);
set_scancode_set(2);
terminal_writestring("Translation off, trying set 2... scancode set set to ");
terminal_writehex(get_scancode_set());
terminal_writestring("\n");
key_prompt(KEY_A_SET2);
set_scancode_set(1);
enable_translation();
terminal_writestring("\nTranslation on, trying set 1\n");
key_prompt(KEY_A_MISINTERPRET);
set_scancode_set(2);
terminal_writestring("Translation on, trying set 2\n");
key_prompt(KEY_A_SET1);
terminal_writestring("\nHanging\n");
}