/*27.07.1999 : cfsetspeed durch cfsetispeed und cfsetospeed ersetz, weil 
               cfsetspeed nicht POSIX-kompatibel ist. Gibt es z. B. nicht
               unter Solaris.
               Programmtext gereinigt.
  24.07.1999 : init_dmm liest nun zur Probe einen Meßwert und liefert -1 bei
               Fehlern. Das war nötig, weil der erste Wert nicht richtig 
               gelesen wird, es fehlte manchmal die letzte Stelle der Einheit. 
               Übertragungsgeschwindigkeit 9660 Baud ergänzt.

  13.06.1999 : Übertragungsgeschwindigkeit als Parameter von init_dmm 
               eingefügt.
  
  Erstellt im Mai 1999 */


#include <fcntl.h>
#include <sys/termios.h>
#include <sys/ioctl.h>
#include <stdio.h>

int init_dmm(const char * device, int speed) /* Funktion zum Initialisieren 
                                                und Öffnen des Ports/Devices*/
{                                        
  int fd,m;
  char test[14];
  int modelines=0;
  struct termios settings;
  char baudrate[6];


/*Öffnen und Überprüfen des Filedeskriptors*/
  fd=open(device,O_RDWR|O_NOCTTY);
  if(fd==-1)
    {
      fprintf(stderr,"Das Device %s kann nicht geöffnet werden!\n",device);
      return(fd);
    }


/*Prüfe ob Filedeskriptor zu einem Terminal gehört*/
  if(!isatty(fd))
    {
      fprintf(stderr,"Das Device %s ist kein Terminal-Device !\n",device);
      return(-1);
    }
  

/*Setzen der Inputflags*/
  settings.c_iflag=   IGNBRK  /*Ignoriere BREAKS beim Input*/
                    | IGNPAR; /*Keine Parität*/


/*Setzen der Outputflags*/
  settings.c_oflag=0;         /*Keine besonderen Angaben nötig*/


/*Setzen der Controlflags*/
  settings.c_cflag= CS7       /*Setze sieben Bit pro Byte*/
                  | CSTOPB    /*Zwei Stopbits*/
                  | CREAD     /*Zeichen können von gelesen werden*/
                  | CLOCAL ;  /*Ignoriere Modemstatus, lokaler Anschluß*/

/*Setzen der lokalen Flags*/
  settings.c_lflag=0;         /*Keine besonderen Angaben nötig*/  


/*Festlegen der minimalen Anzahl der zu lesenden Bytes -> Fall 3*/
  settings.c_cc[VMIN]=0;

  
/*Setzen der Übertragungsgeschwindigkeit */
  switch (speed) {
    case 9600: /* 9600 Bit/s */
              settings.c_cc[VTIME]=10;  
              if(cfsetispeed(&settings,B9600)!=0) 
                {
                  fprintf(stderr,"Fehler beim Setzen der ");
                  fprintf(stderr,"Übertragungsgeschwindigkeit auf %s !\n"
                          ,device);
                  return(-1);
                }
                if(cfsetospeed(&settings,B9600)!=0) 
                {
                  fprintf(stderr,"Fehler beim Setzen der ");
                  fprintf(stderr,"Übertragungsgeschwindigkeit auf %s !\n"
                          ,device);
                  return(-1);
                }
              break;

    case 1200: /*1200 Bit/s */
              settings.c_cc[VTIME]=10;
              if(cfsetispeed(&settings,B1200)!=0) 
                {
                  fprintf(stderr,"Fehler beim Setzen der ");
                  fprintf(stderr,"Übertragungsgeschwindigkeit auf %s !\n"
                          ,device);
                  return(-1);
                }
                if(cfsetospeed(&settings,B1200)!=0) 
                {
                  fprintf(stderr,"Fehler beim Setzen der ");
                  fprintf(stderr,"Übertragungsgeschwindigkeit auf %s !\n"
                          ,device);
                  return(-1);
                }
              break;

    case  600: /* 600 Bit/s */
              settings.c_cc[VTIME]=30;  
              if(cfsetispeed(&settings,B600)!=0) 
                {
                  fprintf(stderr,"Fehler beim Setzen der ");
                  fprintf(stderr,"Übertragungsgeschwindigkeit auf %s !\n"
                          ,device);
                  return(-1);
                }
                if(cfsetospeed(&settings,B600)!=0) 
                {
                  fprintf(stderr,"Fehler beim Setzen der ");
                  fprintf(stderr,"Übertragungsgeschwindigkeit auf %s !\n"
                          ,device);
                  return(-1);
                }       
              break;
   default   : fprintf(stderr,"Unbekannte Übertragungsgeschwindigkeit : %d\n",
                       speed);
               fprintf(stderr,"Erlaubte Werte: 600, 1200, 9600 \n");
               return(-1);
               break;  
  }

/*Übertragung der Einstellungen an die Schnittstelle*/
  if(tcsetattr(fd,TCSANOW,&settings)==-1)
    {
      fprintf(stderr,"Fehler beim Setzen der Terminalattribute auf  %s !\n"
              ,device);
      return(-1);
    }


/*Lesen der IO-Control-Parameter*/
  if(ioctl(fd,TIOCMGET,&modelines)==-1)
    {
      fprintf(stderr,"Fehler bei ioctl TIOCMGET auf  %s!\n",device);
      return(-1);
    }


/*Setzen des RTS-Signals*/
  modelines &= ~TIOCM_RTS;
  if(ioctl(fd,TIOCMSET,&modelines)==-1) 
    {
      fprintf(stderr,"Fehler bei ioctl TIOCMSET auf %s !\n",device); 
      return(-1);
    }


/*Testen des Ports und der Kommunimation durch Lesen eines Meßwertes*/
  if (read_dmmd(fd,test)==-1)
     {
      fprintf(stderr,"Fehler bei der Kommunikation mit dem "); 
      fprintf(stderr,"Meßgerät an Port %s !\n",device);
      fprintf(stderr,"Ist das Meßgerät angeschlossen ? First\n");
      return(-1);
     }
     else{
      fprintf(stdout,"%s\n",test);
     }
  for(m=1;m<4;m++){
  if (read_dmm(fd,test)==-1)
     {
      fprintf(stderr,"Fehler bei der Kommunikation mit dem "); 
      fprintf(stderr,"Meßgerät an Port %s !\n",device);
      fprintf(stderr,"Ist das Meßgerät angeschlossen %d?\n",m);
      return(-1);
     }
     else{
      fprintf(stdout,"%s\n",test);
     }
  }
  sleep(2);
  return(fd);
} 



