Hi,
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;
}
That is unbelievably wrong.
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).
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;
}
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).
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;
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