cteni ze serioveho portu (LONG)

Zdenek Pizl, Czech Agriculture University, Prague pizl na max.af.czu.cz
Středa Duben 7 09:11:48 CEST 1999


On Wed, 7 Apr 1999 bravenec na optimit.cz wrote:

> > 
> >   - kdyz mi po drate prijde 2048 B dlouha message, tak ja ji budu nacitat v
> >  cyklu po 16 B ?? to mi prijde jako hodne nehospodarne co se tyce casu
> >  procesoru a jeho zateze.
> > 
> >   - jak mam cist min casto, ja to potrebuju nacist najednou, vzdyt nevim
> >  kdy mi prijde dalsi SIGIO a dalsi data !!!
> > 
> 
> Ach takto!
> Ale to je hluboke, hluboke nedorozumneni!
> Kernel nijak nepozna, ze zprava, ktera prichazi ze serioveho portu, je
> dlouha

jo, to je mi jasne. Ja z podstaty problemu vim, ze ta zprava NIKDY nebude
delsi nez 2048 bytu. tak jsem predpokladal, ze by mi melo stacit udelat
	count=read(serial_deskriptor,buffer,2049); 
a nacist vsechno co prislo na port.

> 2 KB. Kernelu je to jedno. V momente, kdy se snazite cist data, kernel
> vam 

tady si trosku nerozumime. ja to nectu dvakrat ! ale kernel mi dvakrat
vyvola SIGIO - protoze krome toho cteni ten program jeste obhospodaruje
menu, buttonky, listboxy a podobna svinstva v NCURSES - a tak to musi byt
asynchronni cteni. na testovani jsem si poridil null modem a napsal
stupidni program, kterym posilam na ttyS1 nejaklej retezec a z ttyS0 si ho
zase ctu (nebo alespon chci cist :-(( )

ten zapisovaci progeam vypada nasledovne: (o bezpecnosti nebudeme mluvit)

 ---- cut here ----

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>


int main(int argc, char **argv)
{
    int fd;
    int cont=1;
    int a;
    char buffer[1024];

    fd=open("/dev/ttyS1",O_RDWR);
    if(fd<0)
    {
        printf("hmm, nejde otevrit port ttyS1 !\n");
        exit(1);
    }
    else
    {
        while(cont)
        {
            printf("message : ");
            gets(buffer);
            if(strcmp(buffer,"xXx")!=0)
            {
                strcat(buffer,"\n");
                a=write(fd,buffer,strlen(buffer));
                printf("%d , %d\n\n",a,strlen(buffer));
            }
            else
            {
                cont=0;
            }    
        }
    }
}

 ---- cut here ----


a ten cteci kus programu je nasledovny :

 ---- cut here ----

#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <string.h>

#include "serial_reader.hh"
#include "util.hh"
#include "widget.hh"
#include "listbox.hh"

volatile int STOP=FALSE;

int serial_data_flag=FALSE;
struct termios oldtio;
int serial_deskriptor=-1;

// par globalnich promenny - widgetu
extern ListBox *listbox;

void signal_handler_IO (int status)
{
    int oldmask,mymask;
    int count,totcount;
    char buffer[2049];
    char *pom;

    pom=buffer;
    

    mymask= sigmask(SIGQUIT) | sigmask(SIGINT) ;
    oldmask=sigblock(mymask); 
    // ulozime starou a nastavime novou masku blokovanych signalu

    // tady zpracujeme prisla data
    count=totcount=0;
    memset(buffer,0x00,2049); // vynulujeme cely string
    count=read(serial_deskriptor,pom,1023);
    while(count>0)
   {
        totcount+=count;
        pom+=count;
        count=read(serial_deskriptor,pom,1023-totcount);
    }


    //    tcflush(serial_deskriptor,TCIFLUSH);
    
    *(buffer+totcount-1)=0x00; // urizneme string
    killwhitespaces(buffer);
    listbox->add_item(LISTBOX_APPEND_AT_END, 0, buffer, NULL);
    listbox->send_message(WIDGET_DRAW, 0);

    // konec zpracovani
    signal(SIGIO,signal_handler_IO);
    sigsetmask(oldmask); //nastavime puvodni masku blok. signalu
}


// funkce, ktera nastavi handler a port k asynchronnimu cteni
void set_serial_handler()
{
    int c, res;
    struct termios oldtio,newtio;
    struct sigaction saio;           /* definice akce pro signal*/

    /* open the device to be non-blocking (read will return immediatly) */
    serial_deskriptor = open(INPUTDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (serial_deskriptor <0) {perror(INPUTDEVICE); exit(-1); }

    //install the signal handler before making the device asynchronous
    signal(SIGIO,signal_handler_IO);

    /* allow the process to receive SIGIO */
    fcntl(serial_deskriptor, F_SETOWN, getpid());

    /* Make the file descriptor asynchronous (the manual page says only
     O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
    fcntl(serial_deskriptor, F_SETFL, FASYNC);

    tcgetattr(serial_deskriptor,&oldtio); /* save current port settings */
    /* set new port settings for canonical input processing */
    cfmakeraw(&newtio);
    cfsetispeed(&newtio, BAUDRATE);

    tcflush(serial_deskriptor, TCIFLUSH);
    tcsetattr(serial_deskriptor,TCSANOW,&newtio);
}

 ---- cut here ----


 jeden z problemu je treba to, ze ackoliv jsem otevrel ten deskriptor jako
neblokujici, tak se mi to pri nekterym volani read zablokuje ....

 dalsim je ten, ze ja implicitne nevim, kolik toho prijde. takze se musim
spolehat na to, ze read je neblokujici a kdyz nema co cist tak vrati nulu,
coz jak uz bylo receno, neni vzdycky pravda .. :-(


			===============================
			"			      "
			"                             "
			"    Zdenek Pizl (Corp. yA)   "
			"			      "
			"      pizl na max.af.czu.cz     "
			"                             "
			===============================



Další informace o konferenci Linux