/*

     GESTION PORT SERIE / TRAMES
     PROTOCOLE TRSII
       Pour dialoguer avec les télétransmissions CLIP / FORCE (Constructeur WIT)
       http://www.wit.fr

     Marc Le Douarain , Décembre 1998
     mavati@club-internet.fr
     http://perso.club-internet.fr/mavati
 
     Dernière mise à jour : 13 mars 1999

*/

void Mem_FreeAll(void);


void Print_Monitor(char *chaine,int lgt,char mode,char direction)
{
 int i;
 char car;
 if (lgt>0)
 {
  if ((mode&2)==2)
  {
   if (direction==MONITOR_IN)
   {
    printf("<");
   }
   if (direction==MONITOR_OUT)
   {
    printf(">");
   }
   i=0;
   {
    do
    {
     printf("%x ",chaine[i]);
     i++;
    }while(i<lgt);
    if (direction>0)
    {
     printf("\n");
    }
   }
  }
  if ((mode==0)||(mode==1)||(mode==3))
  {
   if (direction==MONITOR_IN)
   {
    printf("<");
   }
   if (direction==MONITOR_OUT)
   {
    printf(">");
   }
   i=0;
   do
   {
    car=chaine[i];
    switch(car)
    {
     case 9:
      printf("[TAB]");
      break;
     case 13:
      printf("[CR]");
      break;
     case 10:
      printf("[LF]");
      break;
     case 27:
      printf("[ESC]");
      break;
     case 0:
      printf("[NULL]");
      break;
     default:
      printf("%c",car);
    }
    i++;
   }while(i<lgt);
   if (direction>0)
   {
    printf("\n");
   }
  }
 }
}

void Serial_CloseAll(void)
{
 if (MoniteurActif)
  printf("Fermeture du port série\n");
 if (SerialInitOk)
  CloseDevice((struct IORequest *)SerialIO);
 if (IncomingIO)
  DeleteExtIO((struct IORequest *)IncomingIO);
 if (SerialIO)
  DeleteExtIO((struct IORequest *)SerialIO);
 if (SerialMP)
  DeletePort(SerialMP);
 #ifdef GENERATE_GUI
 if (App)
 {
  DisposeApp(App);
  App=NULL;
  CloseLibrary(MUIMasterBase);
 }
 #endif
 Mem_FreeAll();
}

void Serial_OpenAll(void)
{ 
 int Erreur;
 char MessageErreur[255];
 if (MoniteurActif)
  printf("Ouverture du port série\n");
 if ((SerialMP = (struct MsgPort *) CreatePort(0, 0)) == NULL)
 {
  ErrorMessageRequest("Can't create message port");
  Serial_CloseAll();
  exit(30);
 }
 else
 {
  if ((SerialIO = (struct IOExtSer *) CreateExtIO(SerialMP, sizeof(struct IOExtSer))) == NULL)
  {
   ErrorMessageRequest("Can't allocate storage for ExtIO");
   Serial_CloseAll();
   exit(30);
  }
  else
  {
   if ((IncomingIO = (struct IOExtSer *) CreateExtIO(SerialMP, sizeof(struct IOExtSer))) == NULL)
   {
    ErrorMessageRequest("Can't allocate storage for ExtIO");
    Serial_CloseAll();
    exit(30);
   }
   else
   {
    Erreur=OpenDevice(SerialDevice, (long) SerialUnit, (struct IORequest *) SerialIO, 0L);
    if (Erreur!=0)
    {
     sprintf(MessageErreur,"Can't open device '%s',unit:%d",SerialDevice,SerialUnit);
     ErrorMessageRequest(MessageErreur);
     Serial_CloseAll();
     exit(30);
    }
    else
    {
     SerialInitOk=True;
     SerialIO->io_SerFlags = SERF_SHARED|SERF_PARTY_ON;
     SerialIO->io_ReadLen=7;
     SerialIO->io_WriteLen=7;
     SerialIO->io_StopBits=1;
     SerialIO->io_Baud=SerialSpeed;
     SerialIO->IOSer.io_Command = SDCMD_SETPARAMS;
     if (DoIO((struct IORequest *)SerialIO) != NULL)
     {
      ErrorMessageRequest("Unable to set serial params");
      Serial_CloseAll();
      exit(30);
     }
     else
     {
      memcpy(IncomingIO, SerialIO, sizeof(struct IOExtSer));
     }
    }
   }
  }
 }
}

