PS/2-Maus — Änderungen 2226 → 2227

Zeile 51: Zeile 51:
 
|}
 
|}
  
−
<pre>
+
<asm>
 
   141 ;***************************************************************************************************************
 
   141 ;***************************************************************************************************************
 
   142 ;dies ist der IRQ12, der immer angesprungen wird, wenn sich die Daten der Maus verändert habe (sofern der Stream-Mode benutzt wird)
 
   142 ;dies ist der IRQ12, der immer angesprungen wird, wenn sich die Daten der Maus verändert habe (sofern der Stream-Mode benutzt wird)
Zeile 146: Zeile 146:
 
   233    popa            ;stelle auch die anderen Register wieder her
 
   233    popa            ;stelle auch die anderen Register wieder her
 
   234    iret            ;und verlasse den Interrupt</pre>
 
   234    iret            ;und verlasse den Interrupt</pre>
 +
</asm>
  
−
<pre>
+
<asm>
 
   286 .read.mouse:
 
   286 .read.mouse:
 
   287    push cx            ;cx sichern
 
   287    push cx            ;cx sichern
Zeile 166: Zeile 167:
 
   302    ret                ;zum Abschluss springen wir zum Aufrufsort zurück; das Byte liegt dabei in al und ZF zeigt Erfolg bei 1 an
 
   302    ret                ;zum Abschluss springen wir zum Aufrufsort zurück; das Byte liegt dabei in al und ZF zeigt Erfolg bei 1 an
 
   303 ;************************* wartet eine Weile ob Daten kommen und speichert diese ggf. in al ab *************************
 
   303 ;************************* wartet eine Weile ob Daten kommen und speichert diese ggf. in al ab *************************
−
</pre>
+
</asm>
  
 
Besonders interessant ist eig. nur die Prozedur kb.read.mouse, die vom irq12 3x angesprungen wird, um die einzelnen Bytes des Maus-Pakets abzurufen. Der Rest des Codes des IRQ12's speichert diese Bytes, untersucht diese Bytes und verändert die xy-Coordinate des Mauszeigers in den Variablen [x] und [y] entsprechend der Movement- und Sign-Bits.
 
Besonders interessant ist eig. nur die Prozedur kb.read.mouse, die vom irq12 3x angesprungen wird, um die einzelnen Bytes des Maus-Pakets abzurufen. Der Rest des Codes des IRQ12's speichert diese Bytes, untersucht diese Bytes und verändert die xy-Coordinate des Mauszeigers in den Variablen [x] und [y] entsprechend der Movement- und Sign-Bits.
Zeile 193: Zeile 194:
 
Byte 4, also die Z-Bewegung kann eigentlich nur Werte von -8(1111) bis +7(0000) annehmen und nutzt deswegen eigentlich nur Bit 3-0, die anderen Bits dienen dabei nur als Sign-Extension, also nehmen den Zustand von Bit3 an (man schlage auch mal die Befehle movsx, movzx nach x) ). Dazu noch der Code, der in den Wheel-Mode schaltet, der Code zum abholen sollte klar sein, dass ist der selbe wie bei dem Standard-Paket nur, dass noch per call kb.read.mouse ein Byte mehr abgeholt werden muss. Der COde gibt am Ende noch die ID plus dem Error auf ah aus... dafür die Zeilen 45-47.
 
Byte 4, also die Z-Bewegung kann eigentlich nur Werte von -8(1111) bis +7(0000) annehmen und nutzt deswegen eigentlich nur Bit 3-0, die anderen Bits dienen dabei nur als Sign-Extension, also nehmen den Zustand von Bit3 an (man schlage auch mal die Befehle movsx, movzx nach x) ). Dazu noch der Code, der in den Wheel-Mode schaltet, der Code zum abholen sollte klar sein, dass ist der selbe wie bei dem Standard-Paket nur, dass noch per call kb.read.mouse ein Byte mehr abgeholt werden muss. Der COde gibt am Ende noch die ID plus dem Error auf ah aus... dafür die Zeilen 45-47.
  
−
<pre>
+
<asm>
 
   71    mov al,0F3h        ;Befehl zum senden und neu setzen der SampleRate auf al schieben
 
   71    mov al,0F3h        ;Befehl zum senden und neu setzen der SampleRate auf al schieben
 
   72    call kb.write.mouse ;und per vordefinierter Prozedur an die Maus senden
 
   72    call kb.write.mouse ;und per vordefinierter Prozedur an die Maus senden
