read keyboard?
- Lionel
- Member
- Posts: 117
- Joined: Fri Jul 16, 2010 2:16 pm
- Libera.chat IRC: ryanel
- Location: California
read keyboard?
Hello,
I been trying to find a way for getting input from the keyboard. I don't mean getting the input and scan codes from the keyboard, but getting the input from after, say... readline(); is called and taking the output from readline() to the appropriate piece of code. I was a .net developer before a os developer, so I have always been sheltered by Console.Readline();. I tthought of a way to do it, but it would put readline in a infinite loop because reading could never be updated because it's waiting for it to change. I honestly can't find a solution, so could you help me osdev community?
~Lionel
I been trying to find a way for getting input from the keyboard. I don't mean getting the input and scan codes from the keyboard, but getting the input from after, say... readline(); is called and taking the output from readline() to the appropriate piece of code. I was a .net developer before a os developer, so I have always been sheltered by Console.Readline();. I tthought of a way to do it, but it would put readline in a infinite loop because reading could never be updated because it's waiting for it to change. I honestly can't find a solution, so could you help me osdev community?
~Lionel
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: read keyboard?
In other words, you are saying you can't use the getkey() and putc() functions you seem to already have to emulate a command prompt?
- Lionel
- Member
- Posts: 117
- Joined: Fri Jul 16, 2010 2:16 pm
- Libera.chat IRC: ryanel
- Location: California
Re: read keyboard?
No, I can get keyboard input by redirecting the input from my keyboard handler, but I can't find a clean way to get the input in handled.
Re: read keyboard?
The Usual Diagnostic Message: Not Enough User Space Experience.
Try yourself at some userspace C. Don't jump into the deep waters of OS development before you learned to swim (without .NET water wings).
For one, documentation and help is much easier to come by for userspace.
Try yourself at some userspace C. Don't jump into the deep waters of OS development before you learned to swim (without .NET water wings).
For one, documentation and help is much easier to come by for userspace.
Every good solution is obvious once you've found it.
- Lionel
- Member
- Posts: 117
- Joined: Fri Jul 16, 2010 2:16 pm
- Libera.chat IRC: ryanel
- Location: California
Re: read keyboard?
I got it somewhat working:
readch();
reads();
But I stumbled into another problem:
It seems that prints part of memory, but I can't find the bug in the code. Could someone help me with this problem please?
readch();
Code: Select all
unsigned char readch()
{
readingch=1;
while (readingch==1)// readingch is set to 0 in keyboard handler
{
}
if (readchar=="\n"){return 0;}
if (readchar=="\b"){return 0;}
return readchar;
}
Code: Select all
unsigned char *reads()
{
unsigned char *buffer="";
unsigned char charbuffer="";
readings=1;
while (readings==1 & readchar !="\n")
{
buffer=+readch();
puts(buffer);
}
return buffer;
}
It seems that prints part of memory, but I can't find the bug in the code. Could someone help me with this problem please?
Re: read keyboard?
Hints:
1) buffer=+readch(); // buffer = +{0 ~ 255}
2) You are comparing char * string using == operator, which compares their address instead of content.
3) You use bitwise and where you actually would like logical and
ps. There are more errors not mentioned, which contributed to roughly 80% of the lines of your code...
1) buffer=+readch(); // buffer = +{0 ~ 255}
2) You are comparing char * string using == operator, which compares their address instead of content.
3) You use bitwise and where you actually would like logical and
ps. There are more errors not mentioned, which contributed to roughly 80% of the lines of your code...
- Lionel
- Member
- Posts: 117
- Joined: Fri Jul 16, 2010 2:16 pm
- Libera.chat IRC: ryanel
- Location: California
Re: read keyboard?
Hmm. I got it working finally!
Thanks to bluemoon's first hint. I got it. Thanks bluemoon!
p.s:I was going to get it to work, then fix errors and improve it's performance.
Thanks to bluemoon's first hint. I got it. Thanks bluemoon!
Code: Select all
unsigned char *reads()
{
unsigned char *buffer="";
int buffer_charnum=0;
unsigned char input="";
readings=1;
while (readings==1)
{
input=readch();
if (input==0xD)
{
break;
}
buffer[buffer_charnum]=input;
buffer_charnum+=1;
}
return buffer;
}
Re: read keyboard?
Hi,
For C, string literals are created in the ".data" or ".rodata" section and only enough space for the string (e.g. 1 byte in your case) is reserved for it. This means as soon as you put anything in the buffer you trash other data (unless your OS happens to honour the read only attribute of the ".rodata" section and you get a page fault instead, which would be much better in this case as it'd prevent other data being trashed).
On top of this, you're missing a fundamental understanding of how it should work.
For a single-tasking system; the keyboard IRQ handler should place data into a queue; and your "readch()" function should do something like "while( queue_is_empty() ) { __asm__(HLT); }".
For a multi-tasking system; you need to have some sort of IPC (Inter-Process Communication). It doesn't matter if it's some type of messaging or pipes or whatever else. The IRQ handler sends keypresses to wherever (typically a virtual terminal layer and/or GUI) using the IPC, and wherever forwards the keypresses (using IPC again) to the application that is currently "active". In this case the IPC itself handles the buffering/queuing; and the IPC interacts with the scheduler such that any tasks waiting for IPC don't waste any CPU time.
In either of these cases, ASCII alone is not suitable. For example, there is no ASCII code for "F2", "page up", "alt + C" or lots of other keys that normal applications will need. For some types of software (e.g. games) the application will need to know when a key is released, and not just when a key is pressed (but this isn't just limited to games - e.g. consider an application with a scroll bar, where it scrolls while the cursor key is held down and stops scrolling when the key is released). Also (mostly for games), sometimes software needs to know which key and doesn't care what character it corresponds to (for example, "if( key_code == user_settings[key_being_used_to_fire_primary_weapon]) fire_weapon1();". Then there's internationalisation - different keyboard maps, Unicode and support for "input method editors". You probably don't want these things yet, but you won't want to rewrite everything as soon as you start wanting these things later.
Basically if you put all that together, the keyboard driver should be creating and sending "keypress packets" and not ASCII characters. Something like:
If you don't want any internationalisation yet, then the "Unicode_codepoint" field can be used to store ASCII (as the first 128 Unicode codepoints correspond to ASCII codes anyway).
For legacy "console" applications, somewhere (e.g. in a user-space library) you'd have a "readch()" function that gets a keypress packet and ignores most of the extra information and only returns the "Unicode_codepoint" field (if it's non-zero; or for severely borked software only if it's non-zero and less than 128). For applications that aren't crusty old crud you'd also have a "get_keypress()" function (e.g. also in a user-space library) that returns the full information.
Cheers,
Brendan
That is unbelievably wrong.Lionel wrote:Code: Select all
unsigned char *reads() { unsigned char *buffer=""; int buffer_charnum=0; unsigned char input=""; readings=1; while (readings==1) { input=readch(); if (input==0xD) { break; } buffer[buffer_charnum]=input; buffer_charnum+=1; } return buffer; }
For C, string literals are created in the ".data" or ".rodata" section and only enough space for the string (e.g. 1 byte in your case) is reserved for it. This means as soon as you put anything in the buffer you trash other data (unless your OS happens to honour the read only attribute of the ".rodata" section and you get a page fault instead, which would be much better in this case as it'd prevent other data being trashed).
This is badly wrong too. The "readingch" variable should be volatile (expect it to fail as soon as you compile with optimisations enabled); and nothing prevents the "readchar" variable from being changed (by the keyboard IRQ handler) multiple times before it's read (expect to lose keypresses).Lionel wrote:Code: Select all
unsigned char readch() { readingch=1; while (readingch==1)// readingch is set to 0 in keyboard handler { } if (readchar=="\n"){return 0;} if (readchar=="\b"){return 0;} return readchar; }
On top of this, you're missing a fundamental understanding of how it should work.
For a single-tasking system; the keyboard IRQ handler should place data into a queue; and your "readch()" function should do something like "while( queue_is_empty() ) { __asm__(HLT); }".
For a multi-tasking system; you need to have some sort of IPC (Inter-Process Communication). It doesn't matter if it's some type of messaging or pipes or whatever else. The IRQ handler sends keypresses to wherever (typically a virtual terminal layer and/or GUI) using the IPC, and wherever forwards the keypresses (using IPC again) to the application that is currently "active". In this case the IPC itself handles the buffering/queuing; and the IPC interacts with the scheduler such that any tasks waiting for IPC don't waste any CPU time.
In either of these cases, ASCII alone is not suitable. For example, there is no ASCII code for "F2", "page up", "alt + C" or lots of other keys that normal applications will need. For some types of software (e.g. games) the application will need to know when a key is released, and not just when a key is pressed (but this isn't just limited to games - e.g. consider an application with a scroll bar, where it scrolls while the cursor key is held down and stops scrolling when the key is released). Also (mostly for games), sometimes software needs to know which key and doesn't care what character it corresponds to (for example, "if( key_code == user_settings[key_being_used_to_fire_primary_weapon]) fire_weapon1();". Then there's internationalisation - different keyboard maps, Unicode and support for "input method editors". You probably don't want these things yet, but you won't want to rewrite everything as soon as you start wanting these things later.
Basically if you put all that together, the keyboard driver should be creating and sending "keypress packets" and not ASCII characters. Something like:
Code: Select all
typedef struct keypress_packet {
uint32_t Unicode_codepoint; // Zero if not applicable
uint32_t key_number // Similar to the "scan code" the keyboard gives you but
// simplified (one code per key, unlike scan codes)
uint32_t flags // One flag for if the key was pressed or released; plus
// more flags for the state of the shift, control and
// alt keys; plus more flags for the state of caps lock
// scroll lock, numlock.
} KEYPRESS_PACKET;
For legacy "console" applications, somewhere (e.g. in a user-space library) you'd have a "readch()" function that gets a keypress packet and ignores most of the extra information and only returns the "Unicode_codepoint" field (if it's non-zero; or for severely borked software only if it's non-zero and less than 128). For applications that aren't crusty old crud you'd also have a "get_keypress()" function (e.g. also in a user-space library) that returns the full information.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.