Logo Search packages:      
Sourcecode: fbb version File versions  Download package

drv_hst.c

   /****************************************************************
    Copyright (C) 1986-2000 by

    F6FBB - Jean-Paul ROUBELAT
    6, rue George Sand
    31120 - Roquettes - France
      jpr@f6fbb.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Parts of code have been taken from many other softwares.
    Thanks for the help.
    ****************************************************************/

/*
 * PTC-II HostMode interface
 *
 * It has two ports + 1 pactor channel
 *
 * Pactor channel is renumbered to 31, other ports are limited to 30 channels
 */

#include <serv.h>
#include <fbb_drv.h>

/* Caractere de header */
#define HST_CHAR  170
#define PACTOR_ST 254
/* #define DEBUG_HST */

#define STATUS(p) (p_com[(int)p_port[p].ccom].pactor_st)

static char pactor[5];

static int hst_end_host (int);

static int hst_send_data (int);
static int hst_send_dt (int, int, char *, int);
static int hst_send_ui (int, char *, int, Beacon *);
static int hst_sndcmd (int, int, char *, int);
static int nb_waiting (int);
static int recv_hst (int, int, int *, char *);
static int hst_busy (int port, int *canal, int force);

static void hst_get_ui (int, char *, ui_header *);
static void hst_sonde (int, int);
static int hst_compteur (int);

static unsigned short *crctab;

#define updcrc(cp, crc) (((crc >> 8) & 0xff) ^ crctab[((crc ^ (cp & 0xff)) & 0xff)])

static int DebugCh = 0;
static void DebugCmd (int port)
{
      int type = (p_port[port].last->cmd == COMMAND) ? 1 : 0;

      if (DebugCh)
      {
            type |= p_port[port].last->compteur;
      }
}

#ifdef DEBUG_HST

static void dump_data (FILE * fptr, char *ptr, int nb)
{
      int i;
      int j;

      for (i = 0; i < nb; i += 16)
      {
            fprintf (fptr, "%03d ", i);
            for (j = 0; j < 16; j++)
            {
                  if ((i + j) < nb)
                        fprintf (fptr, "%02x ", ptr[i + j] & 0xff);
                  else
                        fprintf (fptr, "   ");
            }
            for (j = 0; j < 16; j++)
            {
                  char c = ptr[i + j] & 0xff;

                  if ((i + j) < nb)
                        putc (isprint (c) ? c : '.', fptr);
                  else
                        putc (' ', fptr);
            }
            putc ('\n', fptr);
      }
}

static void bin_recv (char *ptr, int nb)
{
      FILE *fptr = fopen ("/tmp/debug.hst", "a+b");
      long temps = time (NULL);

      if (fptr == NULL)
            return;

      fprintf (fptr, "\nRX=%-3d %s", nb, asctime (localtime (&temps)));
      dump_data (fptr, ptr, nb);
      fclose (fptr);
}

static void bin_send (char *ptr, int nb)
{
      FILE *fptr = fopen ("/tmp/debug.hst", "a+b");
      long temps = time (NULL);

      if (fptr == NULL)
            return;

      fprintf (fptr, "\nTX=%-3d %s", nb, asctime (localtime (&temps)));
      dump_data (fptr, ptr, nb);
      fclose (fptr);
}
#endif

static void initcrc (void)
{
      unsigned int i, j;
      unsigned short accu, data;

      crctab = malloc (256 * sizeof (unsigned short));

      for (i = 0; i < 256; i++)
      {
            accu = 0;
            data = i;
            for (j = 0; j < 8; j++)
            {
                  if ((data ^ accu) & 1)
                        accu = (accu >> 1) ^ 0x8408;
                  else
                        accu = accu >> 1;
                  data >>= 1;
            }
            crctab[i] = accu;
      }
}

int hst_vide (int port, int echo)
{
      int c, nb = 0;

      df ("vide", 2);

      if ((DEBUG) || (!p_port[port].pvalid))
      {
            deb_io ();
            cprintf ("Erreur port %d!\n", port);
            fin_io ();
            ff ();
            return (0);
      }

      p_port[port].portind = 0;

      tempo = 20;
      deb_io ();
      while (tempo)
      {
            if ((c = rec_tnc (port)) >= 0)
            {
                  if (echo)
                  {
#ifdef __FBBDOS__
                        putch (c);
                        if (c == '\r')
                              putch ('\n');
#endif
                  }
                  tempo = 20;
                  ++nb;
            }
#ifdef __WINDOWS__
            else
            {
                  BWinSleep (100);
                  if (tempo > 0)
                        --tempo;
            }
#endif
#ifdef __LINUX__
            else
            {
                  usleep (100000);
                  if (tempo > 0)
                        --tempo;
            }
#endif
      }
      fin_io ();
      ff ();
      return (nb);
}

/*
 * Fonctions g‚n‚riques du driver
 */