int read_dmmd(int fd,char buf[14]) /* Funktion zum Lesen eines Meßwertes */
{
  int i,k;
  int nbyte;
    write(fd,"D\n",2); /*Schicke ein D ans Meßgerät*/
    i=-1;
    do{
       i++;
       nbyte=read(fd,&buf[i],1); /*Lies ein Zeichen*/
       if(nbyte!=1){             /*Gibt es kein Zeichen -> TIMEOUT*/
         fprintf(stderr,"TIMEOUT !\n");
         return (-1);
       }
    }
    while (((buf[i]!='\r')&&(nbyte==1))||(i<13));  /*Lies insgesamt 14 Zeichen*/
  return(1);
}


int read_dmm(int fd,char buf[14]) /* Funktion zum Lesen eines Meßwertes */
{
  int i,k;
  int nbyte;
/*    write(fd,"D\n",2); /*Schicke ein D ans Meßgerät*/
    i=-1;
    do{
       i++;
       nbyte=read(fd,&buf[i],1); /*Lies ein Zeichen*/
       if(nbyte!=1){             /*Gibt es kein Zeichen -> TIMEOUT*/
         fprintf(stderr,"TIMEOUT !\n");
         return (-1);
       }
    }
    while (((buf[i]!='\r')&&(nbyte==1))||(i<13));  /*Lies insgesamt 14 Zeichen*/
  return(1);
}


int close_dmm(int fd) /*Funktion zum Schließen des Devices*/
{
  return(close(fd));
}
