Page 1 of 1

Keyboard functions

Posted: Sat Jan 27, 2007 7:21 pm
by piranha
Hello!

Does anyone know how to make a simple gets() function? I have tried, but I can't do it. :)

(i have a working getchar() function)

Posted: Sat Jan 27, 2007 8:39 pm
by senaus
Here's one I knocked up quickly:

Code: Select all

int gets(char *buf)
{
	int c = 0;
	do
	{
		buf[c] = getchar();
	}
	while(buf[c++] != '\n');
	buf[--c] = 0;
	return c;
};
Something like that should do the trick.

Cheers,
Sean

Posted: Sat Jan 27, 2007 9:20 pm
by piranha
oh man. I just realized that my getchar() function is weird. it worked before, but not now......

char getch
{
char ch;
while(int01flag == 0)
hlt();
ch = kbdus[ inportb(0x60) ];
int01_flag = 0;
return ch;
}

Posted: Sat Jan 27, 2007 9:50 pm
by Alboin
It looks okay at first glance..... What's so 'weird' about it? (aka. Can you give us a more detailed error message.)

Posted: Sat Jan 27, 2007 11:25 pm
by piranha
Well, I tested it by making it print on the screen what is typed, however it displays weird characters on the screen.

Posted: Sun Jan 28, 2007 1:15 am
by Brendan
Hi,
piranha wrote:Well, I tested it by making it print on the screen what is typed, however it displays weird characters on the screen.
The keyboard returns 'scan codes" which have nothing to do with the ASCII that you're expecting to see on the screen. You need to convert the scan codes (and sequences of scan codes in some cases) into something useful.

Of course "something useful" rarely implies ASCII alone. For a lot of keys there are no useful ASCII codes (function keys, shift, control, alt, capslock, insert, home, pageup, etc).

What you need is a proper keyboard driver that converts the current scancode and the current state (capslock state, numlock state, shift key state, etc) into a "keypress" and then stores this into a buffer. The keypress should include the ASCII (or Unicode) value (if any) and any other information (if was it pressed or release, and what the states things like shift, control and alt at the time).

Once you've done this, "getchar()" just needs to get "keypresses" from the buffer and ignore things that getchar() shouldn't return (e.g. key released, page up, function keys, etc). Of course you'd also want some sort of "getKeypress()" function that returns all information, so things like applications can tell when a function key is used, and so things like games know when a key is released.

Also, usually you'd have some sort of OS layer in-between the keyboard driver and the applications - either a GUI or a virtual terminal thing.


Cheers,

Brendan

Posted: Sun Jan 28, 2007 3:53 am
by Edward
piranha wrote:oh man. I just realized that my getchar() function is weird. it worked before, but not now......
char getch
{
char ch;
while(int01flag == 0)
hlt();
ch = kbdus[ inportb(0x60) ];
int01_flag = 0;
return ch;
}
does the array kbdus convert the scan code into an ascii character?

I also note that you don't take into account key release scan codes. A key release scan code tells you that the user has taken their finger off a key. they have the last bit set. you could try something like this:

Code: Select all

char getch
{
          //the ascii char we want to return
          char ch;

          //this holds the scan code
          char scan_code;

          //label that might be used later
          wait_press:

          while(int01flag == 0)
                     hlt();
         
          int01_flag = 0;
         
          //store the scan code
          scan_code=inportb(0x60);

          //if the top bit is not set then return the character
          if((scan_code&0x80)==0){         
                  ch = kbdus[ scan_code ];
                  return ch;
          }else{
                  //otherwise go back to waiting.
                  goto wait_press;
          }

}
The above might not compile or work. Its just a sugestion.

Edward Tait.

Posted: Sun Jan 28, 2007 7:34 am
by Otter
And that's not all. You have to notice keys like shift or alt, there are some advanced key codes following the scan code 0xE0 and so on ...

Sometimes the keyboard controller sends for example 5 scan codes for one key.

I wrote a very simple kernel that wait's for a new scancode and displays the hexcode of it. I played with it to understand the system.

Posted: Sun Jan 28, 2007 9:57 am
by Brendan
Hi,
Otter wrote:And that's not all. You have to notice keys like shift or alt, there are some advanced key codes following the scan code 0xE0 and so on ...

Sometimes the keyboard controller sends for example 5 scan codes for one key.
Yes, but that's not all...

There's different keyboards for different regions (French, German, Russian, Japanese, etc), and most modern OSs use Unicode instead of ASCII to support this.

For some languages/keyboards there's a huge number of characters (Japanese, Chinese, Korean, etc). For these there's usually some sort of visual tool between the keyboard driver and the application (an IME or Input Method Editor). For a (probably bad) English example, it's like pressing the 'H' key and getting a list of words that begin with 'H', and then either selecting the word 'Hello" from the list or pressing 'E' to get a refined list, until you have the correct character (realising that the English word "Hello" would be a single character, rather than a series of letters).

Then all modern OS's allow multiple applications to run at the same time, and let the user switch between them (e.g. alt+tab in a GUI, or alt+Fn for Unix style virtual terminals).

There's also "magic" keypresses (that are never sent to any application). This usually includes the "control+alt+delete" combination, but can include others (alt+tab, control+alt+backspace, alt combined with numbers on the numerics keypad, etc).

Further, for most systems "getchar()" can be redirected, so that it gets it's data from a file, from a serial port, from another program, etc - it's the same as "getc(stdin)" (where "stdin" isn't always the keyboard).

Lastly, polling always sucks because it's a waste of CPU time - for e.g. if one task is waiting for a key to be pressed, why not run other tasks until a key is pressed? In this specific case it's much worse - if "getchar()" isn't called in a tight loop you'll get lost keypresses, you won't be able to tell if the data from port 0x60 is from the keyboard or the mouse, and you won't be able to write a mouse driver at all.


Cheers,

Brendan

Posted: Sun Jan 28, 2007 10:30 am
by piranha
Thanks you guys for all of that great info :D

It works great now!!


THX!

--Joe