void Serial_Write(struct IOExtSer *Ser_IO, char *Data,int Lgt)
{
 int ErrorNbr;
 char MessageErreur[255];
 Ser_IO->IOSer.io_Command = CMD_WRITE;
 Ser_IO->IOSer.io_Length = Lgt;
 Ser_IO->IOSer.io_Data = (APTR) Data;
 ErrorNbr=DoIO((struct IORequest *)Ser_IO);
 if (ErrorNbr != NULL)
 {
  sprintf(MessageErreur,"Serial write failed, error:%d",ErrorNbr);
  ErrorMessageRequest(MessageErreur);
  Serial_CloseAll();
  exit(30);
 }
 if (MoniteurActif)
 {
  Print_Monitor(Data,Lgt,MoniteurMode,MONITOR_OUT);
 }
}

int Serial_Read(struct IOExtSer *Ser_IO, APTR Data)
{
 int length;
 int ErrorNbr;
 char MessageErreur[255];
 IncomingIO->IOSer.io_Command = SDCMD_QUERY;
 IncomingIO->IOSer.io_Actual = 0;
 if (DoIO((struct IORequest *)IncomingIO) != NULL)
 {
  ErrorMessageRequest("Serial SDCMD_QUERY failed");
  Serial_CloseAll();
  exit(30);
  }
  if ((length = IncomingIO->IOSer.io_Actual) > 0)
  {
   IncomingIO->IOSer.io_Command = CMD_READ;
   IncomingIO->IOSer.io_Length = length;
   IncomingIO->IOSer.io_Data = Data;
   ErrorNbr=DoIO((struct IORequest *)IncomingIO);
   if ( ErrorNbr!= NULL)
   {
    /* Erreur de parité ? */
    if (ErrorNbr==9)
    {
     length=0;
    }
    else
    {
     sprintf(MessageErreur,"Serial read failed, error:%d",ErrorNbr);
     ErrorMessageRequest(MessageErreur);
     Serial_CloseAll();
     exit(30);
    }
   }
   return length;
 }
}

/* Get number of seconds from clock */
ULONG get_timer_secs(void)
{
  unsigned long secondes;
  unsigned long microsecs;
  CurrentTime(&secondes,&microsecs);
  return secondes;
}


/* Making the complete frame when calling this function many times
   Back: "True" if frame is complete.
   --------------------------------------------------------------
   DetecEOT      : caractere to indicate the end of the frame
   MemoStartTime : pointer on the start time (Back: write NULL if 'TimeOut' detected)
   Data          : pointer on the string to complete
   NbrCarac      : pointer on the number of caracters of the string received actually
   TimeOut       : nbr of seconds maxi before end of frame
*/
int Serial_StringCompose(char DetecEOT,char *Data,int *NbrCarac,unsigned long *MemoStartTime,int TimeOut)
{
 char DataTemp[5000];
 int NbrCaracTemp;
 char EOTfound=False; 
 /* Récupération de la trame au fur et à mesure (fonction non-bloquante) */
 NbrCaracTemp=Serial_Read(SerialIO,DataTemp);
 if (NbrCaracTemp>0)
 {
  strcpy_limited(Data+*NbrCarac,DataTemp,NbrCaracTemp);
  *NbrCarac=*NbrCarac+NbrCaracTemp;
  /* Détection de la fin de trame */
  if (Data[(*NbrCarac)-1]==DetecEOT)
  {
   if (MoniteurActif)
   {
    Print_Monitor(Data,*NbrCarac,MoniteurMode,MONITOR_IN);
   }
   EOTfound=True;
  }
 }
 /* Verifying the Time-Out if used */
 if (MemoStartTime!=NULL)
 {
  if ((get_timer_secs()-*MemoStartTime)>TimeOut)
  {
   *MemoStartTime=NULL;
   if (MoniteurActif)
    printf("Erreur:TimeOut in StringCompose!\n");
  }
 }
 return EOTfound;
}

