Autor Thema: [All In One]-Question lolxdfly  (Gelesen 44517 mal)

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #20 am: 03. October 2013, 12:40 »
Hallo,
habe jetzt versuch alles mit einem Array zu machen. Allerdings gibt er bei manchen Buchstaben noch ein anderes Zeichen mit aus. Wenn ich das mit den Breakcode richtig verstanden habe kann es daran nich liegen O.o
Hier der Code:
#ifndef ScConverter_H
#define ScConverter_H
 
#include "stdint.h"
 
  char SC2Char(unsigned char c)
  {
unsigned char nonShifttabel[] = {0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0,
0, 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 0, '+', 0, 0,
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0, 0, '^', 0, '#',
'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, 0, 0, ' ', 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', ',', '<', 0, 0, 0, 0 };

        //kommt später:
/*unsigned char Shifttabel[] = {0, 0, '!', 0, '§', '$', '%', '&', '/', '(', ')', '=', '?', 0, 0,
0, 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 0, '*', 0, 0,
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0, 0, '^', 0, 0,
'Y', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '-', 0, 0, 0, ' ', 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', ',', '<', 0, 0, 0, 0 };*/
unsigned char c1;

if(nonShifttabel[c] != 0)
{
c1=nonShifttabel[c];
}
else
{
c1='\0';
}
return c1;
  }
#endif

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #21 am: 09. October 2013, 17:15 »
Aber wie kann ich jetzt Make- und Breakcode unterscheiden? Lässt sich der Breakcode irgendwie identifizieren?
Wenn der Scancode kleiner als 128 ist, ist es ein Make-Code, sonst ist es ein Break-Code (für die Taste "Scancode-128").

Hallo,
ich habe jetzt glaub ich mein Problem erkannt! Die eine Frage zur Unterscheidung von Make und Breakcode war flasch gestellt! Was ich eigentlich fragen wollte war, wie man z.B. zwischen PgUp und 9(Numpad) unterscheidet. In den Tabellen, die man im Internet findet steht:
Zitat
Keypad 9  (PgUp)
Soll das heißen, dass die 9 auf dem Numpad und PageUp den gleichen Make und Breakcode haben? Irgendwie unterscheiden sie sich ja schon:
Zitat
9 gedrückt halten = 9
!=
Zitat
PgUp gedrückt halten = 999999...

EDIT: Ich seh grade das das höchstwahrscheinlich an den extended Scancodes liegt. Habe versucht sie hiermit abzufangen... hat aber nicht geklappt :( :

if(c==0xE0 || c==0xE1)
return '\0';

lolxdfly
« Letzte Änderung: 11. October 2013, 17:24 von lolxdfly »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #22 am: 11. October 2013, 17:41 »
Ja, soweit ich weiß hat das was mit Extended Scan Codes zu tun. Wenn du einen Keyboard-IRQ bekommst, der dir einen Extended Scan Code liefert, solltest du das in einer Variable merken, und beim nächsten IRQ dann entsprechend behandeln. Siehe auch Beispiel im Wiki. Ich weiß nicht, ob die 9 oder die Bild-Auf-Taste den Extended Scan Code sendet, aber das kann man ja experimentell feststellen.

Vermutlich hast du bisher auch noch nichts getan, um die Taste Num Lock zu behandeln. Wenn Num Lock aus ist, dann sollte beim Drücken der 9 ja tatsächlich dasselbe passieren wie bei der Bild-Auf-Taste. Die Unterscheidung ob Num Lock an oder aus ist, geschieht übrigens im Treiber, nicht in der Tastatur selbst. Du solltest also die LEDs (Num Lock, Caps Lock und Scroll Lock) so initialisieren wie du das haben willst(mit Tastatur-Befehl 0xED), und in deinem Treiber entsprechende Variablen setzen, um dir zu merken welche LED an ist. Wenn der User dann die Num Lock Taste drückt, musst du die Variable entsprechend ändern. Wenn du den Scancode für 9 bekommst, schaust du dann in dieser Variable nach, und wenn Num Lock aus ist, tust du so, als ob Bild-Auf gedrückt wurde, ansonsten halt eine 9.
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #23 am: 11. October 2013, 22:22 »
Hallo,

die ersten PC-Tastaturen hatten 10 F-Tasten links, Buchstaben, Ziffernblock und sonst nichts. Das ganze Extended-Scancode-Zeug ist darum so kompliziert, damit Software, die solche alten Tastaturen erwartet, nicht verwirrt wird (solange unbekannte Scancodes ignoriert werden).

Gruß,
Svenska

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #24 am: 12. October 2013, 14:09 »
Hallo,
danke für die Antworten :-).
Leider habe ich das Arbeiten mit Befehlen von Ports noch nie richtig hinbekommen (Habe es bis jetzt ja auch noch nie dringend gebraucht).
Ich habs mal so versucht:
bool ScrollLock=0;
bool NumLock=0;
bool CapsLock=0;
uint8_t led=inb(0xED); //Port:0x60 Befehl:0xED ...hmmm outb hätte 2 Wertübergaben, aber es returnt kein Wert
if(led == 00000001)         ScrollLock=1;
if(led == 00000010)            NumLock=1;
if(led == 00000100) CapsLock=1;
if(led == 00000110) CapsLock=1;    NumLock=1;
if(led == 00000011)    NumLock=1;   ScrollLock=1;
if(led == 00000111) CapsLock=1;    NumLock=1; ScrollLock=1;       
Kann mir jemand erklären, wie man es richig macht?

