PS/2-Maus — Änderungen 2243 → 2244

Zeile 356: Zeile 356:
 
Die Overflow-Bits geben an, ob die Maus auf der jeweiligen Achse zu schnell bewegt wurden. Die Sign-Bits geben an, ob die jeweiligen Movements negativ sind. Und die Button-Bits geben an, ob die jeweilige Taste gedrückt ist. Der Beispiel-Code, der das Daten-Paket der Maus abholt ist beim Code für den [[#Handler-Code|IRQ12-Handler]] in der Rubrik Anwendung zu finden.
 
Die Overflow-Bits geben an, ob die Maus auf der jeweiligen Achse zu schnell bewegt wurden. Die Sign-Bits geben an, ob die jeweiligen Movements negativ sind. Und die Button-Bits geben an, ob die jeweilige Taste gedrückt ist. Der Beispiel-Code, der das Daten-Paket der Maus abholt ist beim Code für den [[#Handler-Code|IRQ12-Handler]] in der Rubrik Anwendung zu finden.
  
−
<pre>
+
<asm>
 
   147 irq12-handler:
 
   147 irq12-handler:
 
   . zum Anschauend des Codes gehe bitte zum IRQ12-Handler in der Rubrik Anwendung (Link in Text oben)
 
   . zum Anschauend des Codes gehe bitte zum IRQ12-Handler in der Rubrik Anwendung (Link in Text oben)
Zeile 380: Zeile 380:
 
   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 409: Zeile 409:
 
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 428: Zeile 428:
 
   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 444: Zeile 444:
 
   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>
  
 
=== Wheel-and-5-Button-Mode-Packet ===
 
=== Wheel-and-5-Button-Mode-Packet ===
Zeile 478: Zeile 478:
 
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>
  
 
=== Maus im Stream-Modus aktivieren ===
 
=== Maus im Stream-Modus aktivieren ===
Zeile 487: Zeile 487:
 
Nun da der Handler installiert ist, müssen wir die Maus immernoch dazu bringen ihre Daten an diesen zu senden, dies geschieht mit folgenden Befehlszeilen, in denen in dieser Reihenfolge erst dem KBC gesagt wird, dass er die Maus aktivieren soll, danach der Maus selber gesagt, dass sie sich aktivieren soll und zuletzt im CommanByte des KBC das ansprignen des IRQ12 bei Daten aktiviert wird.
 
Nun da der Handler installiert ist, müssen wir die Maus immernoch dazu bringen ihre Daten an diesen zu senden, dies geschieht mit folgenden Befehlszeilen, in denen in dieser Reihenfolge erst dem KBC gesagt wird, dass er die Maus aktivieren soll, danach der Maus selber gesagt, dass sie sich aktivieren soll und zuletzt im CommanByte des KBC das ansprignen des IRQ12 bei Daten aktiviert wird.
  
−
<pre>
+
<asm>
 
   18    mov al,0a8h        ;schiebe auf al den Befehl zur Aktivierung der Maus
 
   18    mov al,0a8h        ;schiebe auf al den Befehl zur Aktivierung der Maus
 
   19    out 64h,al          ;schicke den Befehl an den Keyboard-Controller
 
   19    out 64h,al          ;schicke den Befehl an den Keyboard-Controller
Zeile 515: Zeile 515:
 
   43    out 60h,al          ;und schicke das Command-Byte an den Daten-Port 60h, durch den Befehl 60h wird dieses neu eingelesen
 
   43    out 60h,al          ;und schicke das Command-Byte an den Daten-Port 60h, durch den Befehl 60h wird dieses neu eingelesen
 
   44    call kb.checkcmd    ;und warte, bis das Byte vollständig angenommen wurde
 
   44    call kb.checkcmd    ;und warte, bis das Byte vollständig angenommen wurde
−
</pre>
+
</asm>
  
 
=== Rad und/oder 5 Tasten-Modus aktivieren ===
 
=== Rad und/oder 5 Tasten-Modus aktivieren ===
Zeile 521: Zeile 521:
 
Nachdem der Handler installiert ist und die Maus eingeschalten ist, 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 der Handler installiert ist und die Maus eingeschalten ist, 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 570: Zeile 570:
 
   92                call write                  ;  ~
 
   92                call write                  ;  ~
 
   93            .no_5_button_mode
 
   93            .no_5_button_mode
−
</pre>
+
</asm>
  
 
=== PIC - IRQ12 aktivieren ===
 
=== PIC - IRQ12 aktivieren ===
Zeile 576: Zeile 576:
 
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>
  
 
=== Schleife, in der Mauseingaben möglich sind ===
 
=== Schleife, in der Mauseingaben möglich sind ===
Zeile 586: Zeile 586:
 
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 596: Zeile 596:
 
   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>
  
 
=== Maus deaktivieren, Programm beenden ===
 
=== Maus deaktivieren, Programm beenden ===
Zeile 602: Zeile 602:
 
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 621: Zeile 621:
 
   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 einfach 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 einfach 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 638: Zeile 638:
 
   138  
 
   138  
 
   139    retf                ;springe zum Kernel zurück
 
   139    retf                ;springe zum Kernel zurück
−
</pre>
+
</asm>
  
 
=== Programm Konzept ===
 
=== Programm Konzept ===
Zeile 689: Zeile 689:
 
Joa und in Assembler würde das wie folgt aussehen:
 
Joa und in Assembler würde das wie folgt aussehen:
  
−
<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 791: Zeile 791:
 
   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>
  
 
=== Die Ausgabe-Prozedur ===
 
=== Die Ausgabe-Prozedur ===
Zeile 797: Zeile 797:
 
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 833: Zeile 833:
 
   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>
  
 
== Schlusswort ==
 
== Schlusswort ==
Zeile 840: Zeile 840:
  
 
Soviel von mir, für Fragen per ICQ(412207644) stehe ich gerne zur Verfügung.<br>
 
Soviel von mir, für Fragen per ICQ(412207644) stehe ich gerne zur Verfügung.<br>
−
Zum erstellen des "bunten" Codes habe ich [http://www.andre-simon.de/ Andres Highlighter 2.6.5] genutzt.<br>
 
 
Das Original dieses Dokuments ist auch [http://maxinator.meugster.net/index2.php?site=http://maxinator.meugster.net/programming/ps2mouse/00600064mouse.html hier] zu finde und stammt von mir.
 
Das Original dieses Dokuments ist auch [http://maxinator.meugster.net/index2.php?site=http://maxinator.meugster.net/programming/ps2mouse/00600064mouse.html hier] zu finde und stammt von mir.
  
 
--[[Benutzer:Maxinator|Maxinator]] 22:03, 11. Nov 2007 (CET)
 
--[[Benutzer:Maxinator|Maxinator]] 22:03, 11. Nov 2007 (CET)