Hi.
Wenn man mit Geräten kommunizieren will, hat man mehrere Möglichkeiten:
- I/O Ports
- Eingeblendeter Speicher
- Interruptaufrufe
- Sonstiges
I/O Ports
Dies sind Busleitungen, die man mit einem Treiber oder einem Anwenderprogramm steuern kann. Ein I/O Port hat eine feste Adresse, auf die man mit outb() schreiben kann. Mit inb() kann man davon lesen. Dazu ein Beispiel:
Code:
#include <sys/io.h>
/* Linux - Braucht root-Rechte */
int
main(int argc, char *argv[])
{
printf("\033[?17;103;16c"); // Blockcursor
ioperm(0x3c8, 8, 1);
outb(0, 0x3c8);
ioperm(0x3c8, 8, 0);
ioperm(0x3c9, 8, 1);
outb(2, 0x3c9);
outb(5, 0x3c9);
outb(10, 0x3c9);
ioperm(0x3c9, 8, 0);
ioperm(0x3c8, 8, 1);
outb(7, 0x3c8);
ioperm(0x3c8, 8, 0);
ioperm(0x3c9, 8, 1);
outb(10, 0x3c9);
outb(40, 0x3c9);
outb(60, 0x3c9);
ioperm(0x3c9, 8, 0);
return 0;
}
Dieses Programm modifiziert die Farbpalette der Grafikkarte, sodaß man im Textmodus beliebige Farben haben kann, nicht nur die vordefinierten 8 Stück + blinkend. Der Port 0x3c8 erwartet eine 8bit Zahl, welche die zu ändernde Farbe in der Palette angibt (0=Schwarz, 7=Weiß), und 0x3c9 danach drei 6bit Zahlen, welche die Rot-, Grün- und Blauanteile angeben.
Wir senden hier erst eine 0 an 0x3c8 (=Ich will Farbe 0 ändern, schwarz) und danach 2, 5 und 10 an 0x3c9. Das ergibt ein zartes blau. Das gleiche machen wir mit Farbe Nr.7, sodaß wir statt weiß am Ende himmelblau haben.
Andere Sachen, die man (unter anderem) so steuern kann, sind z.B. der Parallelport, serielle Ports sowie bestimmte MIDI und Soundkarten.
Eingeblendeter Speicher
Viele Geräte haben Speicher. Grafikkarten sind da ein gutes Beispiel. Die schnellste Methode ist, direkt auf den Speicher zuzugreifen. Deshalb blenden viele Geräte ihren eigenen Speicher in den normalen Arbeitsspeicher ein. In 16bit Umgebungen (DOS) ist das ganz einfach: Der Grafikspeicher beginnt immer bei A000:0000 (Segment/Offset). Wenn man da reinschreibt, hat man irgendwas auf dem Bildschirm. In 32bit Protected Mode Umgebungen (Linux, Windows) liegt der I/O Speicher ganz am Ende des virtuellen Adressraums. Da kommt man dann aber nicht so leicht ran.
Interruptaufrufe
Das kann man sich vorstellen wie einen Funktionsaufruf in C. Der Funktionsname hat dabei eine Nummer, die Argumente übergibt man in Registern.
Code:
xor ah,ah
mov al,0x13
int 0x10
mov ah,0x4c
int 0x21
Dieser Schnipsel (DOS Assembler) ändert die Auflösung der Grafikkarte (Interrupt 0x10). Die Argumente sind:
ah - Nummer der Funktion (xor ah,ah = 0 = Auflösung ändern)
al - Auflösung (indexnummer 0x13 = 320x200 256 Farben)
Danach kommt Interrupt 0x21 (DOS) mit der Funktion 0x4c (Programm Ende).
Die Interruptnummern sind dabei Indizes in einer Tabelle (Interruptvektortabelle). In der Tabelle ist dann die entsprechende Sprungadresse angegeben, an der der auszuführende Code steht. Alle INT 0x10 Funktionen sind z.B. in einem ROM der Grafikkarte gespeichert (genannt VGA BIOS), welches in den Speicher eingeblendet wird.
--
Diese hardwarenahe Programmierung wird unter 32bit Systemen (Linux, Windows, etc.) fast immer in Form von Treibern bereitgestellt. Die Treiber deklarieren dann ihrerseits Funktionen, die Anwenderprogramme aufrufen können, um das gewünschte Ziel zu erreichen. Der Treiber deiner Webcam wird (sofern du Linux benutzt) allerdings auch weniger mit I/O Ports und Interrupts rumspielen, sondern eher die USB API benutzen, die der USB Treiber des Kernels bereitstellt. Die Befehlskette könnte dabei z.B. so aussehen:
Anwenderprogramm ===> Webcam Treiber ===> USB Treiber ===> Hardware
MfG.