int opn_hst (int port, int nb)
{
      static int init = 0;
      long bt;
      int reset = 4;
      int nb_can;
      int i;
      int ok;
      char s[80];

      /* Only one INIT on this tnc */

      p_port[port].last = NULL;

      while (reset)
      {
            ok = 0;
            sprintf (s, "Init PORT %d COM%d-%d PTCII",
                         port, p_port[port].ccom, p_port[port].ccanal);
#if defined(__WINDOWS__) || defined(__LINUX__)
            InitText (s);
#else
            cprintf ("%s\r\n", s);
#endif
            if (init)
            {
                  sleep_ (1);
                  return (1);
            }

            init = 1;

            initcrc ();

            sprintf (s, "Init PORT %d COM%d-%d PTCII",
                         port, p_port[port].ccom, p_port[port].ccanal);
#if defined(__WINDOWS__) || defined(__LINUX__)
            InitText (s);
#else
            cprintf ("%s\r\n", s);
#endif
/*      sleep_(1); */
            tncstr (port, "\r\033\rRESTART\r", 0);

            bt = btime () + 100;
            do
            {
                  if (rec_tnc (port) < 0)
                  {
                        ok = 1;
                        break;
                  }
            }
            while (btime () < bt);

            hst_vide (port, 1);

            sprintf (s, "\r\033\rPTC %d\r", PACTOR_CH);
            tncstr (port, s, 0);
            
            sprintf (pactor, "(%d)", PACTOR_CH);

            bt = btime () + 20;
            do
            {
                  if (rec_tnc (port) < 0)
                  {
                        ok = 1;
                        break;
                  }
            }
            while (btime () < bt);

            if (ok == 1)
                  break;

            --reset;
      }
      sprintf (s, "Clear PORT %d COM%d-%d PTCII",
                   port, p_port[port].ccom, p_port[port].ccanal);
#if defined(__WINDOWS__) || defined(__LINUX__)
      InitText (s);
#else
      cprintf ("%s\r\n", s);
#endif
      tncstr (port, "\033JHOST4\r", 0);

      sprintf (s, "Prog PORT %d COM%d-%d PTCII",
                   port, p_port[port].ccom, p_port[port].ccanal);
      hst_vide (port, 1);
#if defined(__WINDOWS__) || defined(__LINUX__)
      InitText (s);
#else
      cprintf ("%s\r\n", s);
#endif
      /* Parametres par defaut */
/*    sprintf (s, "#PTC %d\r", PACTOR_CH);
      hst_sndcmd (port, 0, (char *) s, 1);
      hst_sndcmd (port, 0, (char *) s, 1); */
      
      /* All channels callsign */
      sprintf (s, "I %s-%d", mycall, myssid);
      hst_sndcmd (port, 0, (char *) s, 1);
      hst_sndcmd (port, 0, (char *) s, 1);

      /* Port pactor */
      sprintf (s, "I %s", mycall);
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);

      if (DRSI (port))
      {
            nb_can = 0;
            for (i = 1; i < NBPORT; i++)
            {
                  if (p_port[i].ccom == p_port[port].ccom)
                  {
                        nb_can += p_port[i].nb_voies;
                  }
            }
      }
      else
      {
            nb_can = p_port[port].nb_voies;
      }
      sprintf (s, "Y %d", nb_can);
      hst_sndcmd (port, 0, (char *) s, 1);
      sprintf (s, "O %d", p_port[port].frame);
      hst_sndcmd (port, 0, (char *) s, 1);
      sprintf (s, "%%L 0");
      hst_sndcmd (port, 0, (char *) s, 1);
      sprintf (s, "#PD 0");
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);
      sprintf (s, "#UML 0");
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);
      sprintf (s, "#BOX 0");
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);
      sprintf (s, "#REM 0");
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);
      sprintf (s, "#MA 0");
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);
      sprintf (s, "#CMSG 0");
      hst_sndcmd (port, PACTOR_CH, (char *) s, 1);
      return (ok);
}


void debug_state (int port)
{
}


static void FAR hst_iss (int port, void *userdata)
{
      /* Automatic break_in */
      hst_sndcmd (port, PACTOR_CH, "%I", 2);
      p_port[port].t_iss = NULL;
}

static int is_data (int port)
{
      PortData *cmd = p_port[port].cmd;

      while (cmd)
      {
            if (cmd->cmd == DATA)
            {
                  return (1);
            }
            cmd = cmd->next;
      }
      return (0);
}

static void test_timings (int port)
{
      if (!ONLINE (port) || (p_port[port].ccanal != 0))
            return;

      if (!ISS (port) && (is_data (port)))
      {
            if (!p_port[port].t_iss)
            {
                  p_port[port].t_iss = add_timer (10, port, (void FAR *) hst_iss, NULL);
            }
      }
      else
      {
            del_timer (p_port[port].t_iss);
            p_port[port].t_iss = NULL;
      }
}