Zeile 212: Zeile 213:
 
   87    sti                ;nun da wir das Byte entgegengenommen haben, können wir die IRQs wieder aktivieren
 
   87    sti                ;nun da wir das Byte entgegengenommen haben, können wir die IRQs wieder aktivieren
 
   88    mov [mouseid],al    ;speichere die erhaltene MausID in einer Variable, damit der IRQ12-Handler weiß, ob die Maus ein Rad hat
 
   88    mov [mouseid],al    ;speichere die erhaltene MausID in einer Variable, damit der IRQ12-Handler weiß, ob die Maus ein Rad hat
−
</pre>
+
</asm>
  
−
<pre>
+
<asm>
 
   304 .write.mouse:
 
   304 .write.mouse:
 
   305    push ax            ;al sichern, da dort der zu sendende Befehl gesichert ist
 
   305    push ax            ;al sichern, da dort der zu sendende Befehl gesichert ist
Zeile 228: Zeile 229:
 
   315    ret                ;verlasse Prozedur und springe zumi Aufruf zurück
 
   315    ret                ;verlasse Prozedur und springe zumi Aufruf zurück
 
   316 ;******* Prozedur schickt den Befehl per D4h an die Maus und gibt error von kb.read aus (prc succesfull if ah=0 und al=FAh sein) *********
 
   316 ;******* Prozedur schickt den Befehl per D4h an die Maus und gibt error von kb.read aus (prc succesfull if ah=0 und al=FAh sein) *********
−
</pre>
+
</asm>
  
 
Nun habt ihr aber sicher auch schon gemerkt, dass in dem 3 Byte noch 4 Bits frei sind und wir noch nicht die Stati der 3.+4. Taste bekommen, falls diese vorhanden wären. Damit diese Stati auch mit dem 4.Byte mitgesendet werden, gibt es dafür auch wieder eine Sequenz um dies zu aktivieren, die wie folgt aussieht:
 
Nun habt ihr aber sicher auch schon gemerkt, dass in dem 3 Byte noch 4 Bits frei sind und wir noch nicht die Stati der 3.+4. Taste bekommen, falls diese vorhanden wären. Damit diese Stati auch mit dem 4.Byte mitgesendet werden, gibt es dafür auch wieder eine Sequenz um dies zu aktivieren, die wie folgt aussieht:
Zeile 256: Zeile 257:
 
Das Programm hakt sich in den IRQ12 ein, der auf den INT74h sein sollte, ansonsten muss diese Zeile geändert werden:
 
Das Programm hakt sich in den IRQ12 ein, der auf den INT74h sein sollte, ansonsten muss diese Zeile geändert werden:
  
−
<pre>
+
<asm>
 
   13    mov [es:74h*4+2],cs        ;und dann an den Eintrag für den Int74h/IRQ12 das Segment
 
   13    mov [es:74h*4+2],cs        ;und dann an den Eintrag für den Int74h/IRQ12 das Segment
 
   14    mov [es:74h*4],word irq12  ;und den Offset des Int-Handlers speichern
 
   14    mov [es:74h*4],word irq12  ;und den Offset des Int-Handlers speichern
−
</pre>
+
</asm>
  
 
Nachdem es sich in den IRQ gehakt hat, prüft es, ob die Maus ein Rad und/oder 5 Tasten hat, dies geshieht mit folgenden Zeilen, in dem es die gerade eben besprochenen Sample-Rate-Sequenzen durchführt und dann die ID in eine Variable speichert, die der Int-Handler ausliest um zu wissen, ob er nun 3 oder 4 Bytes holen soll:
 
Nachdem es sich in den IRQ gehakt hat, prüft es, ob die Maus ein Rad und/oder 5 Tasten hat, dies geshieht mit folgenden Zeilen, in dem es die gerade eben besprochenen Sample-Rate-Sequenzen durchführt und dann die ID in eine Variable speichert, die der Int-Handler ausliest um zu wissen, ob er nun 3 oder 4 Bytes holen soll:
  
−
<pre>
+
<asm>
 
   46            lea si,[three_button_mode]      ;zum debuggen, gibt nachricht aus, dass maus sich
 
   46            lea si,[three_button_mode]      ;zum debuggen, gibt nachricht aus, dass maus sich
 
   47            call write                      ;im 3-tasten-modus befindet
 
   47            call write                      ;im 3-tasten-modus befindet
Zeile 312: Zeile 313:
 
   92                call write                  ;  ~
 
   92                call write                  ;  ~
 
   93            .no_5_button_mode
 
   93            .no_5_button_mode