lolxdfly
« Letzte Änderung: 12. October 2013, 14:12 von lolxdfly »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #25 am: 12. October 2013, 14:30 »
Es gibt wie immer mehrere Lösungen. Aus meiner Sicht ist die eleganteste Möglichkeit ein Zustandsautomat (state machine). Suche dir mal im Internet raus, wie das funktioniert. Implementieren kannst du es mit einem switch/case.

IN liest von einem Port. Du übergibst also die Adresse des Ports und bekommst einen Wert geliefert.
OUT schreibt auf einen Port. Du übergibst also die Adresse des Ports und zusätzlich einen Wert.

Wenn du auf einen Port etwas schreiben sollst und dann die Antwort lesen sollst, dann musst du erst OUT(Port, Daten) machen, um dann mit Ergebnis = IN(Port) das Ergebnis zu lesen.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #26 am: 13. October 2013, 14:20 »
Es gibt wie immer mehrere Lösungen. Aus meiner Sicht ist die eleganteste Möglichkeit ein Zustandsautomat (state machine). Suche dir mal im Internet raus, wie das funktioniert. Implementieren kannst du es mit einem switch/case.

IN liest von einem Port. Du übergibst also die Adresse des Ports und bekommst einen Wert geliefert.
OUT schreibt auf einen Port. Du übergibst also die Adresse des Ports und zusätzlich einen Wert.

Wenn du auf einen Port etwas schreiben sollst und dann die Antwort lesen sollst, dann musst du erst OUT(Port, Daten) machen, um dann mit Ergebnis = IN(Port) das Ergebnis zu lesen.

Danke. Hmm trotzdem mache ich noch immer was falsch. Ich habe outb(0x60, 0xED) eingefügt! Außerdem habe ich vorsichtshalber den Binärcode in Dezimalcode umgerechnet, weil ich mir nicht sicher war, ob er den als binär erkennt:
bool ScrollLock=0;
bool NumLock=0;
bool CapsLock=0;
outb(0x60, 0xED); // Befehl 0xED an Port 0x60 schreiben
uint8_t led=inb(0x60); //Port 0x60 auslesen
if(led == 1) ScrollLock=1;
if(led == 2) NumLock=1;
if(led == 4) CapsLock=1;
if(led == 5) CapsLock=1; ScrollLock=1;
if(led == 6) CapsLock=1; NumLock=1;
if(led == 3) NumLock=1; ScrollLock=1;
if(led == 7) CapsLock=1; NumLock=1; ScrollLock=1;

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #27 am: 13. October 2013, 14:50 »
Hallo,