int rcv_hst (int *port, int *canal, int *cmd, char *buffer, int *len, ui_header * ui)
{
      int lgbuf;
      int can = p_port[*port].cur_can & 0xff;
      int code;
      int valid;
      int next = 1;
      char *ptr;

      /* Header provisoire */
      static ui_header loc_ui[NBPORT];

      *cmd = INVCMD;

      if ((BUSY (*port)) && (hst_busy (*port, canal, FALSE)))
      {
            *cmd = COMMAND;
            sprintf (buffer, "(%d) FREQ-BUSY fm PACTOR", *canal);
            *len = strlen (buffer);
            return (1);
      }

      /* Test si c'est le port correspondant au MUX ... */
      if ((operationnel) && (*port != p_com[(int)p_port[*port].ccom].mult_sel))
            return (-1);


      if ((p_port[*port].polling == 0) && (p_port[*port].last == NULL))
      {
            hst_sonde (*port, next);
            return (0);
      }

      valid = 0;

      deb_io ();
      code = recv_hst (*port, can, &lgbuf, buffer);
      fin_io ();

      switch (code)
      {
      case 0:
            *cmd = NOCMD;
            *len = 0;
            p_port[*port].polling = 0;
            if (p_port[*port].last_cmde == 'G')
            {
                  p_port[*port].wait[can] = 0;
            }
            break;
      case 1:
            switch (p_port[*port].last_cmde)
            {
            case 'L':
                  {
                        /* Retour de statistiques */
                        stat_ch sta;
                        int nbmes, nbtra, nbatt, nback, nbret, con;

                        valid = 2;
                        *cmd = STATS;
                        *canal = can;
                        *len = 0;
                        sscanf (buffer, "%d%d%d%d%d%d",
                                    &nbmes, &nbtra, &nbatt, &nback, &nbret, &con);
                        memset (&sta, 0, sizeof (sta));
                        sta.stat = con;
                        sta.ret = nbret;
                        p_port[*port].wait[can] = nbmes + nbtra;
                        sta.ack = nbatt + nback + nb_waiting (*port);
                        memcpy (buffer, &sta, sizeof (sta));
                        if (p_port[*port].wait[can])
                              next = 0;
                  }
                  break;
            case 'B':
                  {
                        valid = 2;
                        *cmd = NBBUF;
                        *len = 0;
                        *((int *) buffer) = atoi (buffer);
                        break;
                  }
            case 'T':
                  {
                        valid = 2;
                        *cmd = NBCHR;
                        *len = 0;
                        *canal = PACTOR_CH;
                        *((long *) buffer) = atol (buffer);
                        break;
                  }
            default:
                  valid = 2;
                  *len = lgbuf;
                  *cmd = ECHOCMD;
                  break;
            }
            p_port[*port].polling = 0;
            break;
      case 2:
            valid = 2;
            *len = lgbuf;
            *cmd = ERRCMD;
            p_port[*port].polling = 0;
            if (p_port[*port].wait[can])
                  --p_port[*port].wait[can];
            break;
      case 3:
            valid = 2;
            *cmd = COMMAND;
            *canal = can;
            *len = lgbuf;
            p_port[*port].polling = 0;
            if (strncmp (buffer, pactor, strlen (pactor)) == 0)
            {
                  char *scan;

                  scan = strchr (buffer, ':');
                  if (scan && (scan != buffer))
                  {
                        --scan;
                        *scan = '0';
                  }
            }

            ptr = strstr (buffer, " CONNECTED");
            if (ptr && (p_port[*port].ccanal == 0))
            {
                  /* Connexion sur le pactor. Forcer le statut ! */
                  int com = p_port[*port].ccom;

                  p_com[com].pactor_st = 0xa2;
                  debug_state (*port);
            }

            if ((ptr) && (hst_busy (*port, canal, TRUE)))
            {
                  memcpy (ptr, " RECONNECT", 10);
            }

            if (p_port[*port].wait[can])
                  --p_port[*port].wait[can];
            break;
      case 4:
            hst_get_ui (*port, buffer, ui);
            valid = 1;
            *cmd = UNPROTO;
            *canal = can;
            *len = 0;
            p_port[*port].idem = 1;
            p_port[*port].polling = 0;
            if (p_port[*port].wait[can])
                  --p_port[*port].wait[can];
            break;
      case 5:
            hst_get_ui (*port, buffer, ui);
            /* Sauvegarde l'UI */
            loc_ui[*port] = *ui;
            valid = 0;
            next = 0;
            p_port[*port].polling = 0;
            break;
      case 6:
            /* Recupere l'UI du coup precedant */
            *ui = loc_ui[*port];
            sprintf (ui->txt, " (%d)", lgbuf);
            valid = 1;
            *cmd = UNPROTO;
            *canal = can;
            *len = lgbuf;
            p_port[*port].idem = 1;
            p_port[*port].polling = 0;
            if (p_port[*port].wait[can])
                  --p_port[*port].wait[can];
            break;
      case 7:
            if (can == PACTOR_ST)
            {
                  int com = p_port[*port].ccom;

                  p_com[com].pactor_st = *buffer;
                  debug_state (*port);
                  test_timings (*port);
                  p_port[*port].polling = 0;
                  hst_sonde (*port, next);
                  return (0);
            }
            valid = 1;
            *cmd = DATA;

            {
                  int res = ONLINE (*port);

                  if ((can != PACTOR_CH) || (res))
                  {
                        *cmd = DATA;
                  }
                  else
                  {
                        *cmd = UNPROTO;
                        memset (ui, 0, sizeof (ui_header));
                        ui->port = *port;
                        strn_cpy (11, ui->from, "PACTOR");
                        ui->ui = 1;
                  }
            }

            *canal = can;
            *len = lgbuf;
            p_port[*port].idem = 1;
            p_port[*port].polling = 0;
            if (p_port[*port].wait[can])
                  --p_port[*port].wait[can];
            break;
      }

      /* Poll du TNC pour la prochaine fois */
      if (code != -1)
      {
            if (p_port[*port].wait[can])
                  next = 0;
            hst_sonde (*port, next);
      }

      return (valid);
}

int cls_hst (int port)
{
      int i;

      /* Vide la file des commandes en attente pour tous les ports du TNC */
      for (i = 1; i < NBPORT; i++)
      {
            if ((HST (i)) && (p_port[port].ccom == p_port[i].ccom))
            {
                  while (p_port[i].cmd)
                  {
                        PortData *cmd = p_port[i].cmd;

                        p_port[i].cur_can = cmd->canal;
                        switch (cmd->cmd)
                        {
                        case COMMAND:
                              p_port[i].last = cmd;
                              p_port[i].last->compteur = 0xc0;
                              hst_send_data (i);

                              /* Attend la reponse 1 seconde */
                              sleep_ (1);

                              /* Vide le buffer */
                              while (rec_tnc (port) != -1);

                              /* La reponse a ete lue et ignoree ... */
                              break;
                        default:
                              break;
                        }
                        p_port[i].cmd = cmd->next;
                        m_libere (cmd, sizeof (PortData));
                        p_port[i].last_cmde = '\0';
                  }
            }
      }

      /* Fin du mode host */
      hst_end_host (port);
      return (1);
}

int sta_hst (int port, int canal, int cmd, void *ptr)
{
      int val;

      /* Pactor port */
      if (p_port[port].moport & 0x80)
            canal = PACTOR_CH;

      switch (cmd)
      {
/*      case TNCSTAT :
   return(lit_stat_hst(port, canal, (stat_ch *)ptr)); */
      case TOR:
            canal = PACTOR_CH;
            val = (hst_sndcmd (port, canal, (char *) ptr, 0) != -1);
            return (val);
      case SNDCMD:
            return (hst_sndcmd (port, canal, (char *) ptr, 0) != -1);
      case ECHOCMD:
            return (hst_sndcmd (port, canal, (char *) ptr, 1) != -1);
      case PORTCMD:
            return (hst_sndcmd (port, 0, (char *) ptr, 1) != -1);
      case PACLEN:
            *((int *) ptr) = 250;
            return (1);
      }
      return (0);
}

int snd_hst (int port, int canal, int cmd, char *buffer, int len, Beacon * ptr)
{
      int ret = 0;

      df ("snd_hst", 8);

      if (p_port[port].synchro > 256)
            return (0);

      /* Pactor port */
      if (p_port[port].moport & 0x80)
            canal = PACTOR_CH;

      switch (cmd)
      {
      case COMMAND:
            break;

      case DATA:
            ret = hst_send_dt (port, canal, buffer, len);
            break;

      case UNPROTO:
            ret = hst_send_ui (port, buffer, len, ptr);
            break;
      }
      ff ();
      return (ret);
}