−
</pre>
+
</asm>
  
 
Um nun sicher zu gehen, dass der IRQ12 überhaupt angeschalten ist, schalten wir ihn lieber nocheinmal persönlich mit folgenden Zeilen über den PIC ein:
 
Um nun sicher zu gehen, dass der IRQ12 überhaupt angeschalten ist, schalten wir ihn lieber nocheinmal persönlich mit folgenden Zeilen über den PIC ein:
  
−
<pre>
+
<asm>
 
   95    in al,0A1h          ;hole von dem PIC2 das IMR
 
   95    in al,0A1h          ;hole von dem PIC2 das IMR
 
   96    and al,11101111b    ;um darin den IRQ12 zu maskieren, damit er aktiviert wird
 
   96    and al,11101111b    ;um darin den IRQ12 zu maskieren, damit er aktiviert wird
 
   97    out 0A1h,al        ;und sende das modifizierte IMR an den Slave
 
   97    out 0A1h,al        ;und sende das modifizierte IMR an den Slave
−
</pre>
+
</asm>
  
 
Nun da die Maus aktiviert und ein funktionierender IRQ12-Handler installiert sein solte, wartet eine Schleife auf ESC. Solange diese Schleife ausgeführt wird, kann der IRQ12 ja trotzdem den Handler anspringen, also kurz gesagt, solange man sich in folgender Schleife befindet werden alle Bewegungen der Maus abgefangen und grafisch dargestellt.
 
Nun da die Maus aktiviert und ein funktionierender IRQ12-Handler installiert sein solte, wartet eine Schleife auf ESC. Solange diese Schleife ausgeführt wird, kann der IRQ12 ja trotzdem den Handler anspringen, also kurz gesagt, solange man sich in folgender Schleife befindet werden alle Bewegungen der Maus abgefangen und grafisch dargestellt.
  
−
<pre>
+
<asm>
 
   99    wait_esc:
 
   99    wait_esc:
 
   100        mov ah,1        ;Funktion 1 des Int16h wählen, um abzufragen, ob ein Tastendruck vorhanden ist
 
   100        mov ah,1        ;Funktion 1 des Int16h wählen, um abzufragen, ob ein Tastendruck vorhanden ist
Zeile 334: Zeile 335:
 
   106        cmp ah,1        ;vergleicht den asciicode mit dem von ESC
 
   106        cmp ah,1        ;vergleicht den asciicode mit dem von ESC
 
   107    jne wait_esc        ;wenn ESC nicht gedrückt wurde, warte auf näcshten Tastendruck
 
   107    jne wait_esc        ;wenn ESC nicht gedrückt wurde, warte auf näcshten Tastendruck
−
</pre>
+
</asm>
  
 
Wenn die Schleife durch drücken von Esc verlassen wurde, dann lösche als erstes Bit1 im command-Byte des Keyboards, damit das anspringen des IRQ12 bei Daten deaktiviert wird.^
 
Wenn die Schleife durch drücken von Esc verlassen wurde, dann lösche als erstes Bit1 im command-Byte des Keyboards, damit das anspringen des IRQ12 bei Daten deaktiviert wird.^
  
−
<pre>
+
<asm>
 
   109    cli                ;alle Interrupts auschalten, damit nicht unser Keyboard-Int das gesendete Byte erhält xD
 
   109    cli                ;alle Interrupts auschalten, damit nicht unser Keyboard-Int das gesendete Byte erhält xD
 
   110    mov al,20h          ;Befehl zum auslesen des Kommando-Bytes auf al schieben
 
   110    mov al,20h          ;Befehl zum auslesen des Kommando-Bytes auf al schieben
Zeile 357: Zeile 358:
 
   125    out 60h,al          ;und schicke das Command-Byte an den Daten-Port 60h, durch den Befehl 60h wird dieses neu eingelesen
 
   125    out 60h,al          ;und schicke das Command-Byte an den Daten-Port 60h, durch den Befehl 60h wird dieses neu eingelesen
 
   126    call kb.checkcmd    ;und warte, bis das Byte vollständig angenommen wurde
 
   126    call kb.checkcmd    ;und warte, bis das Byte vollständig angenommen wurde
−
</pre>
+
</asm>
  
 
Danach wird einfaxch nur noch ein mal die Maus selber deaktiviert, danach wird dem Keyboard-Controller gesagt, dass diese deaktiviert wird und zuletzt wird der IRQ12 im PIC wieder maskiert. Am Ende der Ende-Sequenz wird mit "retf" zu meinem Kernel zurückgesprungen. Retf sollte man je nach seinem eigenen OS anpassen.
 
