Add keyboard callbacks, with a default for writing to the screen.

This commit is contained in:
Curle 2021-06-16 17:24:46 +01:00
parent 9bac0669a3
commit 439e1d9040
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
4 changed files with 123 additions and 53 deletions

View File

@ -0,0 +1,20 @@
#include <kernel/chroma.h>
/************************
*** 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);

View File

@ -1,5 +1,7 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
//#include <kernel/system/screen.h> #include <kernel/video/draw.h>
#include <kernel/system/driver/keyboard.h>
#include <editor/main.h>
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
@ -11,13 +13,15 @@
* If a function isn't fired here, directly or indirectly, it is not run. * 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 KernelAddr = (size_t) &LoadAddr;
size_t KernelEnd = (size_t) &end; size_t KernelEnd = (size_t) &end;
address_space_t KernelAddressSpace; address_space_t KernelAddressSpace;
void PrintPressedChar(KeyboardData* data);
int Main(void) { int Main(void) {
KernelAddressSpace = (address_space_t) {0}; KernelAddressSpace = (address_space_t) {0};
@ -38,25 +42,63 @@ int Main(void) {
InitPrint(); InitPrint();
WriteStringWithFont("Initty Testing");
PrepareCPU(); PrepareCPU();
PCIEnumerate(); PCIEnumerate();
InitMemoryManager(); InitMemoryManager();
//DrawSplash();
InitPrint(); InitPrint();
InitPaging(); 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 (;;) {} for (;;) {}
return 0; 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) { void SomethingWentWrong(const char* Message) {

View File

@ -1,4 +1,5 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <kernel/system/driver/keyboard.h>
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
@ -6,10 +7,10 @@
***********************/ ***********************/
/* This file contains (mostly unused) implementations of a full PS/2 keyboard driver. /* 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. * It provides provisions for full 2-way communication, as well as auxiliary key commands.
* //TODO: Media keys? * //TODO: Media keys?
* *
* Once this driver is to a workable state, I would like to start adding a proper keyboard buffer, * 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. * which will integrate with a window system.
* *
@ -19,14 +20,14 @@ char keys[128] = {
0, 27, 0, 27,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
0, 0,
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#',
0, 0,
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\\', '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, 0,
0, 0,
0, 0,
@ -49,7 +50,22 @@ char keys[128] = {
0, 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() { void KbdEcho() {
if(!KbdFlags.EchoCount) { if(!KbdFlags.EchoCount) {
@ -101,15 +117,20 @@ void UpdateKeyboard(uint8_t msg) {
break; 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) { for(size_t handlerNum = 0; handlerNum < 16; handlerNum++) {
Handler = KeyboardCallbacks[handlerNum];
} else { if(Handler) {
SerialPrintf("Key pressed: [\\%c]\r\n", keys[msg]); Handler(&data);
WriteChar(keys[msg]); }
} }
} }
void Send8042(size_t info) { void Send8042(size_t info) {

View File

@ -8,16 +8,16 @@
* *
* As they use the GCC interrupt attribute, * As they use the GCC interrupt attribute,
* this file must be compiled without red- * 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 * functions are in their own file to
* accomodate this. * accomodate this.
* *
* Additionally, the kernel now has SSE/AVX support. * Additionally, the kernel now has SSE/AVX support.
* So this file and this file *alone* must be compiled with * So this file and this file *alone* must be compiled with
* -mgeneral-regs-only * -mgeneral-regs-only
* *
* Calling a function like so: * Calling a function like so:
* *
* __attribute__((interrupt)) isr1(registers_t* frame) {} * __attribute__((interrupt)) isr1(registers_t* frame) {}
* *
* allows the function to be used to serve * allows the function to be used to serve
@ -33,16 +33,15 @@
*/ */
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <kernel/video/draw.h>
#include <kernel/system/interrupts.h> #include <kernel/system/interrupts.h>
#include <stdbool.h> #include <stdbool.h>
#define UNUSED(X) ((void)X)
const char* ExceptionStrings[] = { const char* ExceptionStrings[] = {
"Division by Zero", "Division by Zero",
"Debug", "Debug",
"Non Maskable Interrupt", "Non Maskable Interrupt",
"Breakpoint", "Breakpoint",
"Into Detected Overflow", "Into Detected Overflow",
"Out of Bounds", "Out of Bounds",
"Invalid Opcode", "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. */ /* 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) { if(Exception < 32) {
SetForegroundColor(0x0000FF00);
FillScreen(0x0000FF00); FillScreen();
/* ExceptionStrings is an array of c-strings defined in kernel.h */ /* ExceptionStrings is an array of c-strings defined in kernel.h */
SerialPrintf("[ ISR] %s exception!\r\n", ExceptionStrings[Exception]); 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); UNUSED(Frame);
if(Exception < 32) { if(Exception < 32) {
SetForegroundColor(0x0000FF00);
FillScreen(0x0000FF00); FillScreen();
SerialPrintf("[ ISR] ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode); SerialPrintf("[ ISR] ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode);
SerialPrintf("[ ISR] %s exception!\r\n", ExceptionStrings[Exception]); SerialPrintf("[ ISR] %s exception!\r\n", ExceptionStrings[Exception]);
while(true) {} 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.. // First we need to define a function pointer..
void (*Handler)(INTERRUPT_FRAME* Frame); 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 /* 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. */ safely tell whether we've actually got something for this IRQ. */
Handler = IRQ_Handlers[Interrupt]; 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. */ /* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */
if(Interrupt > 7) if(Interrupt > 7)
WritePort(0xA0, 0x20, 1); WritePort(0xA0, 0x20, 1);
/* In either case, we tell the Master PIC it's been read to receive any IRQ. */ /* In either case, we tell the Master PIC it's been read to receive any IRQ. */
WritePort(0x20, 0x20, 1); WritePort(0x20, 0x20, 1);
@ -186,52 +173,52 @@ void EmptyIRQ(INTERRUPT_FRAME* frame) {
UNUSED(frame); UNUSED(frame);
// Flash the borders green, then back to blue // Flash the borders green, then back to blue
SetForegroundColor(0x0000FF00);
for(size_t y = 0; y < bootldr.fb_height; y++) { for(size_t y = 0; y < bootldr.fb_height; y++) {
for(size_t x = 0; x < 20; x++) { 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++) { 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 x = 0; x < bootldr.fb_width; x++) {
for(size_t y = 0; y < 20; y++) { 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++) { 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++) {} for(size_t i = 0; i < 100000; i++) {}
SetForegroundColor(0x000000FF);
for(size_t y = 0; y < bootldr.fb_height; y++) { for(size_t y = 0; y < bootldr.fb_height; y++) {
for(size_t x = 0; x < 20; x++) { 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++) { 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 x = 0; x < bootldr.fb_width; x++) {
for(size_t y = 0; y < 20; y++) { 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++) { 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) { static void KeyboardCallback(INTERRUPT_FRAME* frame) {
UNUSED(frame); UNUSED(frame);
uint8_t msg = ReadPort(0x60, 1); uint8_t msg = ReadPort(0x60, 1);