We do a project at school which lasts for 1 year. I and a colleague had the idea that we should try to write a simple operating system. We're not that experienced in Asm and C, so we figured we'd learn best by setting ourselves a task and trying to solve it.
unfortunately we already failed with the keyboard input...
The operating system starts as intended and also writes the intended sentence "Hello world" on the screen. But as soon as you press keys on the keyboard, only funny symbols appear on the screen.
We would be grateful if you could explain what we are doing wrong and also fix the error
the source code is on github: https://github.com/Fabbboy/alpsos/tree/master/src/impl/kernel/drivers
Thanks for your help
EDIT - added the code from github to stackoverflow
Keyboard.h
#ifndef ALPSOS_KEYBOARD_H
#define ALPSOS_KEYBOARD_H
#include <stdint.h>
uint8_t inb(uint16_t port);
//read from port 0x60
uint8_t keyboard_read_input();
//identify the key pressed
char keyboard_handle_input();
#endif //ALPSOS_KEYBOARD_H
And the Keyboard.c
#include <stdint.h>
uint8_t inb(uint16_t port){
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
};
//read from port 0x60
uint8_t keyboard_read_input(){
//if something is on port 0x60
while(!(inb(0x64) & 1));
return inb(0x60);
};
//identify the key pressed
char keyboard_handle_input(){
uint8_t input = keyboard_read_input();
if(input == 0x1C){
return 'A';
}
if(input == 0x1D){
return 'B';
}
if(input == 0x1E){
return 'C';
}
if(input == 0x1F){
return 'D';
}
if(input == 0x20){
return 'E';
}
if(input == 0x21){
return 'F';
}
if(input == 0x22){
return 'G';
}
if(input == 0x23){
return 'H';
}
if(input == 0x24){
return 'I';
}
if(input == 0x25){
return 'J';
}
if(input == 0x26){
return 'K';
}
if(input == 0x27){
return 'L';
}
if(input == 0x28){
return 'M';
}
if(input == 0x29){
return 'N';
}
if(input == 0x2A){
return 'O';
}
if(input == 0x2B){
return 'P';
}
if(input == 0x2C){
return 'Q';
}
if(input == 0x2D){
return 'R';
}
if(input == 0x2E){
return 'S';
}
if(input == 0x2F){
return 'T';
}
if(input == 0x30){
return 'U';
}
if(input == 0x31){
return 'V';
}
if(input == 0x32){
return 'W';
}
if(input == 0x33){
return 'X';
}
if(input == 0x34){
return 'Y';
}
if(input == 0x35){
return 'Z';
}
};
CodePudding user response:
It's highly probable that your keyboard mapping is wrong. A simple solution to that would be to make a test version where the raw number received is displayed in hex, allowing you to create your how key map.
if
chains should be avoided as much as possible, as they require significantly more time and code space. Using a switch
would be better, but a lookup table would be best. You can implement it either as a string :
char *keymap = "0123456789ABCDEF";
or as an array (much more readable in my opinion) :
char keymap[NUMBER_KEYS] =
{
[0x00] = '\0',
[0x01] = '\1',
/* ... */
[0x1C] = 'A',
[0x1D] = 'B',
[0x1E] = 'C',
[0x1F] = 'D',
[0x20] = 'E',
/* ... */
};
Designated initialisers make the association between the key code and it's character more readable, but they're not mandatory.
CodePudding user response:
Where did you get the idea that the keyboard will return that nice contiguous range from 0x1C to 0x35 corresponding to 'A' through 'Z'?
Next are the keyboard scancodes for the alphabet:
a 0x1E
b 0x30
c 0x2E
d 0x20
e 0x12
f 0x21
g 0x22
h 0x23
i 0x17
j 0x24
k 0x25
l 0x26
m 0x27
n 0x31
o 0x18
p 0x19
q 0x10
r 0x13
s 0x1F
t 0x14
u 0x16
v 0x2F
w 0x11
x 0x2d
y 0x15
z 0x2C
These codes alone don't tell you anything about the case of the character! That's a refinement that your program must provide by looking at presses on caps-lock and/or shift.
What you read from port 0x60 can have its highest bit set if it is a release code that the keyboard sent. Mostly you'd want to ignore those.
Writing a decent keyboard handler is not trivial! It's way more complicated than just reading from port 0x60. I'm sure you can find good examples on the internet.