Danach wird einfaxch nur noch ein mal die Maus selber deaktiviert, danach wird dem Keyboard-Controller gesagt, dass diese deaktiviert wird und zuletzt wird der IRQ12 im PIC wieder maskiert. Am Ende der Ende-Sequenz wird mit "retf" zu meinem Kernel zurückgesprungen. Retf sollte man je nach seinem eigenen OS anpassen.
  
−
<pre>
+
<asm>
 
   128    mov al,0F5h        ;auf al den Befehl zum deaktivieren der Maus selbst schieben
 
   128    mov al,0F5h        ;auf al den Befehl zum deaktivieren der Maus selbst schieben
 
   129    call kb.write.mouse ;und an die Maus senden
 
   129    call kb.write.mouse ;und an die Maus senden
Zeile 374: Zeile 375:
 
   138  
 
   138  
 
   139    retf                ;springe zum Kernel zurück
 
   139    retf                ;springe zum Kernel zurück
−
</pre>
+
</asm>
  
 
: So, das war nun unser Programm, das im Konzept so aussehen würde:
 
: So, das war nun unser Programm, das im Konzept so aussehen würde:
Zeile 417: Zeile 418:
 
Joa und in Assembler würde das wie folgt aussehen (selbe Code wie weiter oben, wo per Beispiel gezeigt wird, wie man das Maus-Daten-Paket abholt):
 
Joa und in Assembler würde das wie folgt aussehen (selbe Code wie weiter oben, wo per Beispiel gezeigt wird, wie man das Maus-Daten-Paket abholt):
  
−
<pre>
+
<asm>
 
   141 ;***************************************************************************************************************
 
   141 ;***************************************************************************************************************
 
   142 ;dies ist der IRQ12, der immer angesprungen wird, wenn sich die Daten der Maus verändert habe (sofern der Stream-Mode benutzt wird)
 
   142 ;dies ist der IRQ12, der immer angesprungen wird, wenn sich die Daten der Maus verändert habe (sofern der Stream-Mode benutzt wird)
Zeile 519: Zeile 520:
 
   240 actualb db 0    ;hier wird gespeichert, welche bytes des Maus-Daten-Pakets schon abgeholt wurden (für jedes Byte wird der IRQ12
 
   240 actualb db 0    ;hier wird gespeichert, welche bytes des Maus-Daten-Pakets schon abgeholt wurden (für jedes Byte wird der IRQ12
 
   241                ;einzeln angesprungen)
 
   241                ;einzeln angesprungen)
−
</pre>
+
</asm>
  
 
Wie schon erwähnt wird evtl. hier noch etwas am Abholen und Interpretieren modifiziert, aber ich wollte euch nicht warten lassen, da ich erst ein externes Disketten-Laufwerk bei Amazon bestellen muss ;). Doch weiter gehts. Zum Schluss möchte ich es wenigstens versuchen euch einen Ansatz zu geben, wie man sich am besten in die Visualisierungs-Prozedur hineinzuversetzen hat, denn auch wenn alles kommentiert ist, ist das ein bisschen schwierig meinen genauen Gedankengang dabei festzuhalten. Das ganze funktioniert, indem das Bild und die Daten und Co alles gleich in den Bildschirmspeicher geschrieben wird. Der Bildschrimspeicher, also die Addressen sind alle darauf eingestellt, dass der momentan VideoModus 03h ist, also 80 Zeichen Zeilenlänge bei 25 Zeilen pro Bildschirm hat. So fängt der Bildschirmspeicher im 03h-Modus am segment 0B800h im Speicher an. Der Speicher selber ist 4000Bytes groß, für jedes Zeichen 2 Bytes, eins für das Attribut des Zeichen wie Hintergrund- und Schriftfarbe und eins, wo das Char gespeichert ist, macht bei 25 Zeilen*80 Zeichen*2 Bytes=4000Byte. Das ganze sei an einer Befehlszeile verdeutlicht:
 
