aboutsummaryrefslogtreecommitdiff
path: root/kernel/io/keyboard/keyboard_handler.c
blob: 86a50a7cfeb7e42276159da89aec0c5030528d39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "../../interrupt_descriptor_table.h"
#include "../vga/text_mode_display.h"
#include "scancode_map.h"

extern void keyboard_handler(void);
extern char read_port(unsigned short port);
extern void write_port(unsigned short port, unsigned char data);
extern void load_idt(unsigned long *idt_ptr);

struct idt_entry keyboard_idt[256];

void init_keyboard_idt()
{
  unsigned long keyboard_address;
  unsigned long idt_address;
  unsigned long idt_ptr[2];

  // Build IDT entry
  keyboard_address = (unsigned long) keyboard_handler;

  keyboard_idt[0x21].offset_lowerbits = keyboard_address & 0xffff;
  keyboard_idt[0x21].selector = 0x08; // Offset by 0x08
  keyboard_idt[0x21].zero = 0;
  keyboard_idt[0x21].type_attr = 0x8E; // Interrupt gate addr
  keyboard_idt[0x21].offset_higherbits = (keyboard_address & 0xffff0000) >> 16;

  idt_address = (unsigned long) keyboard_idt;
  idt_ptr[0] = (sizeof(struct idt_entry) * 256) + ((idt_address & 0xffff) << 16);
  idt_ptr[1] = idt_address >> 16;

  // Init PIC 1 @ 0x20
  write_port(0x20, 0x11);
  write_port(0x21, 0x20);
  write_port(0x21, 0x00);
  write_port(0x21, 0x01);
  write_port(0x21, 0xff);

  // PIC 2 @ 0xA0
  write_port(0xA0, 0x11);
  write_port(0xA1, 0x28);
  write_port(0xA1, 0x00);
  write_port(0xA1, 0x01);
  write_port(0xA1, 0xff);

  load_idt(idt_ptr);
}

void init_keyboard_handler()
{
  init_keyboard_idt();

  write_port(0x21, 0xFD);
}

int isKeyup(int scancode)
{
  return scancode & 0x80;
}

void handle_keypress() {

  // Ack the interrupt
  write_port(0x20, 0x20);

  unsigned char scancode = read_port(0x60);

  if(!isKeyup(scancode))
  {
    char pressed_key = scancode_map[scancode];
    vga_print_raw(pressed_key);
  }

}