WKern
Loading...
Searching...
No Matches
keyin.c
Go to the documentation of this file.
1/*
2WKern - A Bare Metal OS / Kernel I am maKing (For Fun)
3Copyright (C) 2025 Wdboyes13
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18
26
27#include <global.h>
28#include <io/kio.h>
29
33unsigned char scancode_to_ascii(unsigned char scancode) {
34 static const unsigned char Keymap[256] = {
35 0, 27, '1', '2', '3', '4', '5', '6', // 0x00 - 0x07
36 '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't',
37 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', // 0x10 - 0x17
38 'd', 'f', 'g', 'h', 'j', 'K', 'l', ';', '\'', '`', 0, '\\', 'z',
39 'x', 'c', 'v', // 0x18 - 0x1F
40 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0,
41 0, 0, 0, // 0x20 - 0x27
42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 };
58
59 return Keymap[scancode];
60}
61
63volatile char Keybuf[256];
65volatile int buf_head = 0;
67volatile int buf_tail = 0;
68
73unsigned char Keytoshift(unsigned char ascii) {
74 if (ascii >= 'a' && ascii <= 'z') {
75 return ascii - 32; // 'a' to 'A'
76 }
77
78 switch (ascii) {
79 case '1':
80 return '!';
81 case '2':
82 return '@';
83 case '3':
84 return '#';
85 case '4':
86 return '$';
87 case '5':
88 return '%';
89 case '6':
90 return '^';
91 case '7':
92 return '&';
93 case '8':
94 return '*';
95 case '9':
96 return '(';
97 case '0':
98 return ')';
99 case '-':
100 return '_';
101 case '=':
102 return '+';
103 case '[':
104 return '{';
105 case ']':
106 return '}';
107 case '\\':
108 return '|';
109 case ';':
110 return ':';
111 case '\'':
112 return '"';
113 case ',':
114 return '<';
115 case '.':
116 return '>';
117 case '/':
118 return '?';
119 case '`':
120 return '~';
121 default:
122 return ascii; // default if no shift mapping exists
123 }
124}
125
130void Irq1HandlerC(void) {
131 unsigned char sc = Inb(0x60);
132
133 if (!(sc & 0x80)) { // Key press (not release)
134 if (sc == 0x3A) {
135 capson = !capson;
136 return;
137 }
138
139 if (sc == 0x2A || sc == 0x36) {
140 shift = 1;
141 return;
142 }
143
144 unsigned char ascii = scancode_to_ascii(sc);
145
146 if (shift) {
147 ascii = Keytoshift(ascii);
148 }
149 if (capson && ascii >= 'a' && ascii <= 'z') {
150 ascii -= 32;
151 }
152 if (ascii == 0 || ascii > 127) {
153 return;
154 }
155 Keybuf[buf_head++] = ascii;
156 if (buf_head == 256) {
157 buf_head = 0;
158 }
159 } else {
160 // Key release
161 if (sc == 0xAA || sc == 0xB6) {
162 shift = 0;
163 }
164 }
165}
166
169char Kgetkey() {
170 while (buf_tail == buf_head) {
171 ; // wait for Key
172 }
173 char ch = Keybuf[buf_tail++];
174 if (buf_tail == 256) {
175 buf_tail = 0;
176 }
177 return ch;
178}
179
186void Kgetstr(char *str, int length) {
187 int i = 0;
188
189 while (i < length - 1) {
190 unsigned char Key = 0;
191 while (!(Key = Kgetkey())) {
192 ;
193 }
194
195 if (Key == '\n') {
196 str[i] = '\0';
197 Kputchar('\n');
198 return;
199 }
200
201 if (Key == '\b' || Key == 0x7F) { // 0x7F is DEL on some layouts
202 if (i > 0) {
203 i--;
204 str[i] = '\0';
206 }
207 continue;
208 }
209 str[i++] = Key;
210 Kputchar(Key);
211 }
212
213 str[length - 1] = '\0';
214}
215
219void Kflush() {
220 while (Inb(0x64) & 0x01) {
221 Inb(0x60);
222 }
223}
u8 Inb(u16 port)
Read a byte from the specified I/O port.
Definition asm.c:40
bool capson
Definition main.c:34
bool shift
Definition main.c:35
char Kgetkey()
Gets the next character from the keyboard buffer (blocking).
Definition keyin.c:169
unsigned char scancode_to_ascii(unsigned char scancode)
Converts a keyboard scancode to an ASCII character.
Definition keyin.c:33
void Kgetstr(char *str, int length)
Reads a line of input from the keyboard (blocking).
Definition keyin.c:186
unsigned char Keytoshift(unsigned char ascii)
Converts an ASCII character to its shifted equivalent.
Definition keyin.c:73
volatile char Keybuf[256]
Circular buffer storing incoming keystrokes.
Definition keyin.c:63
volatile int buf_head
Head index for Keybuf.
Definition keyin.c:65
void Kflush()
Flushes the keyboard controller input buffer.
Definition keyin.c:219
volatile int buf_tail
Tail index for Keybuf.
Definition keyin.c:67
void Irq1HandlerC(void)
IRQ handler for PS/2 keyboard (IRQ1).
Definition keyin.c:130
void KputcharBackspace()
Handles backspace keypress by moving the cursor back and clearing the character.
Definition printer.c:71
void Kputchar(char c)
Outputs a single character to the screen at the current cursor position.
Definition printer.c:46