PSE Seance 3 : Différence entre versions

De Ensiwiki
Aller à : navigation, rechercher
Ligne 21 : Ligne 21 :
 
# appeler la fonction <tt>void do_scancode(int code)</tt> fournie, en lui passant en paramètre le code de la touche (attention, on passe bien un entier sur 32 bits et pas juste un octet) ;
 
# appeler la fonction <tt>void do_scancode(int code)</tt> fournie, en lui passant en paramètre le code de la touche (attention, on passe bien un entier sur 32 bits et pas juste un octet) ;
 
# restaurer le contexte d'exécution, puis terminer le traitant avec l'instruction <tt>iret</tt>.
 
# restaurer le contexte d'exécution, puis terminer le traitant avec l'instruction <tt>iret</tt>.
 +
 +
=== Traitement des caractères reçus ===
 +
 +
La fonction <tt>do_scancode</tt> (extraite du noyau Linux) réalise toutes les opérations complexes de décodage de la touche manipulée : vous n'avez pas à comprendre son fonctionnement précis.
 +
 +
Une fois ce traitement terminée, elle appelle la fonction <tt>void keyboard_data(char *str)</tt> que vous allez devoir écrire. Cette fonction reçoit en argument une chaîne composée des caractères (codes ASCII) correspondant à la touche manipulée : en effet, certaines touches particulières (touches de fonction, etc.) sont représentées par plusieurs codes ASCII.
 +
 +
Pour bien comprendre le fonctionnement de ce mécanisme, on vous recommande de commencer par afficher les codes ASCII contenus dans la chaîne passée en paramètre ainsi que le symbole s'il est imprimable, ce qui peut être fait très simplement en implantant <tt>keyboard_data</tt> comme suit :
 +
<pre>
 +
void keyboard_data(char *str)
 +
{
 +
    printf("Codes ASCII de la touche : ");
 +
    for (int i = 0; str[i] != '\0'; i++) {
 +
        printf("%u ", (unsigned)str[i]);
 +
    }
 +
    if ((str[0] >= 32) && (str[0] < 127)) {
 +
        printf(", symbole imprimable : '%c' ", str[0]);
 +
    }
 +
    printf("\n");
 +
}
 +
</pre>

Version du 25 septembre 2010 à 14:58

Mycomputer.png  Deuxième Année  CDROM.png  Informatique 

Dans cette troisième et dernière séance de Pratique du Système, on va implanter la gestion du clavier dans le système commencé pendant les séances précédentes.

Principe général

Le clavier fonctionne grâce au mécanisme d'interruptions déjà utilisé pour l'horloge à la séance précédente. Lorsqu'un évenement à lieu en provenance du clavier (une touche pressée par exemple), le contrôleur d'interruption reçoit l'IRQ 1. Il active en réaction le signal d'interruption externe 33, pour lequel on doit donc avoir écrit un traitant approprié.

C'est ce traitant qui sensé réaliser tout le travail nécessaire au traitement de l'évenement (par exemple, détecter quelle touche a été pressée, convertir le code de la touche (scancode) en code ASCII pour permettre son affichage, etc.). Dans le cadre des TP de PSE, comme il s'agit d'une opération complexe, on vous fourni une partie du code nécessaire au décodage des événements clavier et votre travail consistera principalement à utiliser correctement le code fourni.

Traitement de l'interruption clavier

Le traitant à écrire pour gérer l'interruption 33 doit réaliser les opérations suivantes dans l'ordre spécifié :

  1. sauvegarder le contexte d'exécution, comme ça a dû être fait aussi pour l'interruption horloge ;
  2. acquitter l'interruption auprès du contrôle d'interruption, là encore de la même façon que pour l'interruption 32 ;
  3. lire le code de la touche manipulée, en utilisant les ports d'entrée-sortie : dans ce cas, il suffit de lire un octet sur le port de données 0x60, grâce à l'instruction inb ;
  4. appeler la fonction void do_scancode(int code) fournie, en lui passant en paramètre le code de la touche (attention, on passe bien un entier sur 32 bits et pas juste un octet) ;
  5. restaurer le contexte d'exécution, puis terminer le traitant avec l'instruction iret.

Traitement des caractères reçus

La fonction do_scancode (extraite du noyau Linux) réalise toutes les opérations complexes de décodage de la touche manipulée : vous n'avez pas à comprendre son fonctionnement précis.

Une fois ce traitement terminée, elle appelle la fonction void keyboard_data(char *str) que vous allez devoir écrire. Cette fonction reçoit en argument une chaîne composée des caractères (codes ASCII) correspondant à la touche manipulée : en effet, certaines touches particulières (touches de fonction, etc.) sont représentées par plusieurs codes ASCII.

Pour bien comprendre le fonctionnement de ce mécanisme, on vous recommande de commencer par afficher les codes ASCII contenus dans la chaîne passée en paramètre ainsi que le symbole s'il est imprimable, ce qui peut être fait très simplement en implantant keyboard_data comme suit :

void keyboard_data(char *str)
{
    printf("Codes ASCII de la touche : ");
    for (int i = 0; str[i] != '\0'; i++) {
        printf("%u ", (unsigned)str[i]);
    }
    if ((str[0] >= 32) && (str[0] < 127)) {
        printf(", symbole imprimable : '%c' ", str[0]);
    }
    printf("\n");
}