1

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';
    }

};
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Pixel Coin
  • 51
  • 6
  • 1
    First check that your print functions works with the chracater values you expect from the keyboard routine. Then fetch a key code and print its hex value. You don't need a full-fledged string converter, just `static const char hex[] = "0123456789ABCDEF";` and index into this with the nibbles of the code. – the busybee Jun 21 '22 at 16:40
  • 2
    What architecture are you programming for? Please note that Stack Overflow questions must be self-contained, so please post your keyboard driver code into the question for us to inspect. Methinks you most likely forgot to translate scan codes into ASCII characters. – fuz Jun 21 '22 at 16:43
  • The link redirects you to the code but i can post it anyways – Pixel Coin Jun 21 '22 at 16:45
  • 1
    About your linked function `keyboard_handle_input()`. a) Make it type `int` (in C there are no functions that take or return the `char` type). b) not all control paths return a value (return a default value). c) don't use a long line of `if`s (use a lookup table or compute if everything is consecutive). d) in an OS, make the function non-blocking. – Weather Vane Jun 21 '22 at 16:49
  • 2
    @PixelCoin Please post it anyway as Stack Overflow questions must be self contained. What if your link goes down? That would make your question useless and the effort placed into answering it wasted. As a general principle, I do not even look at external links when answering a question. – fuz Jun 21 '22 at 18:50

2 Answers2

3

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.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
1

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.

Elzaidir
  • 891
  • 6
  • 13