Added .gitignore
[comos.git] / kernel / keyboard.c
blob426062e8e39248eec7a5c7b9148d5749ec97f8b2
1 #include "keyboard.h"
2 #include "portio.h"
3 #include "console.h"
4 #include "interrupt.h"
5 #include "general.h"
6 #include "critical.h"
7 #include "shell.h"
9 kbListener kbList[255] = {0};
10 uint8_t listpos = 0;
11 static unsigned int kbd_state = KBD_NUMLOCK_STATE, kbd_led_state = 0;
13 unsigned char lowercase[128] =
15 0,0,'1','2','3','4','5','6','7','8','9','0','-','+','\b','\t','q','w','e','r','t','y','u','i','o','p','[',']','\n',
16 0,'a','s','d','f','g','h','j','k','l',';','\'','`',0,'\\','z','x','c','v','b','n','m',',','.','/',0,0,0,' ',0,
18 [59] = K_F1, [60] = K_F2, [61] = K_F3, [62] = K_F4, [63] = K_F5, [64] = K_F6, [65] = K_F7,
19 [66] = K_F8, [67] = K_F9, [68] = K_F10, [69] = K_F11, [70] = K_F12,
20 [72] = K_UP, [75] = K_LEFT, [77] = K_RIGHT, [80] = K_DOWN,
21 };
23 unsigned char uppercase[128] =
25 0,0,'!','@','#','$','%','^','&','*','(',')','_','+','\b','\t','Q','W','E','R','T','Y','U','I','O','P','[',']','\n',
26 0,'A','S','D','F','G','H','J','K','L',':','"','~',0,'|','Z','X','C','V','B','N','M','<','>','?',0,0,0,' ',0,
28 [59] = K_F1, [60] = K_F2, [61] = K_F3, [62] = K_F4, [63] = K_F5, [64] = K_F6, [65] = K_F7,
29 [66] = K_F8, [67] = K_F9, [68] = K_F10, [69] = K_F11, [70] = K_F12,
30 [72] = K_UP, [75] = K_LEFT, [77] = K_RIGHT, [80] = K_DOWN,
33 // Wait for the keyboard to be ready
34 void kbd_wait(void)
36 uint8_t status;
37 do {
38 status = inb(0x64);
39 } while (status & 0x2);
42 // Set keyboard LEDs
43 void kb_set_leds(int led_states)
45 trace("kb_set_leds\n");
46 kbd_wait();
47 // Tell the keyboard controller that we want to modify the LEDs
48 outb(0x60, 0xED);
49 kbd_wait();
50 outb(0x60, (led_states / KBD_CAPSLOCK_STATE) & 0x7);
51 kbd_wait();
52 kbd_led_state = led_states;
55 /* Handles the keyboard interrupt */
56 static void kb_int_handler(int vector, struct interrupt_stack *is)
58 uint8_t new_scan_code = inb(0x60);
59 uint8_t new_char;
60 uint8_t x;
61 bool handled;
63 switch(new_scan_code) {
64 case 29: /* CTRL */
65 kbd_state |= KBD_CTRL_STATE;
66 break;
67 case (29 + (1 << 7)):
68 kbd_state &= ~KBD_CTRL_STATE;
69 break;
71 case 56: /* ALT */
72 kbd_state |= KBD_ALT_STATE;
73 break;
74 case (56 + (1 << 7)):
75 kbd_state &= ~KBD_ALT_STATE;
76 break;
78 case 58: /* CAPS LOCK */
79 kbd_state ^= KBD_CAPSLOCK_STATE;
80 break;
82 case 69: /* NUM LOCK */
83 kbd_state ^= KBD_NUMLOCK_STATE;
84 break;
86 case 70: /* SCROLL LOCK */
87 kbd_state ^= KBD_SCROLLLOCK_STATE;
88 break;
90 case 42: /* SHIFT */
91 case 54:
92 kbd_state |= KBD_SHIFT_STATE;
93 break;
94 case (42 + (1 << 7)):
95 case (54 + (1 << 7)):
96 kbd_state &= ~KBD_SHIFT_STATE;
97 break;
99 default:
100 /* keep parsing if new_scan_code is not a break code */
101 if (!(new_scan_code & 0x80))
103 new_char = (kbd_state & KBD_SHIFT_STATE ? uppercase : lowercase)
104 [new_scan_code];
106 handled = false;
108 // virtual terminal switching
109 // this isn't really the place to do it...
110 if (kbd_state & KBD_ALT_STATE){
111 if (new_char >= '1' && new_char <= '4'){
112 struct vterm *vt;
113 vt = get_vterm(new_char - '1');
114 if (vt){
115 switch_vterm(vt);
116 handled = true;
121 if (!handled){
122 /* distribute new_char to our listeners */
123 for (x = 0; x < listpos; x++)
125 kbList[x](new_char);
129 break;
132 /* if our saved led state does not match our new state, change some lights =) */
133 if ((kbd_state & (KBD_CAPSLOCK_STATE | KBD_NUMLOCK_STATE | KBD_SCROLLLOCK_STATE))
134 != kbd_led_state){
135 kb_set_leds(kbd_state & (KBD_CAPSLOCK_STATE | KBD_NUMLOCK_STATE | KBD_SCROLLLOCK_STATE));
138 /* Acknowledge the IRQ, pretty much tells the PIC that we can accept >= priority IRQs now. */
139 ack_irq(1);
142 void keyboard_init(void)
144 interrupt_set_handler(irq_to_int(1), &kb_int_handler);
145 unmask_irq(1);
148 void keyboard_register_listener(kbListener nlist)
150 kbList[listpos++] = nlist;