home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / PROGRAM / PCL4C30.ZIP / XFER.C < prev    next >
Text File  |  1992-01-20  |  11KB  |  377 lines

  1. /*
  2. **                      ---  xfer.c ---
  3. **
  4. **   EXAMPLE CODE: Transfer files between PCs linked with a null
  5. **   modem cable. Start the receiving computer first by typing:
  6. **
  7. **     XFER port baudrate
  8. **
  9. **  Then start the sending computer by typing:
  10. **
  11. **     XFER port baudrate filename
  12. **
  13. **  Wildcards are OK. Example: "XFER 1 115200 *.DOC"
  14. **
  15. **  This example program (not the PCL4C library) is donated to
  16. **  the Public Domain by MarshallSoft Computing, Inc. It is
  17. **  provided as an example of the use of the PCL4C.
  18. **
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include <fcntl.h>
  24. #include <sys\types.h>
  25. #include <sys\stat.h>
  26. #include <io.h>
  27.  
  28. #include "pcl4c.h"
  29. #include "ascii.h"
  30.  
  31. #define FALSE 0
  32. #define TRUE !FALSE
  33. #define ONESECOND 18
  34. #define BLOCKSIZE 1000
  35. #define MAX_TRY 3
  36.  
  37. #define BYTE unsigned char
  38.  
  39. int Port;               /* current COM port [0..3] */
  40. char Filename[15];      /* file name buffer */
  41. char RxBuf[1024];   /* PCL receive buffer */
  42. char *BaudRate[10] =    {"300","600","1200","2400","4800","9600",
  43.                         "19200","38400","57600","115200"};
  44. int BaudCode;           /* baud rate code ( index into BaudRate[] ) */
  45.  
  46. int IsMaster;           /* TRUE if MASTER, else SLAVE */
  47. char DTAbuffer[128];    /* Disk Transfer Address Buffer */
  48. int ResetAOK = FALSE;   /* TRUE is SioReset() successfull */
  49.  
  50.  
  51. main(argc,argv)
  52. int argc;
  53. char *argv[];
  54. {char Mode;
  55.  char c;
  56.  int i, Code;
  57.  char FileSpec[64];      /* File spec for file transfer */
  58.  /* sign on */
  59.  printf("XFER 1.0: Start receiver before sender\n");
  60.  /* get port from command line */
  61.  if((argc<3)||(argc>4)) ShowUseage("Expect 3 or 4 parameters");
  62.  Port = atoi(argv[1]) - 1;
  63.  if((Port<0) || (Port>3)) ShowUseage("COM must be COM1 to COM4");
  64.  /* get baud rate from command line */
  65.  BaudCode = BaudMatch(argv[2]);
  66.  if(BaudCode<0) ShowUseage("Cannot recognize baud rate");
  67.  /* MASTER will have file spec as 4th argument */
  68.  if(argc==4)
  69.    {strcpy(FileSpec,argv[3]);
  70.     IsMaster = TRUE;
  71.    }
  72.  else IsMaster = FALSE;
  73.  /* init CRC table */
  74.  InitCRC();
  75.  /* setup receive 1K Rx buffer */
  76.  CheckCode(  SioRxBuf(Port,RxBuf,Size1024),"Error calling SioRxBuf()");
  77.  /* set parms & reset (initialize) COM port */
  78.  CheckCode( SioParms(Port,NoParity,OneStopBit,WordLength8),
  79.          "Error calling SioParms()" );
  80.  MyStart(Port,BaudCode);
  81.  CheckCode( SioRxFlush(Port),"Error calling SioRxFlush");
  82.  /* Continue as MASTER or SLAVE */
  83.  if(IsMaster)
  84.    {printf("MASTER ");
  85.     /* wait 1 minute for receivers NAK */
  86.     Code = SioGetc(Port,60*ONESECOND);
  87.     /* ignore an initial 00H */
  88.     if(Code==0) Code = SioGetc(Port,ONESECOND);
  89.     /* timeout ? */
  90.     CheckCode(Code,"waiting for receiver");
  91.     /* get something - should be NAK */
  92.     if((char)Code==NAK)
  93.        {/* Receiver is ready */
  94.         SioPutc(Port,ACK);
  95.         puts("CONNECTED");
  96.        }
  97.     else MyExit("Expecting initial NAK not %x\n",Code);
  98.     /* set DTA */
  99.     setDTA(DTAbuffer);
  100.     /* find 1st matching file */
  101.     if(FindFirst(FileSpec))
  102.        {Transmit(Port,&DTAbuffer[30]);
  103.         /* find remaining files */
  104.         while( FindNext() )
  105.            {SioDelay(4);
  106.             Transmit(Port,&DTAbuffer[30]);
  107.            }
  108.         SioPutc(Port,EOT);
  109.         SioPutc(Port,EOT);
  110.        }
  111.     else puts("No files found");
  112.    }
  113.  else /* SLAVE */
  114.    {printf("SLAVE ");
  115.     /* transmit NAKs until get ACK/EOT back */
  116.     for(i=60;i>0;i--)
  117.        {SioPutc(Port,NAK);
  118.         SioCrtWrite('.');
  119.         Code = SioGetc(Port,ONESECOND);
  120.         if(Code==-1) {if(i==1) MyExit("Transmitter not ready");
  121.                       else continue;
  122.                      }
  123.         CheckCode(Code,"waiting for transmitter");
  124.         if((char)Code==ACK) break;
  125.         if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
  126.        }
  127.     /* receive until timeout or get EOT */
  128.     puts("CONNECTED");
  129.     while(Receive(Port)) ;
  130.    }
  131.  /* all done */
  132.  SioDone(Port);
  133.  puts("All done");
  134. }
  135.  
  136. int Transmit(Port,NamePtr)
  137. int Port;
  138. char *NamePtr;
  139. {int i, Code;
  140.  int BlockLen;
  141.  int Handle;
  142.  unsigned short UpdateCRC();
  143.  unsigned short ComputedCRC;
  144.  char Temp[80];
  145.  BYTE Buffer[1001];
  146.  long filelength();
  147.  int Try;
  148.  /* begin */
  149.  Handle = open(NamePtr,O_RDONLY|O_BINARY,S_IREAD);
  150.  if(Handle<0)
  151.    {printf("Cannot open %s for read\n",NamePtr);
  152.     return(FALSE);
  153.    }
  154.  printf("\nSending %s ( %ld bytes ) ",NamePtr,filelength(Handle));
  155.  /* send SOH */
  156.  CheckCode( SioPutc(Port,SOH), "Error sending SOH");
  157.  /* send file name */
  158.  for(i=0;i<strlen(NamePtr);i++) SioPutc(Port,NamePtr[i]);
  159.  SioPutc(Port,'\0');
  160.  /* send file BLOCKSIZE bytes at a time */
  161.  while(TRUE)
  162.    {BlockLen = read(Handle,Buffer,BLOCKSIZE);
  163.     if(BlockLen==0) break;
  164.     if(BlockLen<0) MyExit("Disk I/O error");
  165.     /* send block length */
  166.     SioPutc(Port,0x00ff&(BlockLen>>8));
  167.     if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
  168.     SioPutc(Port,0x00ff&BlockLen);
  169.     /* send block */
  170.     for(Try=1;Try<=MAX_TRY;Try++)
  171.        {ComputedCRC = 0;
  172.         for(i=0;i<BlockLen;i++)
  173.           {
  174.            ComputedCRC = UpdateCRC(ComputedCRC,Buffer[i]);
  175.            SioPutc(Port,Buffer[i]);
  176.            if(SioBrkKey()) MyExit("BREAK");
  177.           } /* end for */
  178.        /* send CRC */
  179.        SioPutc(Port,(ComputedCRC >> 8) & 0x00ff);
  180.        if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
  181.        SioPutc(Port,ComputedCRC & 0x00ff);
  182.        /* wait for ACK */
  183.        Code = SioGetc(Port,8*ONESECOND);
  184.        CheckCode(Code,"waiting for block ACK");
  185.        /* if received ACK then we are done with this block */
  186.        if((char)Code==ACK)
  187.           {printf(".");
  188.            break;
  189.           }
  190.        /* if received NAK then try again if haven't exceeded MAX_TRY */
  191.        if((char)Code==NAK)
  192.           {printf("?");
  193.            if(Try==MAX_TRY) MyExit("Block was NAKed");
  194.           }
  195.        else
  196.           {sprintf(Temp,"Expecting ACK/NAK not %x",(char)Code);
  197.            MyExit(Temp);
  198.           }
  199.       } /* end for */
  200.    } /* end while */
  201.  /* send BlockLen = 0000H to say we are all done */
  202.  SioPutc(Port,'\0');
  203.  SioDelay(4);
  204.  SioPutc(Port,'\0');
  205.  close(Handle);
  206.  puts("OK");
  207. } /* end Transmit */
  208.  
  209. int Receive(Port)
  210. int Port;
  211. {int Handle;
  212.  char NamePtr[40];
  213.  int i, n, Code;
  214.  int BlockLen;
  215.  unsigned short UpdateCRC();
  216.  unsigned short HiCRC;
  217.  unsigned short LoCRC;
  218.  unsigned short CRC;
  219.  unsigned short ComputedCRC;
  220.  char Temp[80];
  221.  char Buffer[1001];
  222.  int Try;
  223.  /* wait up to 60 seconds for an SOH or EOT */
  224.  Code = SioGetc(Port,60*ONESECOND);
  225.  /* disregard an initial 00H */
  226.  if(Code==0) SioGetc(Port,ONESECOND);
  227.  if(Code==-1) MyExit("Timed out waiting for next file");
  228.  CheckCode(Code,"waiting for next file");
  229.  /* return FALSE if no more files to receive */
  230.  if((char)Code==EOT) return(FALSE);
  231.  if((char)Code!=SOH)
  232.     {sprintf(Temp,"Expecting SOH/EOT instead of 0x%x",(char)Code);
  233.      MyExit(Temp);
  234.     }
  235.  /* get file name */
  236.  i = 0;
  237.  while(TRUE)
  238.    {Code = SioGetc(Port,ONESECOND);
  239.     CheckCode(Code,"waiting for filename");
  240.     NamePtr[i++] = (char)Code;
  241.     if((char)Code=='\0') break;
  242.    }
  243.  printf("\nReceiving %s ",NamePtr);
  244.  /* open for write */
  245.  Handle = open(NamePtr,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IWRITE);
  246.  if(Handle<0)
  247.    {printf("Cannot open %s for write\n",NamePtr);
  248.     return(FALSE);
  249.    }
  250.  while(TRUE)
  251.    {if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
  252.     /* get block length */
  253.     Code = SioGetc(Port,7*ONESECOND);
  254.     CheckCode(Code,"waiting for block length 1");
  255.     BlockLen = 0xff00 & ( Code << 8 );
  256.     Code = SioGetc(Port,ONESECOND);
  257.     CheckCode(Code,"waiting for block length 2");
  258.     BlockLen += (0x00ff & Code);
  259.     /* another block ? */
  260.     if(BlockLen==0)
  261.        {close(Handle);
  262.         puts("OK");
  263.         return(TRUE);
  264.        }
  265.     /* make MAX_TRY attempts to receive block */
  266.     for(Try=1;Try<MAX_TRY;Try++)
  267.        {/* receive block */
  268.         ComputedCRC = 0;
  269.         for(i=0;i<BlockLen;i++)
  270.           {Code = SioGetc(Port,ONESECOND);
  271.            CheckCode(Code,"waiting for data byte");
  272.            Buffer[i] = Code;
  273.            ComputedCRC = UpdateCRC(ComputedCRC,Buffer[i]);
  274.           } /* end for */
  275.        /* get CRC */
  276.        Code = SioGetc(Port,ONESECOND);
  277.        if(Code>=0) HiCRC = Code & 0x00ff;
  278.        else CheckCode(Code,"waiting for CRC 1");
  279.        Code = SioGetc(Port,ONESECOND);
  280.        if(Code>=0) LoCRC = Code & 0x00ff;
  281.        else CheckCode(Code,"waiting for CRC 2");
  282.        CRC = (HiCRC << 8) | LoCRC;
  283.        /* is CRC correct ? */
  284.        if(CRC==ComputedCRC)
  285.           {/* write to disk */
  286.            n = write(Handle,Buffer,BlockLen);
  287.            if(n<0) MyExit("Disk I/O error");
  288.            /* ACK the block */
  289.            SioPutc(Port,ACK);
  290.            printf(".");
  291.            break;
  292.           }
  293.        else /* bad CRC */
  294.           {SioPutc(Port,NAK);
  295.            printf("?");
  296.            if(Try==MAX_TRY)
  297.               {
  298.                sprintf(Temp,"Bad CRC: Computed=%x Received=%x",
  299.                  ComputedCRC,CRC);
  300.                MyExit(Temp);
  301.               }
  302.           }
  303.       } /* end for */
  304.    } /* end while */
  305. }
  306.  
  307. int ShowUseage(Msg)
  308. char *Msg;
  309. {if(Msg) puts(Msg);
  310.  printf("\nUsage:   'XFER <port> <baud> {file-spec}' \n");
  311.  printf("  <port> = 1 to 4\n");
  312.  printf("  <baud> = 300,600,1200,2400,4800,38400,57600,115200\n");
  313.  printf("  {file-spec} = File specification for MASTER\n");
  314.  printf("EXAMPLE:\n");
  315.  printf("  SLAVE Side:  'XFER 1 115200'\n");
  316.  printf("  MASTER Side: 'XFER 4 115200 *.ASM'\n");
  317.  printf("NOTES: Start SLAVE (receiver) before MASTER (sender)\n");
  318.  printf("       Be sure to specify the same baud rate on both sides\n");
  319.  exit(1);
  320. }
  321.  
  322. int MyStart(Port,BaudCode)
  323. int Port;
  324. int BaudCode;
  325. {int i, Code;
  326.  int Attempt;
  327.  /* try up to 3 times to reset COM port */
  328.  for(Attempt=0;Attempt<3;Attempt++)
  329.      {/* attempt to reset port */
  330.       Code = SioReset(Port,BaudCode);
  331.       if(Code==0)
  332.          {printf("COM%d reset at %s baud\n",Port+1,BaudRate[BaudCode]);
  333.           ResetAOK = TRUE;
  334.           return(TRUE);
  335.          }
  336.       if(Code<0) CheckCode(Code,"Cannot reset COM%d",1+Port);
  337.       /* display errors ( Code > 0 ) */
  338.       if(Code&OverrunError) puts("Overrun Error");
  339.       if(Code&ParityError)  puts("Parity Error");
  340.       if(Code&FramingError) puts("Framing Error");
  341.       if(Code&BreakDetect)  puts("Break Detect");
  342.       SioDelay(8);
  343.      }
  344.  printf("Cannot reset COM%d after 5 attempts\n",1+Port);
  345.  exit(1);
  346. }
  347.  
  348. int BaudMatch(ptr)
  349. char *ptr;
  350. {int i;
  351.  /* find baud rate in table */
  352.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  353.  return(-1);
  354. }
  355.  
  356. int MyExit(MsgPtr)
  357. char *MsgPtr;
  358. {if(MsgPtr) puts(MsgPtr);
  359.  if(ResetAOK) SioDone(Port);
  360.  exit(1);
  361. }
  362.  
  363. int CheckCode(Code,MsgPtr)
  364. int Code;
  365. char *MsgPtr;
  366. {/* no error if Code >= 0 */
  367.  if(Code>=0) return(Code);
  368.  /* Display messages */
  369.  printf("\nERROR: ");
  370.  if(MsgPtr) puts(MsgPtr);
  371.  SioError(Code);
  372.  /* Assert UART break & sign off */
  373.  SioBrkSig(Port,'A');
  374.  SioDelay(8);
  375.  if(ResetAOK) SioDone(Port);
  376.  exit(1);
  377. }