print · rss · source

< Gérer les interruptions - la mise en oeuvre | TutoOS | Créer et exécuter une tâche >


Gérer les interruptions du clavier

Sources

Le package contenant les sources : kernel_ManageKBD.tgz
Pour naviguer dans l'arborescence : ManageKBD


Le chipset 8042

Le clavier contient un micro-contrôleur chargé de gérer les différents évènements (pression, relachement des touches et affichages lumineux) : le 8042. Les ports d'entrée/sortie utilisés pour communiquer avec ce chipset sont les suivants :

  • 60h pour la lecture ou la transmission de données
  • 64h pour connaître le statut ou émettre des commandes

Quand une touche est pressée ou relachée, le contrôleur écrit dans son registre de données un code appelé scan code. Le contenu de ce registre est accessible via le port 60h :

i = inb(0x60);

La routine suivante attend que le buffer de sortie du 8042 soit plein puis stocke le contenu de celui-ci :

do {
    i = inb(0x64);
} while((i & 0x01) == 0);

i = inb(0x60);

Il existe deux types de scan code :

  • la pression d'une touche génère un make code
  • le relachement d'une touche génère un break code (break_code = make_code + 0x80)

La routine d'interruption complète pour la gestion des interruptions du clavier : isr_kbd_int()

#include "types.h"
#include "screen.h"
#include "io.h"
#include "kbd.h"

void isr_default_int(void)
{
        print("interrupt\n");
}

void isr_clock_int(void)
{
        static int tic = 0;
        static int sec = 0;
        tic++;
        if (tic % 100 == 0) {
                sec++;
                tic = 0;
        }
}

void isr_kbd_int(void)
{
        uchar i;
        static int lshift_enable;
        static int rshift_enable;
        static int alt_enable;
        static int ctrl_enable;

        do {
                i = inb(0x64);
        } while ((i & 0x01) == 0);

        i = inb(0x60);
        i--;

        //// putcar('\n'); dump(&i, 1); putcar(' ');

        if (i < 0x80) {         /* touche enfoncee */
                switch (i) {
                case 0x29:
                        lshift_enable = 1;
                        break;
                case 0x35:
                        rshift_enable = 1;
                        break;
                case 0x1C:
                        ctrl_enable = 1;
                        break;
                case 0x37:
                        alt_enable = 1;
                        break;
                default:
                        putcar(kbdmap
                               [i * 4 + (lshift_enable || rshift_enable)]);
                }
        } else {                /* touche relachee */
                i -= 0x80;
                switch (i) {
                case 0x29:
                        lshift_enable = 0;
                        break;
                case 0x35:
                        rshift_enable = 0;
                        break;
                case 0x1C:
                        ctrl_enable = 0;
                        break;
                case 0x37:
                        alt_enable = 0;
                        break;
                }
        }

        show_cursor();
}

La gestion du curseur

Le curseur est géré en s'adressant directement au contrôleur VGA via le port 0x3d4 (contrôle) et le port 0x3d5 (données). La routine qui affiche le curseur à l'écran est très simple :

void move_cursor (u8 x, u8 y)
{
    u16 c_pos;

    c_pos = y * 80 + x;
    outb(0x3d4, 0x0f);
    outb(0x3d5, (u8) c_pos);
    outb(0x3d4, 0x0e);
    outb(0x3d5, (u8) (c_pos >> 8));
}

void show_cursor (void)
{
    move_cursor(kX, kY);
}

< Gérer les interruptions - la mise en oeuvre | TutoOS | Créer et exécuter une tâche >

print · rss · source
Page last modified on October 03, 2010, at 03:44 PM