Serielle Schnittstelle, FD_ISSET(fd, &input_fdset) == 0 !?
-
hi,
kann jemand mir sagen, wo fehler ist?
Ich verwende das Programm mit den Einstellungen von Martin Gräfe(3.Auflage, C und Linux).
Das Programm arbeitet nicht richtig und die Daten kann nicht nach STDOUT ausgegeben werden(da if ( FD_ISSET(fd, &input_fdset) ) // <-- hier: fd_isset==0 !!?? ist). Ich habe schon mehrmals versucht und weiß ich immer nicht, wo falsch eingestellt ist(sind).
Den Vorschlag von Marin G aus Forum, der Beitrag am 16:51:55 29.01.2007 habe ich auch versucht und trotzdem es funktioniert nicht.
wo fehler ist?
Ich arbeite unter SUSE10.0 VM.
Dank im Voraus
/*terminal.c - Ein- und Ausgabe ueber die serielle Schnittstelle */ //# include <asm/uaccess.h> # include <string.h> # include <stdio.h> # include <unistd.h> # include <fcntl.h> # include <termios.h> # define TERM_DEVICE "/dev/ttyS0" /* = COM1 */ # define TERM_SPEED B57600 /* Bit/Sek */ int main() { int fd, old_flags; ssize_t length; char buffer[16]; struct termios term_attr; fd_set input_fdset; if ((fd = open(TERM_DEVICE, O_RDWR)) == -1) { perror("terminal: Can't open device " TERM_DEVICE); return(1); } /* RS232 konfigurieren */ if (tcgetattr(fd, &term_attr) != 0) { perror("terminal: tcgetattr() failed"); return(1); } term_attr.c_cflag = TERM_SPEED | CS8 | CRTSCTS | CLOCAL |CREAD; term_attr.c_iflag = 0; term_attr.c_oflag = OPOST | ONLCR; term_attr.c_lflag = 0; cfsetospeed(&term_attr,TERM_SPEED); cfsetispeed(&term_attr,TERM_SPEED); if (tcsetattr(fd, TCSAFLUSH, &term_attr) != 0) perror("terminal: tcsetattr() failed"); /* Std.-Eingabe anpassen */ if (tcgetattr(STDIN_FILENO, &term_attr) != 0) { perror("terminal: tcgetattr() failed"); return(1); } else { term_attr.c_cflag &= ~(CBAUD | CSIZE); // bits loeschen term_attr.c_cflag |= TERM_SPEED | CS8; // neu einstellen tcsetattr(fd, TCSAFLUSH, &term_attr); } /* alte Einst. sichern */ old_flags = term_attr.c_lflag; term_attr.c_lflag &= ~(ICANON | ECHO); if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr) != 0) perror("terminal: tcsetattr() failed"); while (1) { FD_ZERO(&input_fdset); FD_SET(STDIN_FILENO, &input_fdset); FD_SET(fd, &input_fdset); // <-- hier: fd_set ! if (select(fd+1, &input_fdset,NULL,NULL,NULL) == -1) perror("terminal: select() failed"); if (FD_ISSET(STDIN_FILENO, &input_fdset) ) { if ((length = read(STDIN_FILENO, buffer, 16)) == -1) perror("terminal: read() failed"); else if (buffer[0] == '\33') // Abbruch mit ESC break; else write(fd, buffer, length); } if ( FD_ISSET(fd, &input_fdset) ) // <-- hier: fd_isset==0 !!?? { if ((length = read(fd, buffer, 16)) == -1) perror("terminal: read() failed"); else { write(STDOUT_FILENO,buffer,length); } } } /* Std.-Eingabe wie vorher */ term_attr.c_lflag = old_flags; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr) != 0) perror("terminal: tcsetattr() failed"); printf("Aborted.\n"); close(fd); return(0); }
<edit=ruediger>BITTE Syntax Highlight verwenden!
sfds
</edit>
-
Genaueres Problem:
Das Programm kann ein Zeichen von der Tastatur (STDIN_FILENO) mit read lesen und kann auch in die serielle Schnittstelle (fd) mit write schreiben, das heißt der "if(FD_ISSET(STDIN_FILENO, &input_fdset) )"-Block funktioniert.
Aber das gelesene Zeichen kann nicht auf SDTOUT_FILENO ausgeben werden, das Programm springt nicht in den "if(FD_ISSET(fd, &input_fdset))"-Block.
Das select(...) entfernt das Element von fd aus der Menge &input_fdset, wie ich anhand von Kontrollausgaben verifizieren konnte.
Rufe ich FD_SET(fd,&input_fdset)) nach dem select-Aufruf nochmals auf, dann springt das Programm zwar in den "if(FD_ISSET(df, &input_fdset) )"-Block, das Zeichen wird also von der Tastatur gelesen und in die Schnittstelle geschrieben, und anschließend in den "if(FD_ISSET(fd, &input_fdset) )"-Block, bleibt aber offensichtlich in der Funktion read(fd,...) hängen.
Habe ich falsche Einstellungen oder Optionen im Programm? Falls ja, wo und welche?
Ich habe auch schon versucht, open() mit dem optionalen Zugriffsrechtparameter 0666(Lese- und Schreibrechte) aufzurufen (unter vorangegangenem umask(0)).
Ich habe außerdem versucht, das Programm als Superuser root zu starten.
Das Ergebnis ist aber immer dasselbe: es funktioniert nicht.
Kann jemand mir einen Rat geben?
Vielen Dank