/* Fonctions locales */

static int hst_end_host (int port)
{
      PortData *cmd;
      static int done = 0;

      if (done)
            return (1);

      done = 1;

      cmd = (PortData *) m_alloue (sizeof (PortData));
      cmd->canal = 0;
      cmd->cmd = COMMAND;
      cmd->len = 2;
      strcpy (cmd->buf, "MN");
      p_port[port].last = cmd;

      p_port[port].last->compteur = hst_compteur (port);
      hst_send_data (port);

      m_libere (p_port[port].last, sizeof (PortData));

      cmd = (PortData *) m_alloue (sizeof (PortData));
      cmd->canal = 0;
      cmd->cmd = COMMAND;
      cmd->len = 6;
      strcpy (cmd->buf, "JHOST0");
      p_port[port].last = cmd;

      p_port[port].last->compteur = hst_compteur (port);
      hst_send_data (port);

      m_libere (p_port[port].last, sizeof (PortData));
      p_port[port].last = NULL;

      return (1);
}

/*
 * Fonctions locales
 */

static int hst_compteur (int port)
{
      static int val = 2;
      int com = p_port[port].ccom;

      if (val == 2)
      {
            p_com[com].compteur = 0xc0;
      }
      else
      {
            p_com[com].compteur = (val) ? 0x80 : 0;
      }
      val = !val;

      return p_com[com].compteur;
}

static void warning (unsigned numero, char *texte)
{
}

/* Retourne le port logique correspondant au lport physique d'un TNC
   static int global_port(int com, int lport)
   {
   int p;

   for (p = 1 ; p < NBPORT ; p++)
   {
   if ((p_port[p].ccom == com) && (p_port[p].ccanal == lport))
   {
   return (p);
   }
   }
   return(1);
   }
 */

static int iss (int port)
{
      return (ISS (port));
}

static int online (int port)
{
      return (ONLINE (port));
}

static PortData *get_cmd (int port)
{
      PortData *prc = NULL;
      PortData *cmd = p_port[port].cmd;

      /* On envoie les data ou le CHO uniquement si le PACTOR est en ISS */
      if (p_port[port].ccanal == 0)
      {
            /* Canal PACTOR */
            while (cmd)
            {
                  if ((!online (port)) || (iss (port)) || ((cmd->cmd == COMMAND) && (strcmp (cmd->buf, "%O") != 0)))
                  {
                        if (prc)
                              prc->next = cmd->next;
                        else
                              p_port[port].cmd = cmd->next;
                        return (cmd);
                  }
                  prc = cmd;
                  cmd = cmd->next;
            }
            return (NULL);
      }
      else if (cmd)
      {
            p_port[port].cmd = cmd->next;
      }

      return (cmd);
}

static void hst_sonde (int pp, int next)
{
      static int cptr[NBPORT];
      static int first = 1;
      static int debug_cmd = 50;
      PortData *cmd = NULL;

      if ((pp < 0) || (pp >= NBPORT))
            return;

      if (first)
      {
            /* Initializes static variables */
            int i;

            for (i = 0; i < NBPORT; i++)
            {
                  cptr[i] = 0;
            }
            first = 0;
      }

      /* if (p_port[pp].cur_can == 0xff)
         p_port[pp].cur_can = 0xfe; */

      if (p_port[pp].last)
      {
            return;
      }

      if (next == 0)
      {
            cmd = (PortData *) m_alloue (sizeof (PortData));
            cmd->canal = p_port[pp].cur_can;
            cmd->cmd = COMMAND;
            cmd->len = 1;
            strcpy (cmd->buf, "G");
            p_port[pp].last = cmd;
            p_port[pp].last_cmde = 'G';
      }
      else if ((cmd = get_cmd (pp)) != NULL)
      {
            /* Il y a une commande a envoyer */

            if (cmd->cmd != COMMAND)
                  cptr[pp] = 0;

            p_port[pp].last = cmd;
            if (strcmp (cmd->buf, "%T") == 0)
                  p_port[pp].last_cmde = 'T';
            else
                  p_port[pp].last_cmde = '\0';
      }
      else if (operationnel == 1)
      {
            if ((cptr[pp] == 0) && (p_port[pp].cur_can != PACTOR_ST))
            {
                  cmd = (PortData *) m_alloue (sizeof (PortData));
                  cmd->canal = p_port[pp].cur_can;
                  cmd->cmd = COMMAND;
                  cmd->len = 2;
                  strcpy (cmd->buf, "@B");
                  p_port[pp].last = cmd;
                  p_port[pp].last_cmde = 'B';
                  cptr[pp] = 50;
            }
            else if (p_port[pp].cur_can == PACTOR_CH)
            {
                  /* Status */
                  cmd = (PortData *) m_alloue (sizeof (PortData));

                  p_port[pp].cur_can = PACTOR_ST;
                  cmd->canal = p_port[pp].cur_can;
                  cmd->cmd = COMMAND;
                  cmd->len = 1;
                  strcpy (cmd->buf, "G");
                  p_port[pp].last = cmd;
                  p_port[pp].last_cmde = 'G';
            }
            else
            {
                  cmd = (PortData *) m_alloue (sizeof (PortData));

                  /* Passe au canal suivant */
                  if ((p_port[pp].idem == 0) || (p_port[pp].cur_can == PACTOR_ST))
                  {
                        int max;

                        if (p_port[pp].moport & 0x80)
                              max = 1;
                        else
                        {
                              max = p_port[pp].tt_can;
                        }

                        ++(p_port[pp].cur_can);
                        if (p_port[pp].cur_can > max)
                        {
                              int mux_ch;
                              int i;
                              int com;
                              int first_mux;
                              int last_mux;

                              /* Passe eventuellement au PORT/MUX suivant */
                              mux_ch = p_port[pp].ccanal;
                              com = p_port[pp].ccom;

                              /*
                                 first_mux = (DRSI (pp)) ? 0 : 1;
                                 last_mux = (DRSI (pp)) ? 7 : 4;
                               */
                              first_mux = 0;
                              last_mux = 2;

                              for (i = first_mux; i < last_mux; i++)
                              {
                                    ++mux_ch;
                                    if (mux_ch > last_mux)
                                          mux_ch = first_mux;
                                    if (p_com[com].multi[mux_ch])
                                    {
                                          pp = p_com[com].multi[mux_ch];
                                          p_com[com].mult_sel = pp;
                                          break;
                                    }
                              }

                              p_port[pp].cur_can = 0;

                              /* Fait la somme des canaux deja balayes (1 seul TNC !!) */
                              if (p_port[pp].ccanal == 0)
                              {
                                    /* Inclut le monitoring */
                                    p_port[pp].cur_can = 0;
                              }
                              else
                              {
                                    p_port[pp].cur_can = 1;
                                    for (i = 1; i < pp; i++)
                                    {
                                          if ((HST (i)) && (!IS_PACTOR (i)) && (p_port[i].ccom == p_port[pp].ccom))
                                          {
                                                p_port[pp].cur_can += p_port[i].nb_voies;
                                          }
                                    }
                              }
                        }
                        if ((p_port[pp].cur_can == 1) && (p_port[pp].moport & 0x80))
                              p_port[pp].cur_can = PACTOR_CH;
                  }
                  else
                        p_port[pp].idem = 0;
                  cmd->canal = p_port[pp].cur_can;
                  cmd->cmd = COMMAND;
                  cmd->len = 1;
                  strcpy (cmd->buf, "L");
                  p_port[pp].last = cmd;
                  p_port[pp].last_cmde = 'L';
                  if (cptr[pp])
                        --cptr[pp];
            }
      }

      DebugCh = 0;
      if (debug_cmd > 0)
      {
            DebugCh = 1;
            --debug_cmd;
      }
      p_port[pp].last->compteur = hst_compteur (pp);
      hst_send_data (pp);
}

