diff --git a/inc/kernel/system/driver/keyboard.h b/inc/kernel/system/driver/keyboard.h new file mode 100644 index 0000000..92cbece --- /dev/null +++ b/inc/kernel/system/driver/keyboard.h @@ -0,0 +1,20 @@ +#include + +/************************ + *** Team Kitty, 2020 *** + *** Chroma *** + ***********************/ + +typedef struct { + char Char; + int Scancode; + bool Pressed; +} KeyboardData; + +typedef void (*KeyboardCallback)(KeyboardData* Frame); + +extern KeyboardCallback KeyboardCallbacks[16]; + +int SetupKBCallback(void (*Handler)(KeyboardData* Frame)); + +void UninstallKBCallback(int Index); \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c index ac1a7a9..86fb4de 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,5 +1,7 @@ #include -//#include +#include +#include +#include /************************ *** Team Kitty, 2020 *** @@ -11,13 +13,15 @@ * If a function isn't fired here, directly or indirectly, it is not run. */ - +static bool KernelLoaded = false; size_t KernelAddr = (size_t) &LoadAddr; size_t KernelEnd = (size_t) &end; address_space_t KernelAddressSpace; +void PrintPressedChar(KeyboardData* data); + int Main(void) { KernelAddressSpace = (address_space_t) {0}; @@ -38,25 +42,63 @@ int Main(void) { InitPrint(); - WriteStringWithFont("Initty Testing"); - PrepareCPU(); PCIEnumerate(); InitMemoryManager(); - //DrawSplash(); InitPrint(); InitPaging(); - Printf("Paging complete. System initialized.\r\n"); + Printf("Paging complete. System initialized.\n\r"); + KernelLoaded = true; + + SetForegroundColor(0x00FF0000); + WriteChar('C'); + SetForegroundColor(0x0000FF00); + WriteChar('h'); + SetForegroundColor(0x000000FF); + WriteChar('r'); + SetForegroundColor(0x00FFFF00); + WriteChar('o'); + SetForegroundColor(0x00FF00FF); + WriteChar('m'); + SetForegroundColor(0x0000FFFF); + WriteChar('a'); + WriteChar(' '); + SetForegroundColor(0x00FFFFFF); + WriteChar('T'); + SetForegroundColor(0x0000AAAA); + WriteChar('i'); + SetForegroundColor(0x00BBBBBB); + WriteChar('m'); + SetForegroundColor(0x001E2D42); + WriteChar('e'); + SetForegroundColor(0x00E0A969); + WriteChar('!'); + WriteChar('\n'); + + SetForegroundColor(0x00FFFFFF); + + int CharPrinterCallbackID = SetupKBCallback(&PrintPressedChar); + UNUSED(CharPrinterCallbackID); for (;;) {} return 0; +} +void PrintPressedChar(KeyboardData* data) { + if(!KernelLoaded) return; + + if(data->Pressed) { + SerialPrintf("Key released: [\\%c]\r\n", data->Char); + } else { + SerialPrintf("Key pressed: [\\%c (%x)]\r\n", data->Char, data->Scancode); + Printf("%c", data->Char); + } } void SomethingWentWrong(const char* Message) { diff --git a/src/system/drivers/keyboard.c b/src/system/drivers/keyboard.c index fd2cb6e..9c8be98 100644 --- a/src/system/drivers/keyboard.c +++ b/src/system/drivers/keyboard.c @@ -1,4 +1,5 @@ #include +#include /************************ *** Team Kitty, 2020 *** @@ -6,10 +7,10 @@ ***********************/ /* This file contains (mostly unused) implementations of a full PS/2 keyboard driver. - * + * * It provides provisions for full 2-way communication, as well as auxiliary key commands. * //TODO: Media keys? - * + * * Once this driver is to a workable state, I would like to start adding a proper keyboard buffer, * which will integrate with a window system. * @@ -19,14 +20,14 @@ char keys[128] = { 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', - 0, - 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#', - 0, + 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -49,7 +50,22 @@ char keys[128] = { 0, }; +KeyboardCallback KeyboardCallbacks[16] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +static int CurrentCallback = 0; + +int SetupKBCallback(void (*Handler)(KeyboardData* Frame)) { + KeyboardCallbacks[CurrentCallback++] = Handler; + return CurrentCallback; +} + +void UninstallKBCallback(int Number) { + KeyboardCallbacks[Number] = NULL; // 0 is used in the common check to make sure that the function is callable. + // This removes this callback from that check, ergo the function will no longer be called. +} void KbdEcho() { if(!KbdFlags.EchoCount) { @@ -101,15 +117,20 @@ void UpdateKeyboard(uint8_t msg) { break; } + KeyboardData data = (KeyboardData) { + .Scancode = msg, + .Pressed = msg > 0x80 && msg < 0xD8 ? true : false, + .Char = msg > 0x80 && msg < 0xD8 ? keys[msg - 0x80] : keys[msg] + }; + void (*Handler)(KeyboardData* data); - if(msg & 0x80) { - - } else { - SerialPrintf("Key pressed: [\\%c]\r\n", keys[msg]); - WriteChar(keys[msg]); + for(size_t handlerNum = 0; handlerNum < 16; handlerNum++) { + Handler = KeyboardCallbacks[handlerNum]; + if(Handler) { + Handler(&data); + } } - } void Send8042(size_t info) { diff --git a/src/system/interrupts.c b/src/system/interrupts.c index 95df84b..4161c9e 100644 --- a/src/system/interrupts.c +++ b/src/system/interrupts.c @@ -8,16 +8,16 @@ * * As they use the GCC interrupt attribute, * this file must be compiled without red- - * zone protection, thus all of these + * zone protection, thus all of these * functions are in their own file to * accomodate this. - * + * * Additionally, the kernel now has SSE/AVX support. * So this file and this file *alone* must be compiled with * -mgeneral-regs-only - * + * * Calling a function like so: - * + * * __attribute__((interrupt)) isr1(registers_t* frame) {} * * allows the function to be used to serve @@ -33,16 +33,15 @@ */ #include +#include #include #include -#define UNUSED(X) ((void)X) - const char* ExceptionStrings[] = { "Division by Zero", "Debug", "Non Maskable Interrupt", - "Breakpoint", + "Breakpoint", "Into Detected Overflow", "Out of Bounds", "Invalid Opcode", @@ -93,13 +92,10 @@ void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) { /* Only the first 32 ISR/IRQs are reserved for exceptions by the CPU. We can handle up to 512 interrupts total, though. */ if(Exception < 32) { - - FillScreen(0x0000FF00); + SetForegroundColor(0x0000FF00); + FillScreen(); /* ExceptionStrings is an array of c-strings defined in kernel.h */ - SerialPrintf("[ ISR] %s exception!\r\n", ExceptionStrings[Exception]); - //printf("%s exception!", ExceptionStrings[Exception]); - //panic(); } } @@ -110,16 +106,11 @@ void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception UNUSED(Frame); if(Exception < 32) { - - FillScreen(0x0000FF00); - + SetForegroundColor(0x0000FF00); + FillScreen(); SerialPrintf("[ ISR] ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode); SerialPrintf("[ ISR] %s exception!\r\n", ExceptionStrings[Exception]); while(true) {} - //serialPrint(ExceptionStrings[Exception]); - //serialPrintf(" Exception. Context given: %d\r\n", Frame->ErrorCode); - //printf("%s exception. Context: %x", ExceptionStrings[Exception], Frame->ErrorCode); - //panic(); } @@ -131,10 +122,6 @@ void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) { // First we need to define a function pointer.. void (*Handler)(INTERRUPT_FRAME* Frame); - // Tell the user we've got an interrupt in.. - //serial_print(0x3F8, "[INFO] Received IRQ: " + interrupt); - //printf("[INFO] Received IRQ: %x", Interrupt); - /* We set all uninitialized routines to 0, so the if(handler) check here allows us to safely tell whether we've actually got something for this IRQ. */ Handler = IRQ_Handlers[Interrupt]; @@ -147,7 +134,7 @@ void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) { /* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */ if(Interrupt > 7) WritePort(0xA0, 0x20, 1); - + /* In either case, we tell the Master PIC it's been read to receive any IRQ. */ WritePort(0x20, 0x20, 1); @@ -186,52 +173,52 @@ void EmptyIRQ(INTERRUPT_FRAME* frame) { UNUSED(frame); // Flash the borders green, then back to blue - + SetForegroundColor(0x0000FF00); for(size_t y = 0; y < bootldr.fb_height; y++) { for(size_t x = 0; x < 20; x++) { - DrawPixel(x, y, 0x0000FF00); + DrawPixel(x, y); } for(size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) { - DrawPixel(x, y, 0x0000FF00); + DrawPixel(x, y); } } for(size_t x = 0; x < bootldr.fb_width; x++) { for(size_t y = 0; y < 20; y++) { - DrawPixel(x, y, 0x0000FF00); + DrawPixel(x, y); } for(size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) { - DrawPixel(x, y, 0x0000FF00); + DrawPixel(x, y); } } for(size_t i = 0; i < 100000; i++) {} + SetForegroundColor(0x000000FF); for(size_t y = 0; y < bootldr.fb_height; y++) { for(size_t x = 0; x < 20; x++) { - DrawPixel(x, y, 0x000000FF); + DrawPixel(x, y); } for(size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) { - DrawPixel(x, y, 0x000000FF); + DrawPixel(x, y); } } for(size_t x = 0; x < bootldr.fb_width; x++) { for(size_t y = 0; y < 20; y++) { - DrawPixel(x, y, 0x000000FF); + DrawPixel(x, y); } for(size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) { - DrawPixel(x, y, 0x000000FF); + DrawPixel(x, y); } } } static void KeyboardCallback(INTERRUPT_FRAME* frame) { - UNUSED(frame); uint8_t msg = ReadPort(0x60, 1);