/* Comm XMODEM send routines */ #define XMDMSEND 1 #include "globals.h" #include extern void emit_tx(), emit_rx(), emits_tx(), emits_rx(); static int naks,errsect; static ULONG bytes; XMODEM_Send_File(file) UBYTE *file; { extern void purge_line(), send_proto(), report(); extern int read_proto(), readchar(); USHORT readstatus, status, timeoutcount; UBYTE ch; abort = cancel = FALSE; report(file); if ((fd = open(file, O_RDONLY)) < 0) { sprintf(sbuff,"\nCannot Open Send File %s\n",file); emits_rx(sbuff); send_proto(CAN); send_proto(CAN); return FALSE; } else emits_rx("Ready to send File -- ESC aborts transfer\n\n"); naks = errsect = bytes = 0; Xconfig(TRUE); /* set serial port to 8/N/1 */ sector = 1; timeoutcount = 0; purge_line(); /* flush any garbage in receiver */ do /* start handshake with receiver */ { ch = readchar(TTIME,TRUE); if(timeout) { if(++timeoutcount == RETRYMAX) { emits_rx("\nNo response, aborting\n"); return FALSE; } } if(abort || cancel ) return FALSE; } while (ch != NAK && ch != 'C' && ch != 'W'); if(ch == 'W') return WXMODEM_Send_File(file); status = OK; crcflag = (ch == 'C'); sprintf(sbuff,"%s mode requested\n",crcflag ? "\nCRC" : "\nChecksum"); emits_rx(sbuff); while( (readstatus = fillbuf()) && status == OK ) { /* fill file buffer until EOF */ if(readstatus == ERROR) /* or ERROR during read */ return FALSE; status = sendsector( xbuffer ); /* send sector */ sprintf(sbuff,"File: %s bytes= %ld naks= %d [ %d ]\r",file,bytes, naks,errsect); status_line(0,sbuff); Process_window_event(); } if(status == TIMEOUT || status == ABORT) return FALSE; timeoutcount = 0; do { purge_line(); send_proto( EOT ); /* end transmission */ if(timeout) if(timeoutcount++ == RETRYMAX || cancel || abort) return FALSE; } while ((ch = read_proto( TTIME, TRUE )) != ACK); close( fd ); return TRUE; } int fillbuf() { unsigned int bytes_read; bytes_read = read(fd, xbuffer, SECSIZ); if (bytes_read == -1) /* error during read */ return ERROR; if (bytes_read == 0) /* end of file */ return FALSE; if(bytes_read < SECSIZ) for(; bytes_read < SECSIZ; bytes_read++) xbuffer[bytes_read] = PAD; return TRUE; } /************************************** sendsector() transmits a single sector with retransmit on error from receiver ***************************************/ sendsector( buf ) UBYTE *buf; { extern void do_crc(), purge_line(), send_proto(); unsigned int i, badblock; badblock = 0; cancel = FALSE; while( TRUE ) { if( badblock == ERRORMAX ) return TIMEOUT; if( cancel || abort ) return ABORT; sprintf(sbuff,"\rTransmitting block %d",sector); emits_rx(sbuff); send_proto( SOH ); /* start of block */ send_proto( sector ); /* sector number */ send_proto( ~sector ); /* compliment of sector number */ checksum = crc = 0; /* clear CRC and checksum */ for( i = 0 ; i < SECSIZ ; i++ ) { if(buf[ i ] == '\n') if(asciiflg) buf[ i ] = 0x0D; sendchar(buf[ i ]); do_crc( buf[ i ] ); if(viewflg) emit_vw( buf[ i ] ); } purge_line(); /* flush garbage from receiver */ if( crcflag ) { do_crc(0); do_crc(0); /* cycle CRC generator */ send_proto( crc >> 8 ); /* High byte */ send_proto( crc ); /* Low byte */ } else send_proto( checksum ); if( read_proto(TTIME, TRUE ) == ACK) { bytes += SECSIZ; break; } else { badblock++; naks++; errsect = sector; } } sector++; /* bump sector count */ return OK; } read_proto(time,flag) int time,flag; { int ch; ch = readchar(time,flag); emit_rx_protocol(ch); return (ch); }