Designing Keyboard Drivers in C++

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
MeLkOr

Designing Keyboard Drivers in C++

Post by MeLkOr »

I have been wondering how would you design keyboard drivers in C++. I don't know if it strictly depends on the code of thew OS you're working on or not.
-MeLkOr
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Designing Keyboard Drivers in C++

Post by Pype.Clicker »

some stuff will depend on the OS you work on, other won't. For instance, setting up the IRQ handler will be OS-dependent, as you will have (or should have) an OS service that will help you installing a handler and deal with the low-level stuff like saving/restoring registers, etc.

Another thing that will be very OS-dependent is how you will notify the reception of a character to a waiter thread. In other words, you have a thread asleep and waiting for characters to come in its 'buffer', so you have to notify it everytime you push a character.

On the other side, the code that access the chip (8042) to read the scancode the keyboard sent is OS-independent, as well as the code which translates that scancode into an ASCII (or ISO-8859) code, based on the current SHIFT, ALT, etc. state.

So doing this in C++ is just a matter of having ports I/O and irq manipulations, aswell as IPC technique used for threads notifications (it would be the Events api in Clicker) available in C++ ...

and i would risk to say that imvho, enclosing the #include<> of a C kernel in an "extern("C") { ... }" block should be sufficient to access them in C++ rather than plain vanillia C.
MeLkOr

Re:Designing Keyboard Drivers in C++

Post by MeLkOr »

That seems way over my head but i'm willing to try. First of all could you explain some of the acronims you use?
-MelKoR
P.S. - Sorry about closing the message. :-\
Curufir

Re:Designing Keyboard Drivers in C++

Post by Curufir »

Bored again ;D

OS - Operating System

IRQ - Interrupt Request

IRQ handler - The code that is called when an IRQ is received

Thread - Also known as a lightweight process. Threads are associated with a specific process. They share the code and (Sometimes) static data sections of the process, but have their own stack for variable data. A single process can have many hundreds of threads running within it, all running in different areas of the code section. Using threads reduces the memory overhead that running different processes would incurr. An example might be a thread HTTP server. Instead of each request for a page waiting for the server process to be available, or spawning a brand new process (Thereby replicating code/data unnescessarily), a new thread can be created (Or assigned from a pool of threads) instead. Using threads however increases the complexity of your code with respect to access of global variables which should be isolated so that no two threads can be writing to the same global at the same time. It also increases IPC complexity.

Waiter Thread - A thread that is sleeping waiting for some external event to wake it up. For example one might have a thread that sends commands to the floppy disk drive. Whilst a read/write is taking place there is nothing for the thread to do, so it should sleep until the drive announces the operation has been completed.

Sleep - A state occupied by a process or thread in which it is not scheduled to run and therefore does not take up any processor time.

Buffer - An area to store data whilst it awaits use. This is to allow data to continue to be received even though the receiving process is currently unable (Usually by being busy processing something else) to use it.

8042 - The standard keyboard controller chip used on x86 PC systems.

Scancode - A PC keyboard produces a unique number for each key on the keyboard. One for the key being pressed and one for the key being released. Depending on the keyboard one of 3 different scancode sets may be used. It is up to the OS to translate these scancodes into useful values.

ASCII - American Standard Code for Information Interchange. This is a character code definition that uses 7 bits to describe one of 128 characters.

ISO - From the greek word isos, meaning equal. This is an international body that produces standards for many different areas including computing. ISO-8859 is a series of standard multilingual 8 bit character sets for alphabetic languages. Eg ISO-8859-1 is the standard for the West European Latin 1 character set.

I/O - Input/Output.

IPC - Inter-process communication. The means by which one process can pass information to another process for control/data passing purposes. There are different flavours of IPC, such as mailboxes, pipes, shared data areas, and many more.

API - Application Programming Interface. Quite simply the method a programmer can use to access functionality of the OS (Or an application) within their own code.

imvho - In my very humble opinion

Vanilla - In programming terms means unmodified from the original or current standard.

Don't think I missed any :).

***

Some folks might not like my definition of a thread. Quite frankly I don't care, feel free to post your own :P.
MeLkOr

Re:Designing Keyboard Drivers in C++

Post by MeLkOr »

Thanks for the help :)
-MeLkOr
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Designing Keyboard Drivers in C++

Post by Pype.Clicker »

Curufir wrote: Some folks might not like my definition of a thread. Quite frankly I don't care, feel free to post your own :P.
Thanks for taking the time of explaining all these stuff while i was on week-end :)

Your definition of a thread fits me.
Tim

Re:Designing Keyboard Drivers in C++

Post by Tim »

I'm happy with your definition of a thread, although I'd say they usually share static data, not sometimes.
Curufir wrote:It also increases IPC complexity.
Surely using multiple threads in a process decreases IPC complexity, because you're not communicating between processes? Communication between threads can be done with global variables and a semaphore or two, whereas communication between processes involves the kernel more heavily (pipes, sockets, shared memory, etc.).
MeLkOr

Re:Designing Keyboard Drivers in C++

Post by MeLkOr »

I was having some trouble with my (trial) OS that will be small and is written in C++. Here is the code...

Code: Select all

#include <iostream.h>
#include <stdlib.h>

void shell (void);
/* function shell's global variables */
char T [256];
/* end */