Wie schon erwähnt wird evtl. hier noch etwas am Abholen und Interpretieren modifiziert, aber ich wollte euch nicht warten lassen, da ich erst ein externes Disketten-Laufwerk bei Amazon bestellen muss ;). Doch weiter gehts. Zum Schluss möchte ich es wenigstens versuchen euch einen Ansatz zu geben, wie man sich am besten in die Visualisierungs-Prozedur hineinzuversetzen hat, denn auch wenn alles kommentiert ist, ist das ein bisschen schwierig meinen genauen Gedankengang dabei festzuhalten. Das ganze funktioniert, indem das Bild und die Daten und Co alles gleich in den Bildschirmspeicher geschrieben wird. Der Bildschrimspeicher, also die Addressen sind alle darauf eingestellt, dass der momentan VideoModus 03h ist, also 80 Zeichen Zeilenlänge bei 25 Zeilen pro Bildschirm hat. So fängt der Bildschirmspeicher im 03h-Modus am segment 0B800h im Speicher an. Der Speicher selber ist 4000Bytes groß, für jedes Zeichen 2 Bytes, eins für das Attribut des Zeichen wie Hintergrund- und Schriftfarbe und eins, wo das Char gespeichert ist, macht bei 25 Zeilen*80 Zeichen*2 Bytes=4000Byte. Das ganze sei an einer Befehlszeile verdeutlicht:
  
−
<pre>
+
<asm>
 
   01    mov [es:100], word 1234h
 
   01    mov [es:100], word 1234h
−
</pre>
+
</asm>
  
 
Diese Zeile würde an die Stelle 0;50 auf den Bildschirm eine grüne 4 auf blauem Hintergrund ausgeben. Der Hintergrund ist blau, weil die "1" dies so sagt, bei 2 gilt das für den Vordergrund und 34h ist wie schon gesagt das Zeichen selber. Das wäre es dann auch schon, mehr kann ich dazu einfach nicht sagen, versucht euch einfach in die Prozedur hineinzuversetzen, ein bisschen rumzuspielen und die eigenartige Adressierungen durchzudenken. Und hier ist die langersehnte Prozedur zum veranschaulichen des Pakets xD:
 
Diese Zeile würde an die Stelle 0;50 auf den Bildschirm eine grüne 4 auf blauem Hintergrund ausgeben. Der Hintergrund ist blau, weil die "1" dies so sagt, bei 2 gilt das für den Vordergrund und 34h ist wie schon gesagt das Zeichen selber. Das wäre es dann auch schon, mehr kann ich dazu einfach nicht sagen, versucht euch einfach in die Prozedur hineinzuversetzen, ein bisschen rumzuspielen und die eigenartige Adressierungen durchzudenken. Und hier ist die langersehnte Prozedur zum veranschaulichen des Pakets xD:
  
−
<pre>
+
<asm>
 
   369 ;***************************************************************************************
 
   369 ;***************************************************************************************
 
   370 ;Display-Mouse -> eine ganz spezifische Prozedur, die die Daten des Mouse-Packets vernaschaulicht
 
   370 ;Display-Mouse -> eine ganz spezifische Prozedur, die die Daten des Mouse-Packets vernaschaulicht
Zeile 747: Zeile 748:
 
   584    popad          ;dann stelle die Register wieder her
 
   584    popad          ;dann stelle die Register wieder her
 
   585    ret            ;und kehre zum Aufrufsort zurück
 
   585    ret            ;und kehre zum Aufrufsort zurück
−
</pre>
+
</asm>
  
 
Und das wars auch schon von mir, mehr ist nicht zu sagen, vor allem, da ich den Code extra stark kommentiert habe. Am Anfang des Dokuments ist der Downloadlink dessen, viel Spaß damit und viel Glück bei eurem OS xD. Wer sich noch tiefer in das Thema einlesen will, dem empfehle ich folgendes [http://maxinator.meugster.net/programming/ps2mouse/tp-intf2-4.PDF Dokument] über das Synaptic-Touchpad, in dem auch das PS/2-Protokoll gut beschrieben ist. Das ganze Programm kann auch gleich auf meinem [http://maxinator.meugster.net/programme/downloads.html OS] getestet werden, indem ihr in die Shell als Befehl einfach "ps2mouse" oder "run ps2mouse" eingebt.
 
Und das wars auch schon von mir, mehr ist nicht zu sagen, vor allem, da ich den Code extra stark kommentiert habe. Am Anfang des Dokuments ist der Downloadlink dessen, viel Spaß damit und viel Glück bei eurem OS xD. Wer sich noch tiefer in das Thema einlesen will, dem empfehle ich folgendes [http://maxinator.meugster.net/programming/ps2mouse/tp-intf2-4.PDF Dokument] über das Synaptic-Touchpad, in dem auch das PS/2-Protokoll gut beschrieben ist. Das ganze Programm kann auch gleich auf meinem [http://maxinator.meugster.net/programme/downloads.html OS] getestet werden, indem ihr in die Shell als Befehl einfach "ps2mouse" oder "run ps2mouse" eingebt.