static int hst_busy (int port, int *canal, int force)
{
      if (p_port[port].ccanal != 0)
            return (0);

      *canal = PACTOR_CH;

      if (p_port[port].t_busy)
      {
            m_libere (p_port[port].t_busy->userdata, sizeof (PortData));
            del_timer (p_port[port].t_busy);
            p_port[port].t_busy = NULL;
            return (1);
      }
      else if (force && (p_port[port].t_wait))
      {
            /* Supprimer le timer wait */
            m_libere (p_port[port].t_wait->userdata, sizeof (PortData));
            del_timer (p_port[port].t_wait);
            p_port[port].t_wait = NULL;
            return (1);
      }
      return (0);
}

static void FAR hst_startscan (int port, PortData * command)
{
      PortData *cmd = p_port[port].cmd;

      if (ISS (port))
      {
            /* Still sending - postpone the command */
            add_timer (1, port, (void FAR *) hst_startscan, command);
            return;
      }

      /* Insert the command in top of queue */
      command->next = cmd;
      p_port[port].cmd = command;
      pactor_scan[port] = 1;
}

static void FAR hst_connect (int port, PortData * command)
{
      PortData *cmd = p_port[port].cmd;

      p_port[port].t_busy = NULL;

      if (cmd)
      {
            /* Rajoute la commande en fin de queue */
            while (cmd->next)
                  cmd = cmd->next;
            cmd->next = command;
      }
      else
            /*cmd = */
            p_port[port].cmd = command;
      aff_forward ();
}

static void FAR hst_wait (int port, PortData * command)
{
      p_port[port].t_wait = NULL;
      if (p_port[port].t_busy)
      {
            m_libere (p_port[port].t_busy->userdata, sizeof (PortData));
            del_timer (p_port[port].t_busy);
      }
      p_port[port].t_busy = add_timer (10, port, (void FAR *) hst_connect, command);
      aff_forward ();
}

static int hst_sndcmd (int port, int canal, char *buffer, int retour)
{
      PortData *cmd = p_port[port].cmd;
      int nb;
      char cmde[80];
      char scan[80];
      char val[80];
      char temp[80];

      /* if (p_port[port].ccanal == 0)
         canal = PACTOR_CH; */
      if (strlen (buffer) == 0)
            return (0);

      /* Demande de connexion du canal pactor : verifier d'abord le status */
      if (*buffer == 'C')
      {
            if (canal == PACTOR_CH)
            {
                  /* Armer le timer = 10 secondes */
                  cmd = (PortData *) m_alloue (sizeof (PortData));
                  cmd->next = NULL;
                  cmd->canal = canal;
                  cmd->cmd = COMMAND;
                  cmd->len = strlen (buffer);
                  strcpy (cmd->buf, buffer);
                  if (p_port[port].t_wait)
                  {
                        m_libere (p_port[port].t_wait->userdata, sizeof (PortData));
                        del_timer (p_port[port].t_wait);
                  }
                  p_port[port].t_wait = add_timer (7, port, (void FAR *) hst_wait, cmd);
                  return (1);
            }
            else if (strchr (buffer, ':') == NULL)
            {
                  /* Selectionner le bon port */
                  ++buffer;
                  while (isspace (*buffer))
                        ++buffer;
                  sprintf (temp, "C %d:%s", p_port[port].ccanal, buffer);
                  buffer = temp;
            }
      }

      *scan = '\0';
      *val = '\0';
      nb = sscanf (buffer, "%s %s %s", cmde, scan, val);

      if (cmde[0] == '!')
            cmde[0] = '#';

      if ((nb == 3) && (strcmpi (cmde, "#TRX") == 0) && (strncmpi (scan, "SCAN", strlen (scan)) == 0))
      {
            if (isdigit (*val)) 
            {
                   if (atoi (val) > 0)
                   {
                        cmd = (PortData *) m_alloue (sizeof (PortData));
                        cmd->next = NULL;
                        cmd->canal = canal;
                        cmd->cmd = COMMAND;
                        cmd->len = strlen (buffer);
                        strcpy (cmd->buf, buffer);
                        hst_startscan (port, cmd);
                        return 1;
                  }
                  pactor_scan[port] = 0;
            }
      }

      if (strcmp (cmde, "%O") == 0)
      {
            /* Un seul change-over en queue ! Enleve le precedent ... */
            PortData *pr = NULL;

            cmd = p_port[port].cmd;
            while (cmd)
            {
                  if (strcmp (cmd->buf, "%O") == 0)
                  {
                        if (pr)
                        {
                              pr->next = cmd->next;
                        }
                        else
                        {
                              p_port[port].cmd = cmd->next;
                        }

                        /* Libere la structure */
                        m_libere (cmd, sizeof (PortData));
                        break;
                  }
                  pr = cmd;
                  cmd = cmd->next;
            }
      }

      cmd = p_port[port].cmd;
      if (cmd)
      {
            /* Rajoute la commande en fin de queue */
            while (cmd->next)
                  cmd = cmd->next;
            cmd->next = (PortData *) m_alloue (sizeof (PortData));
            cmd = cmd->next;
      }
      else
      {
            p_port[port].cmd = (PortData *) m_alloue (sizeof (PortData));
            cmd = p_port[port].cmd;
      }

      strcpy (cmd->buf, buffer);
      if (cmd->buf[0] == '!')
            cmd->buf[0] = '#';


      if ((nb == 2) && (strncmpi (cmde, "#MYPAC", 6) == 0))
      {
            sprintf(cmd->buf, "I%s", scan);
            canal = PACTOR_CH;
      }

      cmd->next = NULL;
      cmd->canal = canal;
      cmd->cmd = COMMAND;
      cmd->len = strlen (cmd->buf);

      return 1;
}

