kbd #6
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
|||||||
build:
|
build:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
x86_64-elf-gcc -g -c -I src src/time/timer.c src/idt/idt.c src/mem/utils.c src/mem/gdt.c src/io/serial.c src/io/term.c src/io/printf.c src/kmain.c -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
|
x86_64-elf-gcc -g -c -I src src/kbd/ps2.c src/time/timer.c src/idt/idt.c src/mem/utils.c src/mem/gdt.c src/io/serial.c src/io/term.c src/io/printf.c src/kmain.c -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
|
||||||
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
|
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
|
||||||
nasm -f elf64 src/idt/idt.S -o idt_stub.o
|
nasm -f elf64 src/idt/idt.S -o idt_stub.o
|
||||||
x86_64-elf-ld -o pepperk -T linker.ld *.o
|
x86_64-elf-ld -o pepperk -T linker.ld *.o
|
||||||
|
|||||||
@@ -301,3 +301,10 @@ vector_32_handler:
|
|||||||
push qword 0
|
push qword 0
|
||||||
push qword 32
|
push qword 32
|
||||||
jmp interrupt_stub
|
jmp interrupt_stub
|
||||||
|
|
||||||
|
; PS/2 Keyboard
|
||||||
|
align 16
|
||||||
|
vector_33_handler:
|
||||||
|
push qword 0
|
||||||
|
push qword 33
|
||||||
|
jmp interrupt_stub
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "../io/serial.h"
|
#include "../io/serial.h"
|
||||||
|
#include "../kbd/ps2.h"
|
||||||
|
|
||||||
struct interrupt_descriptor idt[256];
|
struct interrupt_descriptor idt[256];
|
||||||
struct idtr idt_reg;
|
struct idtr idt_reg;
|
||||||
@@ -123,12 +124,16 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
serial_kputs("Tick!");
|
//serial_kputs("Tick!");
|
||||||
ticks++;
|
ticks++;
|
||||||
// Send an EOI so that we can continue having interrupts
|
// Send an EOI so that we can continue having interrupts
|
||||||
outb(0x20, 0x20);
|
outb(0x20, 0x20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 33:
|
||||||
|
keyboard_handler();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
serial_kputs("kernel: idt: Unexpected interrupt\n");
|
serial_kputs("kernel: idt: Unexpected interrupt\n");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -66,7 +66,19 @@ static void draw_char(char c, int px, int py, int fg, int bg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putchar(char c)
|
static void erase_char(int px, int py)
|
||||||
|
{
|
||||||
|
for (size_t y=0; y<FONT_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (size_t x=0; x<8; x++)
|
||||||
|
{
|
||||||
|
// Black
|
||||||
|
putpixel(px+x, py+y, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void putchar(char c)
|
||||||
{
|
{
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
@@ -75,6 +87,32 @@ static void putchar(char c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Improperly handled.
|
||||||
|
// When we're on an empty line it should get to the upper line's last character
|
||||||
|
// NOT just the last position possible; we would need to track the last line's character amount for that
|
||||||
|
if (c == '\b')
|
||||||
|
{
|
||||||
|
if (cursor.x == 0 && cursor.y == 0)
|
||||||
|
{
|
||||||
|
// Top-left corner
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.x == 0)
|
||||||
|
{
|
||||||
|
cursor.y--;
|
||||||
|
cursor.x = (framebuffer->width / FONT_WIDTH) -1; // here
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cursor.x--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int px = cursor.x * FONT_WIDTH;
|
||||||
|
int py = cursor.y * FONT_HEIGHT;
|
||||||
|
erase_char(px, py);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((cursor.x+1)*FONT_WIDTH >= framebuffer->width)
|
if ((cursor.x+1)*FONT_WIDTH >= framebuffer->width)
|
||||||
{
|
{
|
||||||
cursor.x = 0;
|
cursor.x = 0;
|
||||||
@@ -87,7 +125,7 @@ static void putchar(char c)
|
|||||||
cursor.x++;
|
cursor.x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overhead that could be avoided, right?
|
// Overhead that could be avoided, right? (for printf)
|
||||||
void _putchar(char character)
|
void _putchar(char character)
|
||||||
{
|
{
|
||||||
putchar(character);
|
putchar(character);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
int term_init();
|
int term_init();
|
||||||
void kputs(const char* str);
|
void kputs(const char* str);
|
||||||
|
void putchar(char c);
|
||||||
|
|
||||||
enum TermColors
|
enum TermColors
|
||||||
{
|
{
|
||||||
|
|||||||
236
src/kbd/ps2.c
Normal file
236
src/kbd/ps2.c
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
// PS/2 Keyboard support
|
||||||
|
|
||||||
|
#include "../io/serial.h"
|
||||||
|
#include "../io/printf.h"
|
||||||
|
#include "ps2.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../io/term.h"
|
||||||
|
|
||||||
|
// The key status bitfield will be used to see if ALT, CONTROL, or SHIFT is pressed
|
||||||
|
uint8_t key_status = 0b00000000;
|
||||||
|
|
||||||
|
// Keymap pointers so we can change between different layouts
|
||||||
|
unsigned char* keymap;
|
||||||
|
unsigned char* keymap_shifted;
|
||||||
|
|
||||||
|
unsigned char kbdus[128] =
|
||||||
|
{
|
||||||
|
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
||||||
|
'9', '0', '-', '=', '\b', /* Backspace */
|
||||||
|
'\t', /* Tab */
|
||||||
|
'q', 'w', 'e', 'r', /* 19 */
|
||||||
|
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
|
||||||
|
CTRL, /* 29 - Control */
|
||||||
|
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
|
||||||
|
'\'', '`', SHIFT, /* Left shift */
|
||||||
|
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
||||||
|
'm', ',', '.', '/', SHIFT, /* Right shift */
|
||||||
|
'*',
|
||||||
|
ALT, /* Alt */
|
||||||
|
' ', /* Space bar */
|
||||||
|
0, /* Caps lock */
|
||||||
|
0, /* 59 - F1 key ... > */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, /* < ... F10 */
|
||||||
|
0, /* 69 - Num lock*/
|
||||||
|
0, /* Scroll Lock */
|
||||||
|
0, /* Home key */
|
||||||
|
0, /* Up Arrow */
|
||||||
|
0, /* Page Up */
|
||||||
|
'-',
|
||||||
|
0, /* Left Arrow */
|
||||||
|
0,
|
||||||
|
0, /* Right Arrow */
|
||||||
|
'+',
|
||||||
|
0, /* 79 - End key*/
|
||||||
|
0, /* Down Arrow */
|
||||||
|
0, /* Page Down */
|
||||||
|
0, /* Insert Key */
|
||||||
|
0, /* Delete Key */
|
||||||
|
0, 0, 0,
|
||||||
|
0, /* F11 Key */
|
||||||
|
0, /* F12 Key */
|
||||||
|
0, /* All other keys are undefined */
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char kbdus_shifted[128] =
|
||||||
|
{
|
||||||
|
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */
|
||||||
|
'(', ')', '_', '+', '\b', /* Backspace */
|
||||||
|
'\t', /* Tab */
|
||||||
|
'Q', 'W', 'E', 'R', /* 19 */
|
||||||
|
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter */
|
||||||
|
CTRL, /* 29 */
|
||||||
|
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */
|
||||||
|
'"', '~', SHIFT, /* Left shift */
|
||||||
|
'|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */
|
||||||
|
'M', '<', '>', '?', SHIFT, /* Right shift */
|
||||||
|
'*',
|
||||||
|
ALT, /* Alt */
|
||||||
|
' ', /* Space */
|
||||||
|
0, /* Caps lock */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, /* F10 */
|
||||||
|
0, /* Num lock */
|
||||||
|
0, /* Scroll lock */
|
||||||
|
0, 0, 0,
|
||||||
|
'-',
|
||||||
|
0, 0, 0,
|
||||||
|
'+',
|
||||||
|
0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
0, /* F11 */
|
||||||
|
0 /* F12 */
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOT THE REAL FR KEYMAP!!
|
||||||
|
// Some French keys have accents or weird symbols that aren't part of ASCII
|
||||||
|
// so they won't fit in 1 char. As a substitute for now, these will be
|
||||||
|
// changed to their ASCII counterparts (without accents, etc.)
|
||||||
|
unsigned char kbdfr[128] =
|
||||||
|
{
|
||||||
|
0, 27, '&', 'e', '"', '\'', '(', '-', 'e', '_',
|
||||||
|
'c', 'a', ')', '=', '\b',
|
||||||
|
'\t',
|
||||||
|
'a', 'z', 'e', 'r',
|
||||||
|
't', 'y', 'u', 'i', 'o', 'p', '^', '$', '\n',
|
||||||
|
CTRL,
|
||||||
|
'q', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
|
||||||
|
'u', '`', SHIFT,
|
||||||
|
'*', 'w', 'x', 'c', 'v', 'b', 'n',
|
||||||
|
',', ';', ':', '!', SHIFT,
|
||||||
|
'*',
|
||||||
|
ALT,
|
||||||
|
' ',
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char kbdfr_shifted[128] =
|
||||||
|
{
|
||||||
|
0, 27, '1', '2', '3', '4', '5', '6', '7', '8',
|
||||||
|
'9', '0', '^', '+', '\b',
|
||||||
|
'\t',
|
||||||
|
'A', 'Z', 'E', 'R',
|
||||||
|
'T', 'Y', 'U', 'I', 'O', 'P', '^', 'L', '\n',
|
||||||
|
CTRL,
|
||||||
|
'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
|
||||||
|
'%', '~', SHIFT,
|
||||||
|
'u', 'W', 'X', 'C', 'V', 'B', 'N',
|
||||||
|
'?', '.', '/', 'S', SHIFT,
|
||||||
|
'*',
|
||||||
|
ALT,
|
||||||
|
' ',
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
void keyboard_handler()
|
||||||
|
{
|
||||||
|
unsigned char scancode = inb(0x60);
|
||||||
|
|
||||||
|
// Key release (bit 7 set)
|
||||||
|
if (scancode & 0x80)
|
||||||
|
{
|
||||||
|
unsigned char code = scancode & 0x7F;
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
// Clear the corresponding bit if corresponding key is released
|
||||||
|
case LEFT_SHIFT_PRESSED:
|
||||||
|
case RIGHT_SHIFT_PRESSED:
|
||||||
|
key_status &= ~SHIFT_PRESSED_BIT;
|
||||||
|
break;
|
||||||
|
case CTRL_PRESSED:
|
||||||
|
key_status &= ~CTRL_PRESSED_BIT;
|
||||||
|
break;
|
||||||
|
case ALT_PRESSED:
|
||||||
|
key_status &= ~ALT_PRESSED_BIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send EOI
|
||||||
|
outb(0x20, 0x20);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Key press
|
||||||
|
switch (scancode)
|
||||||
|
{
|
||||||
|
// Set bits for corresponding special key press
|
||||||
|
case LEFT_SHIFT_PRESSED:
|
||||||
|
case RIGHT_SHIFT_PRESSED:
|
||||||
|
key_status |= SHIFT_PRESSED_BIT;
|
||||||
|
break;
|
||||||
|
case CTRL_PRESSED:
|
||||||
|
key_status |= CTRL_PRESSED_BIT;
|
||||||
|
break;
|
||||||
|
case ALT_PRESSED:
|
||||||
|
key_status |= ALT_PRESSED_BIT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Should we get a SHIFTED char or a regular one?
|
||||||
|
unsigned char c = (key_status & SHIFT_PRESSED_BIT) ? keymap_shifted[scancode] : keymap[scancode];
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
putchar(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_kputs("key pressed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Interrupt (to master PIC)
|
||||||
|
outb(0x20, 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_init(unsigned char layout)
|
||||||
|
{
|
||||||
|
// Here we might go and select PS/2, USB, or other... (once we implement multiple keyboard protocols)
|
||||||
|
|
||||||
|
// Keyboard layout selection
|
||||||
|
switch (layout)
|
||||||
|
{
|
||||||
|
case US:
|
||||||
|
keymap = kbdus;
|
||||||
|
keymap_shifted = kbdus_shifted;
|
||||||
|
break;
|
||||||
|
case FR:
|
||||||
|
keymap = kbdfr;
|
||||||
|
keymap_shifted = kbdfr_shifted;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
serial_kputs("Unsupported layout.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/kbd/ps2.h
Normal file
37
src/kbd/ps2.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef PS2_H
|
||||||
|
#define PS2_H
|
||||||
|
|
||||||
|
void keyboard_handler();
|
||||||
|
|
||||||
|
#define SHIFT_PRESSED_BIT 0b00000001
|
||||||
|
#define ALT_PRESSED_BIT 0b00000010
|
||||||
|
#define CTRL_PRESSED_BIT 0b00000100
|
||||||
|
|
||||||
|
enum SpecialKeys
|
||||||
|
{
|
||||||
|
SHIFT = 255,
|
||||||
|
ALT = 254,
|
||||||
|
CTRL = 253
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SpecialScancodes
|
||||||
|
{
|
||||||
|
LEFT_SHIFT_PRESSED = 0x2A,
|
||||||
|
LEFT_SHIFT_RELEASED = 0xAA,
|
||||||
|
RIGHT_SHIFT_PRESSED = 0x36,
|
||||||
|
RIGHT_SHIFT_RELEASED = 0xB6,
|
||||||
|
CTRL_PRESSED = 0x1D,
|
||||||
|
CTRL_RELEASED = 0x9D,
|
||||||
|
ALT_PRESSED = 0x38,
|
||||||
|
ALT_RELEASED = 0xB8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KeyboardLayout
|
||||||
|
{
|
||||||
|
US,
|
||||||
|
FR
|
||||||
|
};
|
||||||
|
|
||||||
|
void keyboard_init(unsigned char layout);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "idt/idt.h"
|
#include "idt/idt.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "time/timer.h"
|
#include "time/timer.h"
|
||||||
|
#include "kbd/ps2.h"
|
||||||
|
|
||||||
// Limine version used
|
// Limine version used
|
||||||
__attribute__((used, section(".limine_requests")))
|
__attribute__((used, section(".limine_requests")))
|
||||||
@@ -57,6 +58,8 @@ void kmain()
|
|||||||
timer_init();
|
timer_init();
|
||||||
SET_INTERRUPTS;
|
SET_INTERRUPTS;
|
||||||
|
|
||||||
|
keyboard_init(FR);
|
||||||
|
|
||||||
// Draw something
|
// Draw something
|
||||||
printf("%s, %s!", "Hello", "world");
|
printf("%s, %s!", "Hello", "world");
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ void pic_enable()
|
|||||||
{
|
{
|
||||||
// Enabling IRQ0 (unmasking it) but not the others
|
// Enabling IRQ0 (unmasking it) but not the others
|
||||||
uint8_t mask = inb(0x21);
|
uint8_t mask = inb(0x21);
|
||||||
mask &= ~(1 << 0); // Clear bit 0 (IRQ0)
|
mask &= ~(1 << 0); // Set IRQ0 (timer, clear bit 0)
|
||||||
|
mask &= ~(1 << 1); // Set IRQ1 (PS/2 Keyboard, clear bit 1)
|
||||||
outb(0x21, mask);
|
outb(0x21, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user