/** xprfuncs.c
*
*   Call-back functions for eXternal PRotocol support
*
**/
#include <functions.h>
#include <exec/exec.h>
#include <stdio.h>
/*
*   xproto.h is given in Appendix B
*/
#include "xproto.h"
/*
*   xfer.h is a VLT private header file containing some information for
*   file transfer protocols
*/
#include "xfer.h"

/*
*   These are the C versions of the interface
*/
long        vlt_update(),  vlt_swrite(),  vlt_fread(),  vlt_fopen(),
            vlt_fclose(),  vlt_gets(),    vlt_sread(),  vlt_chkabort();
/*
*   These are the assembly level glue functions, see vltface.asm
*/
extern long avlt_update(), avlt_swrite(), avlt_fread(), avlt_fopen(),
            avlt_fclose(), avlt_gets(),   avlt_sread(), avlt_chkabort();

/**
*
*   This function initializes an XPR_IO structure.
*
**/
xpr_setup(IO)
struct XPR_IO *IO;
{
/*
*   NULL out all the functions we don't do yet.
*   Fill the other ones with the addresses to the assembler glue version
*   of the interface routines. See vltface.asm
*/
   IO->xpr_filename  = NULL;
   IO->xpr_fopen     = avlt_fopen;
   IO->xpr_fclose    = avlt_fclose;
   IO->xpr_fread     = avlt_fread;
   IO->xpr_fwrite    = NULL;
   IO->xpr_sread     = avlt_sread;
   IO->xpr_swrite    = avlt_swrite;
   IO->xpr_sflush    = NULL;
   IO->xpr_update    = avlt_update;
   IO->xpr_chkabort  = avlt_chkabort;
   IO->xpr_chkmisc   = NULL;
   IO->xpr_gets      = avlt_gets;
   IO->xpr_setserial = NULL;
   IO->xpr_ffirst    = NULL;
   IO->xpr_fnext     = NULL;
   IO->xpr_finfo     = NULL;
   IO->xpr_reserved1 = NULL;
   IO->xpr_reserved2 = NULL;
/*
*   Especially, NULL out the XPR private data field.
*/
   IO->xpr_data      = NULL;

   return;
}

/**
*
*   Interface to VLT's MsgDisplay() function.
*
**/
/*
*   These are formats for VLT's requester
*/
static char *xprnamfmt = "%s\n%s\n\n\n\n";
static char *filnamfmt = "\n\n%s\n\n\n";
static char *blksizfmt = "\n\n\n\nBlock:  %6ld  --  Block Size:  %6ld\n";
static char *errtimfmt = "\n\n\n\n\nErrors: %6ld  --  Timeouts:    %6ld";
static char *delayfmt  = "\n\n\n\n\nPacket delay %ld";
/*
*   Below are some VLT globals to orchestrate the display
*/
long xpr_blocks = 0L, xpr_blocksize = 0L, xpr_errors = 0L, xpr_timeouts = 0L;
/*
*   The function
*/
long vlt_update(x)
struct XPR_UPDATE *x;
{
   extern struct Window *mywindow;
   extern char *XPR_Name;
/*
*   First time, determine the window size (50 chars wide, 5 lines tall).
*/
   SetMsgWindow(mywindow, 50, 6);
/*
*   Use VLT's PostMsg function to display all the information.
*/
   if (x->xpru_updatemask & XPRU_PROTOCOL) {
      PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_protocol);
   }
   if (x->xpru_updatemask & XPRU_MSG) {
      PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_msg);
   }
   if (x->xpru_updatemask & XPRU_ERRORMSG) {
      PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_errormsg);
   }
   if (x->xpru_updatemask & XPRU_FILENAME) {
      PostMsg(mywindow, filnamfmt, x->xpru_filename);
   }
   if (x->xpru_updatemask & XPRU_PACKETDELAY) {
      PostMsg(mywindow, delayfmt, x->xpru_packetdelay);
   }
   if (x->xpru_updatemask & (XPRU_BLOCKS | XPRU_BLOCKSIZE)) {
      if (x->xpru_updatemask & XPRU_BLOCKS)    xpr_blocks    = x->xpru_blocks;
      if (x->xpru_updatemask & XPRU_BLOCKSIZE) xpr_blocksize = x->xpru_blocksize;
      PostMsg(mywindow, blksizfmt, xpr_blocks, xpr_blocksize);
   }
   if (x->xpru_updatemask & (XPRU_ERRORS | XPRU_TIMEOUTS)) {
      if (x->xpru_updatemask & XPRU_ERRORS)   xpr_errors   = x->xpru_errors;
      if (x->xpru_updatemask & XPRU_TIMEOUTS) xpr_timeouts = x->xpru_timeouts;
      PostMsg(mywindow, errtimfmt, xpr_errors, xpr_timeouts);
   }
   return(0L);
}

/**
*
*   Prompt the user for input
*
**/
long vlt_gets(s, t)
char *s, *t;
{
/*
*   Use VLT's DoRequest() function
*/
   return((long) DoRequest(mywindow, t, s, NULL, " Cancel "));
}

/**
*
*   Write a string to the serial port
*
**/
long vlt_swrite(s, n)
char *s;
long n;
{
/*
*   Use VLT's SendString() function
*/
   SendString(s, (int) n);
   return(0L);
}

/**
*
*   Read characters from the serial port
*
**/
long vlt_sread(buff, length, micros)
unsigned char *buff;
long length, micros;
{
   extern int timeout;
   long secs = 0L;

   if (buff == NULL) return(-1L);
/*
*   Convert timeout to seconds and micros if necessary
*/
   if (micros) {
      if (micros > 1000000L) {
         secs   = micros / 1000000L;
         micros = micros % 1000000L;
      }
   }
/*
*   Cheat! Only return a single character since we have such a nice
*   readchar() function in VLT. One day I'll have to modify this to 
*   save the odd microsecond...
*/
   buff[0] = (unsigned char) readchar(secs, micros);
/*
*   VLT has a global called timeout. This comes in xfer.h.
*   If the read was successful, return having read a single character.
*/
   if (timeout == GOODREAD) return(1L);
/*
*   Else return error condition
*/
   return(-1L);
}

/**
*
*   Interfaces to stdio
*
**/
long vlt_fopen(s, t)
char *s, *t;
{
   return((long) fopen(s, t));
}

long vlt_fclose(fp)
FILE *fp;
{
   return((long) fclose(fp));
}

long vlt_fread(buff, size, count, fp)
char *buff;
long size, count;
FILE *fp;
{
   int res;
   res = fread(buff, (int) size, (int) count, fp);
   return((long) res);
}

/**
*
*   Check for Abort
*
**/
long vlt_chkabort()
{
/*
*   VLT aborts its protocols when the escape key is pressed.
*   CheckForKey loops over the UserPort messages looking for an escape.
*/
   return((long) CheckForKey(69));
}