static int hst_send_dt (int port, int canal, char *buffer, int len)
{

      PortData *cmd = p_port[port].cmd;

      if (len <= 0)
            return (0);

      if (cmd)
      {
            /* Rajoute la commande en fin de queue */
            while (cmd->next)
                  cmd = cmd->next;
            cmd->next = (PortData *) m_alloue (sizeof (PortData));
            cmd = cmd->next;
      }
      else
            cmd = p_port[port].cmd = (PortData *) m_alloue (sizeof (PortData));

      cmd->next = NULL;
      cmd->canal = canal;
      cmd->cmd = DATA;
      cmd->len = len > 256 ? 256 : len;
      memcpy (cmd->buf, buffer, cmd->len);
      return (1);
}

static int hst_send_ui (int port, char *buffer, int len, Beacon * beacon)
{
      char commande[300];
      char s[80];
      int i;
      int ptport;
      int canal;
      PortData *cmd;

      if (len <= 0)
            return (0);

      if (p_port[port].ccanal == 0)
      {
            /* No beacon on pactor port ! */
            return (1);
      }
      else
      {
            ptport = p_port[port].ccanal;
            canal = 0;
      }

      /* Selection du port */
      sprintf (commande, "%%P%d", ptport);

      cmd = p_port[port].cmd;
      if (cmd)
      {
            /* Rajoute la commande en fin de queue */
            while (cmd->next)
                  cmd = cmd->next;
            cmd->next = (PortData *) m_alloue (sizeof (PortData));
            cmd = cmd->next;
      }
      else
            cmd = p_port[port].cmd = (PortData *) m_alloue (sizeof (PortData));

      cmd->canal = canal;
      cmd->cmd = COMMAND;
      cmd->next = NULL;
      cmd->len = strlen (commande);
      strcpy (cmd->buf, commande);

      sprintf (commande, "C %d:%s-%d", ptport, beacon->desti.call, beacon->desti.num);

      for (i = 0; i < 8; i++)
      {
            if (*beacon->digi[i].call)
            {
                  if (i == 0)
                  {
                        strcat (commande, " VIA");
                  }
                  sprintf (s, " %s-%d",
                               beacon->digi[i].call, beacon->digi[i].num);
                  strcat (commande, s);
            }
      }

      cmd->next = (PortData *) m_alloue (sizeof (PortData));
      cmd = cmd->next;

      cmd->next = NULL;
      cmd->canal = canal;
      cmd->cmd = COMMAND;
      cmd->len = strlen (commande);
      strcpy (cmd->buf, commande);

      cmd->next = (PortData *) m_alloue (sizeof (PortData));
      cmd = cmd->next;

      cmd->next = NULL;
      cmd->canal = canal;
      cmd->cmd = UNPROTO;
      cmd->len = len > 256 ? 256 : len;
      memcpy (cmd->buf, buffer, cmd->len);

      return (1);
}

/* static int hst_send_data (int port, int canal, int type, char *buffer, int len) */
static int hst_send_data (int port)
{
      int i;
      int c;
      int canal, type, len;
      char *buffer;
      char debug_buf[300];
      char *pdb = debug_buf;
      int dlen = 0;

      unsigned short crc = 0xffff;

      if (p_port[port].last == NULL)
            return (0);

      DebugCmd (port);

      canal = p_port[port].last->canal;
      type = (p_port[port].last->cmd == COMMAND) ? 1 : 0;
      type |= p_port[port].last->compteur;
      len = p_port[port].last->len;
      buffer = p_port[port].last->buf;

      send_tnc (port, HST_CHAR);
      *pdb++ = HST_CHAR;
      ++dlen;
      send_tnc (port, HST_CHAR);
      *pdb++ = HST_CHAR;
      ++dlen;

      crc = updcrc (canal, crc);
      send_tnc (port, canal);
      *pdb++ = canal;
      ++dlen;

      crc = updcrc (type, crc);
      send_tnc (port, type);
      *pdb++ = type;
      ++dlen;

      c = len - 1;
      crc = updcrc (c, crc);
      send_tnc (port, c);
      *pdb++ = c;
      ++dlen;
      if (c == HST_CHAR)
      {
            send_tnc (port, 0);
            *pdb++ = 0;
            ++dlen;
      }

      for (i = 0; i < len; i++)
      {
            c = *buffer++;
            crc = updcrc (c, crc);
            send_tnc (port, c);
            *pdb++ = c;
            ++dlen;
            if (c == HST_CHAR)
            {
                  send_tnc (port, 0);
                  *pdb++ = 0;
                  ++dlen;
            }
      }

      crc = ~crc;

      /* Send crc */
      c = crc & 0xff;
      send_tnc (port, c);
      *pdb++ = c;
      ++dlen;
      if (c == HST_CHAR)
      {
            send_tnc (port, 0);
            *pdb++ = 0;
            ++dlen;
      }

      c = crc >> 8;
      send_tnc (port, c);
      *pdb++ = c;
      ++dlen;
      if (c == HST_CHAR)
      {
            send_tnc (port, 0);
            *pdb++ = 0;
            ++dlen;
      }

#ifdef DEBUG_HST
      /* if (p_port[port].last->cmd == COMMAND) */
            bin_send (debug_buf, dlen);
#endif

      p_port[port].polling = 1;
      p_com[(int)p_port[port].ccom].delai = 0;

      return (1);
}

