home *** CD-ROM | disk | FTP | other *** search
- /** xprascii.c
- *
- * These are the protocol transfer routines for a simple ASCII upload.
- *
- **/
- #include <exec/exec.h>
- #include <functions.h>
- #include <stdio.h>
- /*
- * xproto.h is the include file given in Appendix B.
- */
- #include "xproto.h"
- /*
- * The following two strings must exist.
- */
- char XPRname[] = "xprascii.library";
- char XPRid[] = "xprascii 0.9 (May 89)\r\n";
- UWORD XPRrevision = 9;
-
- long atol();
- /*
- * The callxx...() routines are described later. They provide the
- * assembler interface from the XPR library to the call-back routines.
- */
- long calla(), callaa(), callad(), calladd(), calladda();
-
- char *malloc();
-
-
- /**
- *
- * Send a file
- *
- **/
- long XProtocolSend(IO)
- struct XPR_IO *IO;
- {
- long fp, r, i;
- long brkflag = 0, fl = 0L, sd = 0L;
- long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfread)(),
- (*xsread)(), (*xchkabort)();
- unsigned char *buff = NULL, *serbuff = NULL;
- struct XPR_UPDATE xpru;
-
- /*
- * These are the call-backs we need. If any of them isn't provided, quit.
- * Could do some error reporting if at least xupdate is there.
- */
- if ((xupdate = IO->xpr_update) == NULL) return(0L);
- if ((xswrite = IO->xpr_swrite) == NULL) return(0L);
- if ((xfopen = IO->xpr_fopen) == NULL) return(0L);
- if ((xfclose = IO->xpr_fclose) == NULL) return(0L);
- if ((xfread = IO->xpr_fread) == NULL) return(0L);
- if ((xsread = IO->xpr_sread) == NULL) return(0L);
- if ((xchkabort = IO->xpr_chkabort) == NULL) return(0L);
- /*
- * Allocate a few buffers.
- */
- buff = (unsigned char *) malloc(80);
- serbuff = (unsigned char *) malloc(80);
- /*
- * If we ran out of memory, print a message.
- * The argument needs to go in A0: calla does this for us.
- */
- if (buff == NULL || serbuff == NULL) {
- xpru.xpru_updatemask = XPRU_ERRORMSG;
- xpru.xpru_errormsg = "Ran out of memory!";
- calla(xupdate, &xpru);
- return(0L);
- }
- /*
- * Read the send delay, if a XProtocolSetup() was done before.
- * If send delay is too large, cut it off at 10 seconds.
- * In this example, the xpr_data field contains a null terminated string
- * containing the number of ticks to delay each 80 characters.
- */
- if (IO->xpr_data) {
- sd = atol(IO->xpr_data);
- if (sd > 500L) sd = 500L;
- }
- /*
- * Open the file. One could do wild card detection here.
- * xfopen requires two arguments, in a0 and a1 respectively.
- * Again, this must be done in assembler, and callaa does it.
- */
- fp = callaa(xfopen, IO->xpr_filename, "r");
- if (fp == NULL) {
- free(buff);
- free(serbuff);
- xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
- xpru.xpru_errormsg = "Failed to open input file";
- xpru.xpru_filename = IO->xpr_filename;
- calla(xupdate, &xpru);
- return(0L);
- }
- /*
- * Start the transfer. See 3.8 for a discussion on how to implement
- * xupdate.
- */
- xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
- xpru.xpru_msg = "Starting ASCII Send";
- xpru.xpru_filename = IO->xpr_filename;
- calla(xupdate, &xpru);
- /*
- * Now read 80 byte chunks from the file using xfread.
- * xfread requires four arguments, a0, d0, d1 and a1.
- */
- xpru.xpru_blocks = 0L;
- while (r = calladda(xfread, buff, 1L, 80L, fp)) {
- /*
- * Convert line feeds to carriage returns before sending to host.
- * fl counts the characters. Display how many characters are sent.
- */
- for (i = 0L; i < r; i++) if (buff[i] == '\n') buff[i] = '\r';
- fl += r;
- xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
- xpru.xpru_bytes = fl;
- xpru.xpru_blocks++;
- xpru.xpru_blocksize = r;
- calla(xupdate, &xpru);
- callad(xswrite, buff, r);
- /*
- * Every 80 bytes, put out a message and delay if requested.
- */
- xpru.xpru_updatemask = XPRU_PACKETDELAY;
- xpru.xpru_packetdelay = sd * 20L; /* msec! */
- calla(xupdate, &xpru);
- /*
- * Can't use Delay() here, because Delay() is in dos.library!
- * However writing an equivalent function using the timer.device is
- * trivial.
- */
- TimeOut(sd);
- /*
- * Eat any characters that might arrive from the serial port.
- * calladd stores arg1 in a0, arg2 in d0, arg3 in d1.
- * We're not really waiting for any characters: use a timeout of 0L.
- */
- while (calladd(xsread, serbuff, 80L, 0L) > 0L) ;
- /*
- * Check for "abort" here. Perhaps should call chkmisc() as well.
- */
- if (brkflag = xchkabort()) break;
- }
- /*
- * Close the file
- */
- calla(xfclose, fp);
- free(buff);
- free(serbuff);
- /*
- * If we got here through chkabort() say Aborted.
- */
- xpru.xpru_updatemask = XPRU_MSG;
- if (brkflag) xpru.xpru_msg = "Aborted";
- else xpru.xpru_msg = "Done";
- calla(xupdate, &xpru);
- if (brkflag) return(0L);
- else return(1L);
- }
-
-
- /**
- *
- * Receive a file.
- *
- **/
- long XProtocolReceive(IO)
- struct XPR_IO *IO;
- {
- long fp, r, i;
- long brkflag = 0, fl = 0L, sd = 0L;
- long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfwrite)(),
- (*xsread)(), (*xchkabort)();
- unsigned char *serbuff = NULL;
- struct XPR_UPDATE xpru;
-
- /*
- * These are the call-backs we need. If any of them isn't provided, quit.
- * Could do some error reporting if at least xupdate is there.
- */
- if ((xupdate = IO->xpr_update) == NULL) return(0L);
- if ((xswrite = IO->xpr_swrite) == NULL) return(0L);
- if ((xfopen = IO->xpr_fopen) == NULL) return(0L);
- if ((xfclose = IO->xpr_fclose) == NULL) return(0L);
- if ((xfwrite = IO->xpr_fwrite) == NULL) return(0L);
- if ((xsread = IO->xpr_sread) == NULL) return(0L);
- if ((xchkabort = IO->xpr_chkabort) == NULL) return(0L);
- /*
- * Allocate a buffer.
- */
- serbuff = (unsigned char *) malloc(80);
- /*
- * If we ran out of memory, print a message.
- * The argument needs to go in A0: calla does this for us.
- */
- if (serbuff == NULL) {
- xpru.xpru_updatemask = XPRU_ERRORMSG;
- xpru.xpru_errormsg = "Ran out of memory!";
- calla(xupdate, &xpru);
- return(0L);
- }
- /*
- * Open the file. One could do wild card detection here.
- * xfopen requires two arguments, in a0 and a1 respectively.
- * Again, this must be done in assembler, and callaa does it.
- */
- fp = callaa(xfopen, IO->xpr_filename, "w");
- if (fp == NULL) {
- free(serbuff);
- xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
- xpru.xpru_errormsg = "Failed to open output file";
- xpru.xpru_filename = IO->xpr_filename;
- calla(xupdate, &xpru);
- return(0L);
- }
- /*
- * Start the transfer. See 3.8 for a discussion on how to implement
- * xupdate.
- */
- xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
- xpru.xpru_msg = "Starting ASCII Receive";
- xpru.xpru_filename = IO->xpr_filename;
- calla(xupdate, &xpru);
- /*
- * Now read 80 byte chunks from the serial port using xsread. Stop
- * when no characters arrive for 5 sec.
- */
- xpru.xpru_blocks = 0L;
- while ((r = calladd(xsread, serbuff, 80L, 5000000L)) > 0L) {
- /*
- * Strip high-bit before storing in file.
- * fl counts the characters. Display how many characters are received.
- */
- for (i = 0L; i < r; i++) serbuff[i] &= 0177;
- fl += r;
- xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
- xpru.xpru_bytes = fl;
- xpru.xpru_blocks++;
- xpru.xpru_blocksize = r;
- calla(xupdate, &xpru);
- /*
- * Write 80 byte chunks to the file using xwrite
- */
- calladda(xfwrite, serbuff, 1L, r, fp);
-
- /*
- * Check for "abort" here. Perhaps should call chkmisc() as well.
- */
- if (brkflag = xchkabort()) break;
- }
- /*
- * Close the file
- */
- calla(xfclose, fp);
- free(serbuff);
- /*
- * If we got here through chkabort() say Aborted.
- */
- xpru.xpru_updatemask = XPRU_MSG;
- if (brkflag) xpru.xpru_msg = "Aborted";
- else xpru.xpru_msg = "Done";
- calla(xupdate, &xpru);
- if (brkflag) return(0L);
- else return(1L);
- }
-
-
- /**
- *
- * Setup
- *
- **/
- long XProtocolSetup(IO)
- struct XPR_IO *IO;
- {
- long (*xupdate)(), (*xgets)();
- struct XPR_UPDATE xpru;
-
- if ((xupdate = IO->xpr_update) == NULL) return(0L);
- if ((xgets = IO->xpr_gets) == NULL) return(0L);
- /*
- * Allocate a bit of memory for a data buffer
- */
- if (IO->xpr_data == NULL) {
- if ((IO->xpr_data = (long *) malloc(256)) == NULL) {
- xpru.xpru_updatemask = XPRU_ERRORMSG;
- xpru.xpru_errormsg = "ASCII - Out of memory!";
- calla(xupdate, &xpru);
- return(0L);
- }
- }
- /*
- * If setup string isn't handed to us, ask questions
- */
- if (IO->xpr_filename == NULL) {
- /*
- * Get the value for the send dealy
- */
- callaa(xgets, "Enter ASCII send delay (ticks, 1 tick = 20 msec)",
- IO->xpr_data);
- }
- else {
- strcpy(IO->xpr_data, IO->xpr_filename);
- }
-
- return(1L);
- }
-
- /**
- *
- * Cleanup
- *
- **/
- long XProtocolCleanup(IO)
- struct XPR_IO *IO;
- {
- if (IO->xpr_data) free(IO->xpr_data);
- IO->xpr_data = NULL;
-
- return(1L);
- }
-
- /**
- *
- * The following functions setup the proper registers for the call-back
- * functions.
- *
- **/
- #asm
- public _callad
- _callad:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 12(sp),d0 ; Third argument goes in d0
- /*
- * Now this is a trick to avoid using another register.
- * Charlie taught me this...
- */
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calladda
- _calladda:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 12(sp),d0 ; Third argument goes in d0
- move.l 16(sp),d1 ; Fourth argument goes in d1
- movea.l 20(sp),a1 ; Fifth argument goes in a1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calla
- _calla:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _callaa
- _callaa:
- movea.l 8(sp),a0 ; Second argument goes in a0
- movea.l 12(sp),a1 ; Third argument goes in a1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calladd
- _calladd:
- move.l 8(sp),a0 ; Second argument goes in a0
- move.l 12(sp),d0 ; Third argument goes in d0
- move.l 16(sp),d1 ; Fourth argument goes in d1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- #endasm
- /*
- * Could have added any other functions needed for other call-backs.
- * Could have written a fancier single one... Could've...
- */
-