/* ############################### */
/* # Initialization of the modem # */
/* ############################### */
int init_modem(char *InitString)
{
 int InitOk=False;
 char TrameToModem[64];
 char TrameFmModem[256];
 int LgtTrameFmModem;
 int TrameComplete;
 unsigned long MemoTime;
 int nbratt;
 /* Send standart string 'ATZ' */
 strcpy(TrameToModem,"ATZ\r");
 Serial_Write(SerialIO,TrameToModem,4);
 MemoTime=get_timer_secs();
 nbratt=3;
 do
 {
  LgtTrameFmModem=0;
  do
  {
   TrameComplete=Serial_StringCompose(10,TrameFmModem,&LgtTrameFmModem,&MemoTime,5);
   Delay(5);
  }
  while ((TrameComplete!=True)&&(MemoTime!=NULL));
  if (MemoTime!=NULL)
  {
   if (str_pos(TrameFmModem,LgtTrameFmModem,"OK",2)==NULL)
   {
    nbratt--;
   }
   else
   {
    InitOk=True;
   }
  }
 }
 while((InitOk!=True)&&(MemoTime!=NULL)&&(nbratt>0));

 /* Send configuration string */
 if ( (InitOk)&&(strlen(InitString)>0) )
 {
  InitOk=False;
  strcpy(TrameToModem,InitString);
  strcpy(TrameToModem+strlen(InitString),"\r");
  Serial_Write(SerialIO,TrameToModem,strlen(InitString)+1);
  MemoTime=get_timer_secs();
  nbratt=3;
  do
  {
   LgtTrameFmModem=0;
   do
   {
    TrameComplete=Serial_StringCompose(10,TrameFmModem,&LgtTrameFmModem,&MemoTime,5);
    Delay(5);
   }
   while ((TrameComplete!=True)&&(MemoTime!=NULL));
   if (MemoTime!=NULL)
   {
    if (str_pos(TrameFmModem,LgtTrameFmModem,"OK",2)==NULL)
    {
     nbratt--;
    }
    else
    {
     InitOk=True;
    }
   }
  }while((InitOk!=True)&&(MemoTime!=NULL)&&(nbratt>0));
 }
 return InitOk;
} 

/* ################################################# */
/* # Calling and waiting connection with the modem # */
/* # Return : FALSE => under call                  # */
/* #          TRUE => call succesfull              # */
/* #          2 => Error 'TIME-OUT !'              # */
/* #          3 => Error 'BUSY'                    # */
/* ################################################# */
int call_modem(char *NumTel,int FirstCall)
{
 int ConnectOk=False;
 char TrameToModem[64];
 static char TrameFmModem[256];
 static int LgtTrameFmModem;
 static unsigned long MemoTime;
 int TrameComplete;
 char * StringConnected;
 static char StringMessageSpeed[64];

 /* CALLING THE TELEPHONE NUMBER WITH ATDTxxxxxxx */
 if (FirstCall)
 {
  strcpy(TrameToModem,"ATDT");
  strcpy(TrameToModem+4,NumTel);
  strcpy(TrameToModem+4+strlen(NumTel),"\r");
  Serial_Write(SerialIO,TrameToModem,strlen(TrameToModem));
  MemoTime=get_timer_secs();
  LgtTrameFmModem=0;
 }
 /* WAITING MESSAGE "CONNECT" FROM MODEM */
 TrameComplete=Serial_StringCompose(10,TrameFmModem,&LgtTrameFmModem,&MemoTime,50);
 if (TrameComplete)
 {
  StringConnected=str_pos(TrameFmModem,LgtTrameFmModem,"CONNECT",7);
  if (StringConnected!=NULL)
  {
   ConnectOk=True;
   strcpy(StringMessageSpeed,"Connecté à: ");
   strcpy_termnotnull(StringMessageSpeed+strlen(StringMessageSpeed),StringConnected+8,13,10);
   DisplayStatus(StringMessageSpeed);
  }
  StringConnected=str_pos(TrameFmModem,LgtTrameFmModem,"BUSY",4);
  if (StringConnected!=NULL)
  {
   ConnectOk=3;
  }
  LgtTrameFmModem=0;
 }
 if (MemoTime==NULL)
  ConnectOk=2;
 return ConnectOk;
}

/* ################################################# */
/* # Hanging up the actual connection of the modem # */
/* ################################################# */
void hangup_modem(void)
{
 int i;
 Delay(100);
 Serial_Write(SerialIO,"+++",3);
 Delay(10);
 i=Serial_Read(SerialIO,TrameRecue);
 Delay(150);
 Serial_Write(SerialIO,"ATH0\r",5);
 Delay(10);
 i=Serial_Read(SerialIO,TrameRecue);
 Delay(25);
 Serial_Write(SerialIO,"ATZ\r",4);
 Delay(10);
 i=Serial_Read(SerialIO,TrameRecue);
 Delay(25);
 i=Serial_Read(SerialIO,TrameRecue);
if (MoniteurActif)
printf("-----%d\n",i);
}