static void resync_port (int port)
{
      long nt = btime ();
      static int first = 1;
      static long delai[NBPORT];

      if ((port < 0) || (port >= NBPORT))
            return;

      if (first)
      {
            /* Initializes static variables */
            int i;

            for (i = 0; i < NBPORT; i++)
            {
                  delai[i] = 0L;
            }
            first = 0;
      }


      if ((p_port[port].synchro < 256) && (delai[port] < nt))
      {
            ++p_port[port].synchro;

            /* Retry du dernier paquet */
            hst_send_data (port);
            delai[port] = nt + 20L;
#if defined(__WINDOWS__) || defined(__LINUX__)
            DisplayResync (port, p_port[port].synchro);
#else
            {
                  char s[40];

                  sprintf (s, "Port %d Resync %-4d", port, p_port[port].synchro);
                  aff_chaine (W_DEFL, 1, 1, s);
            }
#endif
      }

      if (p_port[port].synchro == 256)
      {
            char txt[80];

            sprintf (txt, "Port %d was not resynchronized. Stopped. Error =", port);
            warning (4, txt);
            ++p_port[port].synchro;
      }
}

static int crc_check (char *ptr, int len)
{
      int i;
      unsigned short crc = 0xffff;

      for (i = 0; i < len; i++)
      {
            crc = updcrc (*ptr, crc);
            ++ptr;
      }

      return (crc == 0xf0b8);
}

static int recv_hst (int port, int canal, int *lgbuf, char *buffer)
{
      int crc_ok;
      int r_canal, code = 0, nb, lg;
      int i, pos, c, hst;
      int last = -1;
      char buf[300];
      char *debbuf = buffer;

      /* Implementation polling */
      int valid = 0;
      char *ptr = p_port[port].portbuf;
      int index = p_port[port].portind;

      while ((c = rec_tnc (port)) >= 0)
      {
            if (index == 300)
            {
                  /* Erreur : Vider le buffer et resynchroniser ? */
                  vide (port, 0);
                  index = 0;
                  break;
            }
            /* Ajoute les caracteres dans le buffer */
            ptr[index++] = c;
      }
      p_port[port].portind = index;

      /* Tester si la trame est complete */
      if (index >= 6)
      {
            /* La trame doit faire au moins 6 octets : header + canal et code + crc16 */

            /* Verifier que les deux premiers octets sont HST_CHAR */
            if ((ptr[0] != HST_CHAR) || (ptr[1] != HST_CHAR))
            {
                  /* Le paquet n'est pas bon. Jeter le 1er octet */
                  for (i = 1; i < index; i++)
                  {
                        ptr[i - 1] = ptr[i];
                  }
                  --p_port[port].portind;
                  return (-1);            /* Modifie de 0 a -1 le 05/04/98 */
            }

            /* Sauter le header - supprimer les 0x00 apres les HST_CHAR et recopie dans buf */
            for (i = 2, pos = 0, hst = 0; i < index; i++)
            {
                  if (hst)
                  {
                        if (ptr[i] == 0)
                              hst = 0;
                        else
                        {
                              p_port[port].portind = 0;

                              /* Demande la repetition du paquet */
                              hst_send_data (port);
                              return (-1);
                        }
                  }
                  else
                        buf[pos++] = ptr[i];

                  if (ptr[i] == HST_CHAR)
                  {
                        hst = 1;
                  }
            }

            /* Verifie que les caracteres HST_CHAR sont bien suivis de leur 0 */
            pos -= hst;

            /* Nouvelle longueur du paquet */
            ptr = buf;
            index = pos;

            crc_ok = crc_check (ptr, index);

            /* On tente le decodage ... */
            index -= 2;                   /* enlever le crc */
            r_canal = *ptr++;

            code = *ptr++;
            index -= 2;

            *lgbuf = 0;

            if (canal == 0xff)
                  canal = r_canal;

            lg = 0;
            switch (code)
            {
            case 0:
                  if (pos >= 4)
                  {
                        if (!crc_ok)
                        {
                              /* La trame est erronnee */

                              /* Jette la trame recue */
                              p_port[port].portind = 0;

                              /* Demande la repetition du paquet */
                              hst_send_data (port);
                              return (-1);
                        }
#ifdef DEBUG_HST
                        if (r_canal != PACTOR_ST)
                        {
                              char buf_debug[300];

                              buf_debug[0] = 0xaa;
                              buf_debug[1] = 0xaa;
                              memcpy (buf_debug + 2, buf, pos);
                              bin_recv (buf_debug, pos + 2);
                        }
#endif
                        *buffer = '\0';
                        valid = 1;
                  }
                  break;
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                  while (index)
                  {
                        last = *ptr++;
                        *buffer++ = last;
                        ++lg;
                        --index;
                  }

                  /* Le caractere doit etre un NULL pour finir le paquet */
                  if (last == '\0')
                  {
                        if (!crc_ok)
                        {
                              /* La trame est erronnee */

                              /* Jette la trame recue */
                              p_port[port].portind = 0;

                              /* Demande la repetition du paquet */
                              hst_send_data (port);
                              return (-1);
                        }
#ifdef DEBUG_HST
                        if (r_canal != PACTOR_ST)
                        {
                              char buf_debug[300];

                              buf_debug[0] = 0xaa;
                              buf_debug[1] = 0xaa;
                              memcpy (buf_debug + 2, buf, pos);
                              bin_recv (buf_debug, pos + 2);
                        }
#endif
                        valid = 1;
                        *buffer = '\n';
                        *++buffer = '\0';
                  }
                  break;
            case 6:
            case 7:
                  nb = lg = 1 + (0xff & *ptr++);
                  --index;

                  if (nb == index)
                  {
                        if (!crc_ok)
                        {
                              /* La trame est erronnee */

                              /* Jette la trame recue */
                              p_port[port].portind = 0;

                              /* Demande la repetition du paquet */
                              hst_send_data (port);
                              return (-1);
                        }
                        /* Tous les caracteres sont recus */
#ifdef DEBUG_HST
                        if (r_canal != PACTOR_ST)
                        {
                              char buf_debug[300];

                              buf_debug[0] = 0xaa;
                              buf_debug[1] = 0xaa;
                              memcpy (buf_debug + 2, buf, pos);
                              bin_recv (buf_debug, pos + 2);
                        }
#endif
                        while (nb--)
                        {
                              *buffer++ = *ptr++;
                        }
                        valid = 1;
                  }
                  break;
            default:
                  if ((!svoie[CONSOLE]->sta.connect) && (p_port[port].synchro == 0))

                  {
                        char txt[80];

                        if (!crc_ok)
                        {
                              /* La trame est erronnee */

                              /* Jette la trame recue */
                              p_port[port].portind = 0;

                              /* Demande la repetition du paquet */
                              hst_send_data (port);
                              return (-1);
                        }
                        sprintf (txt, "Erreur code trame = %d. Erreur =", code);
                        warning (2, txt);
                  }
                  if (p_port[port].synchro == 0)
                  {
                        vide (port, 0);
                        p_port[port].portind = 0;
                  }
                  else if ((r_canal == '^') && (code == 'A'))
                  {
                        /* TNC reinitialise en mode normal ??? */
                        valid = 1;
#ifdef __WINDOWS__
                        if (operationnel)
                        {
                              fbb_quit (0);
                              *lgbuf = 0;
                              return (-1);
                        }
#endif
                  }
                  break;
            }
            *lgbuf = lg;
      }

      if (valid)
      {
            /* La trame a ete acceptee... On libere la donnee */
            m_libere (p_port[port].last, sizeof (PortData));
            p_port[port].last = NULL;

            if ((DebugCh) || (code == 2))
            {
                  int len = *lgbuf;
                  char buf[300];

                  strcpy (buf, debbuf);
                  len = *lgbuf;

                  if (code == 1)
                  {
                        --len;
                        buf[len] = '\0';
                  }

            }

            /* Une trame complete a ete recue */
            if (p_port[port].synchro)
            {
#if defined(__WINDOWS__) || defined(__LINUX__)
                  char txt[80];

                  sprintf (txt, "Ending resynchronization on port %d - Error =", port);
                  warning (5, txt);

                  DisplayResync (port, 0);
#else
                  ++com_error;
                  aff_date ();
#endif
            }
            p_port[port].portind = 0;
            p_port[port].synchro = 0;
            p_com[(int)p_port[port].ccom].delai = 0;
      }
      else
      {
            code = -1;

            /* Rien n'a ete recu... Tester le temps (2 secondes d'attente) */
            if (p_com[(int)p_port[port].ccom].delai > 10)
            {
                  /* Lancer la procedure de resynchronisation */
                  if (p_port[port].synchro == 0)
                  {
                        char txt[80];

                        sprintf (txt, "Starting resynchronization on port %d - Error =", port);
                        warning (3, txt);
                        /* vide (port, 0); */
                  }
                  p_port[port].portind = 0;
                  resync_port (port);
            }
      }

      return (code);
}