main (void)
{

    int ms;

    cout << "Welcome to Tropical OS" << endl;
    cout << "Press 1 to exit" << endl;
    cout << "Press 2 to continue to the command line" <<       endl;
    cin >> ms;

    if (ms == 1)
    {
        return 0;
    }
    if (ms == 2)
    {
        void shell (void);
    }
}
void shell (void)
{
    cout << "T~ ";  /* This is the command prompt */
    cin >> T;
    
    if ((T == "help") || (T == "Help"))
    {
         cout << "This isnt what it actually says right here but is as far as i need to go" << endl;
    }
The problem is that it never makes it to the function "shell"? I don't know why this happens but help would be apricated.
Curufir

Re:Designing Keyboard Drivers in C++

Post by Curufir »

Tim Robinson wrote: Surely using multiple threads in a process decreases IPC complexity, because you're not communicating between processes? Communication between threads can be done with global variables and a semaphore or two, whereas communication between processes involves the kernel more heavily (pipes, sockets, shared memory, etc.).
You say tomato I say tomato :).

One of the reasons behind me saying threads increase IPC complexity is that if one has no threads then all IPC is between processes. If threads exist then the number of IPC methods used increases because at least one of them has to deal with communication between threads not processes. If one increases the number of methods of communication one also increases the complexity of overall communication.

The other reason is one of IPC from one threaded process to another. Eg A threaded application A requesting information from a threaded server B. In the first instance this is simple, A simply spawns a thread A1, and requests information from B which spawns a thread B1 to handle the request . Now if a second request is made whilst the first one is still running then you have A spawning a new thread A2 and B spawning a new thread B2. Now with both B1 and B2 running, the OS (Or the application) has to keep control of which of A1 or A2 is the target thread in process A that the currently running B thread is passing data to. It's that control mechanism that increases the complexity IMHO.
Curufir

Re:Designing Keyboard Drivers in C++

Post by Curufir »

MeLkOr wrote: I was having some trouble with my (trial) OS that will be small and is written in C++. Here is the code...

<snip>

The problem is that it never makes it to the function "shell"? I don't know why this happens but help would be apricated.
Well my C++ code is even rustier than my C code (AFAIK C++ takes a lot more to get running standalone than C), but isn't

Code: Select all

cin >> ms
Going to return an ascii numeric character? And your tests are against integers.
Schol-R-LEA

Re:Designing Keyboard Drivers in C++

Post by Schol-R-LEA »

Actually, there are several problems in the code as presented, though some of them are minor, such as using idioms that are deprecated under the current C++ standard revision.

The key problem is that [tt]main()[/tt] is not calling [tt]shell()[/tt] at all; in the statement

Code: Select all

   
    if (ms == 2)
    {
        void shell (void);
    }
the [tt]void shell (void);[/tt] is only a function prototype, not a function invocation. The correct call would be

Code: Select all

    if (ms == 2)
    {
        shell ();
    }
The other showstopper is that you are trying to use a simple comparision on two cstrings; however, what is getting compared are the pointers, not the strings themselves. To do the comparison, you either have to use [tt]strcmp()[/tt], or else change [tt]T[/tt] to a [tt]string[/tt] object instead of a [tt]char[[]][/tt].

Also, the way C++ header files work has changed, to eliminate the file extension; so instead of [tt]<iostream.h>[/tt] you would simply use [tt]<iostream>[/tt] (C headers such as [tt]<stdio.h>[/tt] have not been changed, and indeed C++ uses this to differentiate between C and C++ headers IIRC).

Furthermore, the way iostream works, has changed: all of the stream I/O objects are now in the [tt]std[/tt] namespace, so in order to use them you either need to prepend them with the namespace scope likes this:

Code: Select all

std::cout << "Hello, World!" << std::endl;
or else add [tt]using namespace std;[/tt] at the beginning of the file.

Here is a modified version of the code as I was able to compile and run it (environment: Dev-C++ 4.9.8.1, WinXP console):

Code: Select all

/* 
Note that you only need to include <stdlib.h>
if you are actually calling one of the standard functions; 
in the code as you wrote it, you hadn't. If you were 
to use strcmp(), you'd have needed it. In this version, 
I declare T as a string instead, and so I need <string>
but not  <stdlib.h>. HTH.
*/

#include <iostream>
#include <string>


using namespace std;

void shell (void);

/* function shell's global variables */
string T;
/* end */

int main (void)
{

    int ms;

    cout << "Welcome to Tropical OS" << endl;
    cout << "Press 1 to exit" << endl;
    cout << "Press 2 to continue to the command line" << endl;
    cin >> ms;

    if (ms == 1)
    {
        return 0;
    }
    if (ms == 2)
    {
        shell ();
    }
}


void shell (void)
{
    cout << "T~ ";  /* This is the command prompt */
    cin >> T;
    
    if ((T == "help") || (T == "Help"))
    {
        cout << "This isn't what it actually says right here but is as far as i need to go" << endl;
    }
}
I intentionally used the minimum number of changes necessary to get this to work; other improvements would certainly be possible, but I'll leave that to you. HTH. C&CW.
Schol-R-LEA

Re:Designing Keyboard Drivers in C++

Post by Schol-R-LEA »

Curufir wrote:
Well my C++ code is even rustier than my C code (AFAIK C++ takes a lot more to get running standalone than C), but isn't

Code: Select all

cin >> ms
Going to return an ascii numeric character? And your tests are against integers.
As I understand it, the input and output operators are friend functions of the stream classes, not methods. This allows them to be overloaded for new classes. There are versions of the I/O operators for each of the basic C++ types. Using [tt]>>[/tt] to read from an [tt]istream[/tt] with an integer argument will attempt to parse the input as an integer.

I'm not entirely sure I have this correct, however; any comments and corrections are welcome about this.
Curufir

Re:Designing Keyboard Drivers in C++

Post by Curufir »

Schol-R-LEA wrote: I'm not entirely sure I have this correct, however; any comments and corrections are welcome about this.
I'll take your word for it seeing as my C++ is so bad atm ;D. Hmm, I'm not sure how happy I'd be to have the compiler playing around with things in the background that much. Perhaps that's why C++ and I have never really got on.
Post Reply