Portzugriffe sind Hardwarezugriffe, im Allgemeinen ist das kein RAM. Das heißt, wenn du etwas reinschreibst, dann heißt das nicht, dass du das auch wieder rauslesen kannst. Lese- und Schreibzugriffe können völlig verschiedene Dinge in der Hardware auslösen.

Der Tastaturbefehl 0xED setzt den LED-Zustand. Lesen kannst du ihn damit nicht. "OUT(0x60, 0xED); OUT(0x60, 0x07);" sollte die drei LEDs einschalten.

Verlasse dich niemals darauf, dass reservierte Bits beim Lesen den Wert Null haben. Aktualisierte Chips nutzen diese Bits möglicherweise für Sonderfunktionen, sind aber zur älteren Version kompatibel. Dann gilt in der Regel (siehe Datenblatt!), dass man reservierte Bits ignoriert (Lesezugriff) oder nullsetzt (Schreibzugriff). Das heißt, dass deine Liste von Abfragen alle(!) 256 möglichen Einträge abfragen sollte. Um sich das zu ersparen, arbeitet man mit Bitmasken, die man mit logischen Operatoren auswertet:

if(led & 0x01) ScrollLock=1; else ScrollLock=0;
if(led & 0x02) NumLock=1;    else NumLock=0;
if(led & 0x04) CapsLock=1;   else CapsLock=0;

oder kürzer (ternäres if):

ScrollLock = (led & 0x01) ? 1 : 0;
NumLock    = (led & 0x02) ? 1 : 0;
CapsLock   = (led & 0x04) ? 1 : 0;

Damit erleichterst du es dem Compiler außerdem, guten Code zu erzeugen.

Gruß,
Svenska

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #28 am: 13. October 2013, 14:57 »
oder kürzer (ternäres if):

ScrollLock = (led & 0x01) ? 1 : 0;
NumLock    = (led & 0x02) ? 1 : 0;
CapsLock   = (led & 0x04) ? 1 : 0;
Das ist immer noch unnötig kompliziert. Das hier reicht, weil die Variablen ja bools sind:
ScrollLock = led & 0x01;
NumLock    = led & 0x02;
CapsLock   = led & 0x04;
Wenn man ints dafür missbrauchen würde und trotzdem immer 0/1 als Ergebnis haben wollte, könnte man auch !!(led & 0x01) benutzen.


Quizfrage noch für lolxdfly: Welche Anweisungen in folgender Zeile sind bedingt und welche nicht?
if(led == 7) CapsLock=1; NumLock=1; ScrollLock=1;
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #29 am: 13. October 2013, 15:21 »
Quizfrage noch für lolxdfly: Welche Anweisungen in folgender Zeile sind bedingt und welche nicht?
if(led == 7) CapsLock=1; NumLock=1; ScrollLock=1;
hmm ich glaube es geht nur bis zum ersten Semikolon  :-D also hört es nach CapsLock=1; und NumLock=1; ScrollLock=1; sind nicht mehr bedingt... (mist)

War das jetzt richtig, dass ich mit outb(0x60, 0xED) den LED-Zustand setzte und dann mit inb(0x60) den LED-Status auslese?
Oder soll ich alle LEDs aus machen und dann den Scancode für die Tasten abscannen, die die LED-Status ändern können?
« Letzte Änderung: 13. October 2013, 15:23 von lolxdfly »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #30 am: 14. October 2013, 00:40 »
Frage:
War das jetzt richtig, dass ich mit outb(0x60, 0xED) den LED-Zustand setzte und dann mit inb(0x60) den LED-Status auslese?
Antwort:
Der Tastaturbefehl 0xED setzt den LED-Zustand. Lesen kannst du ihn damit nicht.

 :evil:

Das ist immer noch unnötig kompliziert. Das hier reicht, weil die Variablen ja bools sind:
ScrollLock = led & 0x01;
NumLock    = led & 0x02;
CapsLock   = led & 0x04;
Stimmt natürlich, allerdings sind die Variablen dann nicht mehr 0 oder 1. Aus !!(led & 0x01) sollte der Compiler aber den gleichen Code generieren wie aus (led & 0x01) ? 1 : 0.