static void hst_get_ui (int port, char *buffer, ui_header * ui)
{
      char *ptr;
      char *scan;

      memset (ui, 0, sizeof (ui_header));

      ui->port = port;

      scan = buffer;

      if ((isdigit (scan[0])) && (scan[1] == ':'))
      {
            /* port HST */
            ui->port = hst_port (port, scan[0] - '0');
            scan += 2;
            if (*scan == ' ')
            {
                  /* bug TFPCX ... */
                  ++scan;
            }
      }

      ptr = strtok (scan, " ");     /* fm */

      if (ptr == NULL)
            return;

      ptr = strtok (NULL, " ");     /* exped */

      if (ptr == NULL)
            return;
      n_cpy (11, ui->from, ptr);

      ptr = strtok (NULL, " ");     /* to */

      if (ptr == NULL)
            return;

      ptr = strtok (NULL, " ");     /* desti */

      if (ptr == NULL)
            return;
      n_cpy (11, ui->to, ptr);

      ptr = strtok (NULL, " ");     /* via ou ctl */

      if (ptr == NULL)
            return;

      if (strcmp (ptr, "via") == 0)
      {
            for (;;)
            {
                  if (*ui->via)
                        strcat (ui->via, " ");

                  ptr = strtok (NULL, " ");     /* digis */

                  if (ptr == NULL)
                        return;

                  if (strcmp (ptr, "ctl") == 0)
                        break;

                  strncat (ui->via, ptr, 12);
            }
      }

      ptr = strtok (NULL, " ");     /* controle */

      if (ptr == NULL)
            return;
      strn_cpy (11, ui->ctl, ptr);
      ui->ui = (strncmp (ptr, "UI", 2) == 0);

      ptr = strtok (NULL, " ");     /* pid */

      if (ptr == NULL)
            return;

      ptr = strtok (NULL, " ");     /* pid */

      if (ptr == NULL)
            return;
      sscanf (ptr, "%x", &ui->pid);
}

static int nb_waiting (int port)
{
      /* Donne le nombre de trames DATA en attente d'envoi vers le TNC */
      int nb = 0;
      PortData *cmd = p_port[port].cmd;

      while (cmd)
      {
            if (cmd->cmd == DATA)
                  ++nb;
            cmd = cmd->next;
      }

      return (nb);
}

Generated by  Doxygen 1.6.0   Back to index