home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
PCL4C30.ZIP
/
XFER.C
< prev
next >
Wrap
Text File
|
1992-01-20
|
11KB
|
377 lines
/*
** --- xfer.c ---
**
** EXAMPLE CODE: Transfer files between PCs linked with a null
** modem cable. Start the receiving computer first by typing:
**
** XFER port baudrate
**
** Then start the sending computer by typing:
**
** XFER port baudrate filename
**
** Wildcards are OK. Example: "XFER 1 115200 *.DOC"
**
** This example program (not the PCL4C library) is donated to
** the Public Domain by MarshallSoft Computing, Inc. It is
** provided as an example of the use of the PCL4C.
**
*/
#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include "pcl4c.h"
#include "ascii.h"
#define FALSE 0
#define TRUE !FALSE
#define ONESECOND 18
#define BLOCKSIZE 1000
#define MAX_TRY 3
#define BYTE unsigned char
int Port; /* current COM port [0..3] */
char Filename[15]; /* file name buffer */
char RxBuf[1024]; /* PCL receive buffer */
char *BaudRate[10] = {"300","600","1200","2400","4800","9600",
"19200","38400","57600","115200"};
int BaudCode; /* baud rate code ( index into BaudRate[] ) */
int IsMaster; /* TRUE if MASTER, else SLAVE */
char DTAbuffer[128]; /* Disk Transfer Address Buffer */
int ResetAOK = FALSE; /* TRUE is SioReset() successfull */
main(argc,argv)
int argc;
char *argv[];
{char Mode;
char c;
int i, Code;
char FileSpec[64]; /* File spec for file transfer */
/* sign on */
printf("XFER 1.0: Start receiver before sender\n");
/* get port from command line */
if((argc<3)||(argc>4)) ShowUseage("Expect 3 or 4 parameters");
Port = atoi(argv[1]) - 1;
if((Port<0) || (Port>3)) ShowUseage("COM must be COM1 to COM4");
/* get baud rate from command line */
BaudCode = BaudMatch(argv[2]);
if(BaudCode<0) ShowUseage("Cannot recognize baud rate");
/* MASTER will have file spec as 4th argument */
if(argc==4)
{strcpy(FileSpec,argv[3]);
IsMaster = TRUE;
}
else IsMaster = FALSE;
/* init CRC table */
InitCRC();
/* setup receive 1K Rx buffer */
CheckCode( SioRxBuf(Port,RxBuf,Size1024),"Error calling SioRxBuf()");
/* set parms & reset (initialize) COM port */
CheckCode( SioParms(Port,NoParity,OneStopBit,WordLength8),
"Error calling SioParms()" );
MyStart(Port,BaudCode);
CheckCode( SioRxFlush(Port),"Error calling SioRxFlush");
/* Continue as MASTER or SLAVE */
if(IsMaster)
{printf("MASTER ");
/* wait 1 minute for receivers NAK */
Code = SioGetc(Port,60*ONESECOND);
/* ignore an initial 00H */
if(Code==0) Code = SioGetc(Port,ONESECOND);
/* timeout ? */
CheckCode(Code,"waiting for receiver");
/* get something - should be NAK */
if((char)Code==NAK)
{/* Receiver is ready */
SioPutc(Port,ACK);
puts("CONNECTED");
}
else MyExit("Expecting initial NAK not %x\n",Code);
/* set DTA */
setDTA(DTAbuffer);
/* find 1st matching file */
if(FindFirst(FileSpec))
{Transmit(Port,&DTAbuffer[30]);
/* find remaining files */
while( FindNext() )
{SioDelay(4);
Transmit(Port,&DTAbuffer[30]);
}
SioPutc(Port,EOT);
SioPutc(Port,EOT);
}
else puts("No files found");
}
else /* SLAVE */
{printf("SLAVE ");
/* transmit NAKs until get ACK/EOT back */
for(i=60;i>0;i--)
{SioPutc(Port,NAK);
SioCrtWrite('.');
Code = SioGetc(Port,ONESECOND);
if(Code==-1) {if(i==1) MyExit("Transmitter not ready");
else continue;
}
CheckCode(Code,"waiting for transmitter");
if((char)Code==ACK) break;
if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
}
/* receive until timeout or get EOT */
puts("CONNECTED");
while(Receive(Port)) ;
}
/* all done */
SioDone(Port);
puts("All done");
}
int Transmit(Port,NamePtr)
int Port;
char *NamePtr;
{int i, Code;
int BlockLen;
int Handle;
unsigned short UpdateCRC();
unsigned short ComputedCRC;
char Temp[80];
BYTE Buffer[1001];
long filelength();
int Try;
/* begin */
Handle = open(NamePtr,O_RDONLY|O_BINARY,S_IREAD);
if(Handle<0)
{printf("Cannot open %s for read\n",NamePtr);
return(FALSE);
}
printf("\nSending %s ( %ld bytes ) ",NamePtr,filelength(Handle));
/* send SOH */
CheckCode( SioPutc(Port,SOH), "Error sending SOH");
/* send file name */
for(i=0;i<strlen(NamePtr);i++) SioPutc(Port,NamePtr[i]);
SioPutc(Port,'\0');
/* send file BLOCKSIZE bytes at a time */
while(TRUE)
{BlockLen = read(Handle,Buffer,BLOCKSIZE);
if(BlockLen==0) break;
if(BlockLen<0) MyExit("Disk I/O error");
/* send block length */
SioPutc(Port,0x00ff&(BlockLen>>8));
if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
SioPutc(Port,0x00ff&BlockLen);
/* send block */
for(Try=1;Try<=MAX_TRY;Try++)
{ComputedCRC = 0;
for(i=0;i<BlockLen;i++)
{
ComputedCRC = UpdateCRC(ComputedCRC,Buffer[i]);
SioPutc(Port,Buffer[i]);
if(SioBrkKey()) MyExit("BREAK");
} /* end for */
/* send CRC */
SioPutc(Port,(ComputedCRC >> 8) & 0x00ff);
if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
SioPutc(Port,ComputedCRC & 0x00ff);
/* wait for ACK */
Code = SioGetc(Port,8*ONESECOND);
CheckCode(Code,"waiting for block ACK");
/* if received ACK then we are done with this block */
if((char)Code==ACK)
{printf(".");
break;
}
/* if received NAK then try again if haven't exceeded MAX_TRY */
if((char)Code==NAK)
{printf("?");
if(Try==MAX_TRY) MyExit("Block was NAKed");
}
else
{sprintf(Temp,"Expecting ACK/NAK not %x",(char)Code);
MyExit(Temp);
}
} /* end for */
} /* end while */
/* send BlockLen = 0000H to say we are all done */
SioPutc(Port,'\0');
SioDelay(4);
SioPutc(Port,'\0');
close(Handle);
puts("OK");
} /* end Transmit */
int Receive(Port)
int Port;
{int Handle;
char NamePtr[40];
int i, n, Code;
int BlockLen;
unsigned short UpdateCRC();
unsigned short HiCRC;
unsigned short LoCRC;
unsigned short CRC;
unsigned short ComputedCRC;
char Temp[80];
char Buffer[1001];
int Try;
/* wait up to 60 seconds for an SOH or EOT */
Code = SioGetc(Port,60*ONESECOND);
/* disregard an initial 00H */
if(Code==0) SioGetc(Port,ONESECOND);
if(Code==-1) MyExit("Timed out waiting for next file");
CheckCode(Code,"waiting for next file");
/* return FALSE if no more files to receive */
if((char)Code==EOT) return(FALSE);
if((char)Code!=SOH)
{sprintf(Temp,"Expecting SOH/EOT instead of 0x%x",(char)Code);
MyExit(Temp);
}
/* get file name */
i = 0;
while(TRUE)
{Code = SioGetc(Port,ONESECOND);
CheckCode(Code,"waiting for filename");
NamePtr[i++] = (char)Code;
if((char)Code=='\0') break;
}
printf("\nReceiving %s ",NamePtr);
/* open for write */
Handle = open(NamePtr,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IWRITE);
if(Handle<0)
{printf("Cannot open %s for write\n",NamePtr);
return(FALSE);
}
while(TRUE)
{if(SioBrkKey()) MyExit("User pressed CTRL-BREAK !");
/* get block length */
Code = SioGetc(Port,7*ONESECOND);
CheckCode(Code,"waiting for block length 1");
BlockLen = 0xff00 & ( Code << 8 );
Code = SioGetc(Port,ONESECOND);
CheckCode(Code,"waiting for block length 2");
BlockLen += (0x00ff & Code);
/* another block ? */
if(BlockLen==0)
{close(Handle);
puts("OK");
return(TRUE);
}
/* make MAX_TRY attempts to receive block */
for(Try=1;Try<MAX_TRY;Try++)
{/* receive block */
ComputedCRC = 0;
for(i=0;i<BlockLen;i++)
{Code = SioGetc(Port,ONESECOND);
CheckCode(Code,"waiting for data byte");
Buffer[i] = Code;
ComputedCRC = UpdateCRC(ComputedCRC,Buffer[i]);
} /* end for */
/* get CRC */
Code = SioGetc(Port,ONESECOND);
if(Code>=0) HiCRC = Code & 0x00ff;
else CheckCode(Code,"waiting for CRC 1");
Code = SioGetc(Port,ONESECOND);
if(Code>=0) LoCRC = Code & 0x00ff;
else CheckCode(Code,"waiting for CRC 2");
CRC = (HiCRC << 8) | LoCRC;
/* is CRC correct ? */
if(CRC==ComputedCRC)
{/* write to disk */
n = write(Handle,Buffer,BlockLen);
if(n<0) MyExit("Disk I/O error");
/* ACK the block */
SioPutc(Port,ACK);
printf(".");
break;
}
else /* bad CRC */
{SioPutc(Port,NAK);
printf("?");
if(Try==MAX_TRY)
{
sprintf(Temp,"Bad CRC: Computed=%x Received=%x",
ComputedCRC,CRC);
MyExit(Temp);
}
}
} /* end for */
} /* end while */
}
int ShowUseage(Msg)
char *Msg;
{if(Msg) puts(Msg);
printf("\nUsage: 'XFER <port> <baud> {file-spec}' \n");
printf(" <port> = 1 to 4\n");
printf(" <baud> = 300,600,1200,2400,4800,38400,57600,115200\n");
printf(" {file-spec} = File specification for MASTER\n");
printf("EXAMPLE:\n");
printf(" SLAVE Side: 'XFER 1 115200'\n");
printf(" MASTER Side: 'XFER 4 115200 *.ASM'\n");
printf("NOTES: Start SLAVE (receiver) before MASTER (sender)\n");
printf(" Be sure to specify the same baud rate on both sides\n");
exit(1);
}
int MyStart(Port,BaudCode)
int Port;
int BaudCode;
{int i, Code;
int Attempt;
/* try up to 3 times to reset COM port */
for(Attempt=0;Attempt<3;Attempt++)
{/* attempt to reset port */
Code = SioReset(Port,BaudCode);
if(Code==0)
{printf("COM%d reset at %s baud\n",Port+1,BaudRate[BaudCode]);
ResetAOK = TRUE;
return(TRUE);
}
if(Code<0) CheckCode(Code,"Cannot reset COM%d",1+Port);
/* display errors ( Code > 0 ) */
if(Code&OverrunError) puts("Overrun Error");
if(Code&ParityError) puts("Parity Error");
if(Code&FramingError) puts("Framing Error");
if(Code&BreakDetect) puts("Break Detect");
SioDelay(8);
}
printf("Cannot reset COM%d after 5 attempts\n",1+Port);
exit(1);
}
int BaudMatch(ptr)
char *ptr;
{int i;
/* find baud rate in table */
for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
return(-1);
}
int MyExit(MsgPtr)
char *MsgPtr;
{if(MsgPtr) puts(MsgPtr);
if(ResetAOK) SioDone(Port);
exit(1);
}
int CheckCode(Code,MsgPtr)
int Code;
char *MsgPtr;
{/* no error if Code >= 0 */
if(Code>=0) return(Code);
/* Display messages */
printf("\nERROR: ");
if(MsgPtr) puts(MsgPtr);
SioError(Code);
/* Assert UART break & sign off */
SioBrkSig(Port,'A');
SioDelay(8);
if(ResetAOK) SioDone(Port);
exit(1);
}