/* XMUTIL.C Xmodem utility procedures. Includes CRC generation and other * utility routines not in xmsend.c (send state machine) and * xmrecv.c (receive state machine) * GOAL: Provide high level interfaces to interrupt handler routines. * Includes init() which sits between interrupt handler and cterm. * NOTE: Do no printf's in this file. */ #include "commint.h" /* defines and structs for Turbo C int handler */ #include "cterm.h" /* project header goes here */ #include "commn.h" /* definition of S_INIT structure */ #define MAXJUNK 100 /* used by eat_noise */ /* Messages posted by A_Send_End and A_Recv_End */ char user_msg[] = "Terminated by user"; char nonak[] = "No initial NAK/CRC received"; char cancel[] = "Cancel Received"; char badcomm[] = "Problem Reading/Writing to comm port"; char badread[] = "Problem reading disk file"; char badwrite[] = "Problem writing disk file"; char eof_msg[] = "File successfully transferred"; char giveup[] = "Retries exhausted by NAK's and/or timeouts"; /* ------- External references */ extern int crc; /* external flag for CRC or Checksum */ extern void interrupt rxrdy_IH(); /* in module commint.c */ extern unsigned char getcomch(); extern S_INIT cur_config; /* Calls the following from commint.c module: extern int Remove_IH(); extern int Inst_IH(); */ /* Calls the following from ctermx.c module: extern int Config_Comm(); */ /* Export to xmsend and xmrecv routines */ unsigned crcaccum; unsigned char checksum; int crc = 1; /* flag for CRC (!0) or checksum (0) */ void updcrc( unsigned char c) { unsigned shifter, i, flag; if (crc) { for (shifter = 0x80; shifter; shifter >>= 1) { flag = (crcaccum & 0x8000); crcaccum <<= 1; crcaccum |= (shifter & c) ? 1 : 0; if (flag) crcaccum ^= 0x1021; } } else checksum += c; } /* ---------- read_comm ------------------------ * Does: Reads data from the comm port already opened. * Pass: by ref - number of bytes to read (returns actually read). * pointer to buffer for data * time to wait (in msecs) for completion. 0 = 1 test * Uses: TurboC 1.5+ specific delay() function. * Test show that delay() works reliably at 10 msecs (not 1) * Priority: If all char's read, returns before time expires. * Any time a receive error is detected, return immediately. * Returns: 0 if all read, TIMEOUT (define) if timeout. */ int read_comm( int *num, unsigned char *buf, int wait ) { int toread = *num; int redok = 0; unsigned char *cptr = buf; int wait10ms = wait / 10; if (wait10ms == 0) wait10ms = 1; /* add 1 in case under 10 */ do { if (incomm() != 0) { /* Data is waiting. Move it into buffer and get count read */ *cptr = getcomch(); /* Send to users buffer */ cptr++; redok++; } else if ( wait10ms ) { delay(10); /* Borland says 1 millisecond per... */ wait10ms--; } } while (!( (redok == toread) || (wait10ms == 0) )); *num = redok; /* return the actual number read via *num ref param */ return ( (wait10ms > 0) ? 0 : TIMEOUT ); } /* ---------- close_comm ------------------------ * Does: Closes the comm port previously opened by removing our interrupt * handler and returning the UART to the previous (saved) state. */ int close_comm() { Remove_IH(); } /* init ----- initialize params and installs interrupt handler. * Pass: Comm port number (1 or 2) to install and configure, bbsmode flag. * Does: Installs interrupt handler and sets comm port. * Sets comm parameters per struct passed. * Config_Comm publishes global baud rate for receiver timing. */ int init_comm( int comnum, int bbsconf ) { int retval; retval = Inst_IH(rxrdy_IH, comnum); if (retval != 0) { Remove_IH(); /* this could probably waste somebody else */ return(1); /* was exit(1) */ } if (bbsconf == 0) { cur_config.ubits.lctrl = sev1even; } else cur_config.ubits.lctrl = ate1none; Config_Comm(comnum, cur_config); return(0); }