Gruß,
Svenska

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #31 am: 14. October 2013, 09:59 »
Stimmt, sie sind nicht 0 oder 1, sondern true oder false (wie vorher auch, waren ja auch bei dir schon bools). Was in einen Integer gecastet aber 0 oder 1 gibt und nicht irgendwelche anderen Zahlen, insofern ist das praktisch gesehen das gleiche.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #32 am: 21. January 2014, 17:32 »
Hallo,
innerhalb meiner "Pause" in der Kernelentwicklung habe ich viele neue Erfahrungen gewonnen, mitdessen Hilfe ich jetzt den KeyboardTreiber fertig gekommen habe. Er funktioniert auch fast fehlerfrei (kernel crash, wenn ein 'd' im Input gelesen wird). Damit funktioniert endlich das Login meines Kernels  :lol:

Da ich alles was mit Grafik und Maus zutun hat erstmal auf später verschoben habe, wollte ich jetzt erst einmal alles was mit Interrupts zutun hat zum laufen bekommen.
Ersteinmal muss ich sagen, dass dieses http://www.lowlevel.eu/wiki/PIC_Tutorial echt gut erklärt ist. Ich hab zum ersten mal alles verstanden, was auf der Seite stand.  :-D
Mein Problem ist das implementieren der Interrupt Service Routine. Da ich noch fast keine ASM-Erfahrungen habe fällt es mir schwer den ASM-Teil zu codieren.

Wenn man nach dem hier vorgeht http://www.lowlevel.eu/wiki/Teil_5_-_Interrupts muss man "nur" die Descriptor Tables implementieren. Vom ISR wird hier nichts gesagt :/
Oder sind das 2 verschieden Sachen?

lolxdfly

EDIT: der crash wenn ich das 'd' drücke habe ich behoben!! Bei den Interrups bin ich nix weiter...

EDIT2: Bin jetzt mit dem GDT angefangen. Sooo schwer ist das ja gar nicht. Überseh ich was oder geht aus dem TuT nicht hervor, welche Größe GDT_ENTRIES haben muss?
« Letzte Änderung: 06. February 2014, 21:33 von lolxdfly »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #33 am: 21. January 2014, 20:05 »
Die Adresse des Interrupthandlers ist Teil des Eintrags in der IDT, du kommst also nicht drum herum. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #34 am: 06. February 2014, 21:33 »
Hallo,
das GTD gibt mir zwei Compile Error:
Zitat
expected primary-expression before '.' token

Eigentlich ist relativ klar was da falsch gelaufen ist, aber der Fix der gehen sollte geht nicht:
struct __TEST {
    uint16_t limit;
    void* pointer;
} __attribute__((packed)) gdtp = {
    __TEST.limit = GDT_ENTRIES * 8 - 1,
    __TEST.pointer = gdt,
};
(Ich musste den anonymous struckt in einen normel umformen da dies sonst bei c++ probleme machen würde: non-local '<anonymous struct> gdtp' vairable uses anonymus types.)

Oder hab ich irgendwas anderes falsch gemacht?  :?

lolxdfly

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #35 am: 06. February 2014, 21:44 »
Initialisierung von structs funktioniert nur in C, nicht in C++. Der Fix sollte vermutlich eher so aussehen:

struct gdt_pointer {
    uint16_t limit;
    void* pointer;
} __attribute__((packed));

gdt_pointer gdtp;

gdtp.limit = GDT_ENTRIES * 8 - 1;
gdtp.pointer = gdt;
Dieser Text wird unter jedem Beitrag angezeigt.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #36 am: 06. May 2014, 13:58 »
Initialisierung von structs funktioniert nur in C, nicht in C++. Der Fix sollte vermutlich eher so aussehen:

struct gdt_pointer {
    uint16_t limit;
    void* pointer;
} __attribute__((packed));

gdt_pointer gdtp;

gdtp.limit = GDT_ENTRIES * 8 - 1;
gdtp.pointer = gdt;

Auch diese Version geht nicht... aber das ist mittlerweile egal. Habs selber hinbekommen  :wink:

Ich hab quasi von neu angefangen und and das meiste selber im eigenen Stiel gemacht. Mag sein, dass ich jz die Verbesserungen von C++ gegüber C nicht ganz ausnutze, aber das spielt ja denke ich keine große Rolle. Es läuft jetzt endlich das ganze GDT, IDT, IRQs und PIT Krams.
Im mom. bin ich beim Paging angelangt...

Ich habe vor den Codeaufbau wie er hier (http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html) beschrieben ist als Beispiel zu nehmen. Ich bekomme nur eine undefenierte Referenz zu der panic Funktion...

#define PANIC(msg) (panic(msg, __FILE__, __LINE__)) //undefined reference to panic(....

extern void panic(const char *message, const char *file, uint32_t line);

Auch wenn panic als extern "C" void deklariert ist gibt es den linking error ;/

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #37 am: 06. May 2014, 14:03 »
Wenn ich die ganz blöde Frage stellen darf: Hast du nur den panic()-Prototypen oder auch wirklich eine Implementierung dafür? Und falls ja, wird die Implementierung auch mitgelinkt?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #38 am: 06. May 2014, 14:11 »
Wenn ich die ganz blöde Frage stellen darf: Hast du nur den panic()-Prototypen oder auch wirklich eine Implementierung dafür? Und falls ja, wird die Implementierung auch mitgelinkt?
Ja ich habe auch eine fertige Funktion in der .cpp and ja die .o wird mitgelinkt!
extern void panic(char *message, char *file, uint32_t line)
{
    asm volatile("cli"); // Disable interrupts.

    video_write("PANIC(", COLOR_BLACK, COLOR_RED);
    video_write(message, COLOR_BLACK, COLOR_RED);
    video_write(") at ", COLOR_BLACK, COLOR_RED);
    video_write(file, COLOR_BLACK, COLOR_RED);
    video_write(":", COLOR_BLACK, COLOR_RED);
    video_write_dec(line, COLOR_BLACK, COLOR_LIGHT_GRAY);
    video_write("\n", COLOR_BLACK, COLOR_LIGHT_GRAY);
    // Halt by going into an infinite loop.
    for(;;);
}

PS: Erlich gesagt habe ich keine Ahnung warum die Funktion hier als extern deklariert wurde, aber in dem TuT war es genauso und wenn man sie "normal" deklariert ändert das nichts am Error :/

EDIT: Habs X_X... dummer Fehler:

in .h: void panic(const char *message, const char *file, uint32_t line);
in .cpp: void panic(char *message, char *file, uint32_t line);

EDIT2:Ok.. wie ich es schon befürchtet hatte crasht es wenn ich Paging aktiviere...
im Qemu Log taucht folgendes auf:
Zitat
check_exception old: 0xffffffff new 0xe
check_exception old: 0xe new 0xe
Im ObjDump gibt es kein
Zitat
00102c17
!!!

EDIT3:Habs gefunden, nicht gefixt :/
Ist genauso wie hier: nur mit 10187e: http://www.lowlevel.eu/wiki/Teil_9_-_Paging#Paging_aktivieren

EDIT4: Dürfte am link script liegen... die Adresse ist ein externes Symbl aus dem Link Script:
  end = .; _end = .; __end = .;soll ich dass einfach ans Ende dranklatschen? Hab leider überhaupt keine Ahnung was Link Scripte angeht :S
« Letzte Änderung: 06. May 2014, 20:41 von lolxdfly »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #39 am: 06. May 2014, 20:53 »
EDIT3:Habs gefunden, nicht gefixt :/
Ist genauso wie hier: nur mit 10187e: http://www.lowlevel.eu/wiki/Teil_9_-_Paging#Paging_aktivieren

EDIT4: Dürfte am link script liegen... die Adresse ist ein externes Symbl aus dem Link Script:
  end = .; _end = .; __end = .;soll ich dass einfach ans Ende dranklatschen? Hab leider überhaupt keine Ahnung was Link Scripte angeht :S
Das verstehe ich nicht. Ist an der Adresse 10187e das Symbol "end"?
Dieser Text wird unter jedem Beitrag angezeigt.

 

Einloggen