head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.16.21; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @/************************************************************************/ /* Copyright 1998 MBARI */ /************************************************************************/ /* $Header: ymodem.c,v 1.1 2001/06/19 11:45:17 oasisa Exp $ */ /* Summary : YModem Protocol Handler for OASIS Mooring Controller */ /* Filename : ymodem.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 1.1 $ */ /* Created : 08/20/98 */ /* Comment : Adapted from xmodem program by Steve Grandi, grandi@@noao.edu*/ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /************************************************************************/ /* Modification History: */ /* 20aug98 rah, created */ /* $Log: ymodem.c,v $ * Revision 1.1 2001/06/19 11:45:17 11:45:17 oasisa (Oasis users) * Initial revision * * Revision 4.2 98/09/09 10:55:44 10:55:44 bobh (Bob Herlien) * Sept/Oct '98 deployments of M1, Eqpac 1 & 2 * */ /************************************************************************/ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* ARGOS_BIT definition */ #include /* Log record definitions */ #include /* OASIS Multitasking definitions */ #include /* Standard I/O */ #include /* String functions */ #include /* YModem protocol definitions */ #ifdef YMODEM typedef struct /************************************/ { /* LogBuf - Buffer for LogRec */ LogPtr logP; /* Record ptr into Log memory */ Nat16 endBlk; /* Last Log block to send */ Nat16 logBytesSent; /* Number bytes of logBuf already sent*/ LogRec logBuf; /* Log Record Buffer */ char ymdmBuf[YBUFSIZE]; /* YModem send buffer */ } YMdmStruct; /************************************/ /********************************/ /* External Data */ /********************************/ Extern LogPtr nextFreeLog; /* Next record to log */ /********************************/ /* External Functions */ /********************************/ Extern char *tmpMalloc( Nat16 size ); Extern Void tmpFree( char *ptr ); Extern Void bcopy( const Byte *src, Byte *dst, Nat16 len ); Extern Void bzero( void *s, int n ); /* Zero memory */ Extern Void doputc( Int16 c ); Extern Void xputs( const char *s ); Extern Void xputn( const char *s, Int16 len ); Extern Int16 xgetc_tmout( Nat16 tmout ); Extern Void xflush_ser( Nat16 tmout ); Extern Void xprintf( const char *format, ... ); Extern LogRtn isLogged( LogPtr *lp ); Extern MBool logGetRec( LogPtr *lp, LogRec *logp ); Extern Nat16 calcYModemCRC( char *p, Nat16 len ); Extern Nat16 calcYModemChksum( char *p, Nat16 len ); Extern char *decToAscii( char *buff, Nat16 val ); /********************************/ /* Global Data */ /********************************/ Global Nat16 ymodemFileNum; /* Number part of file name */ /* e.g., "ep1.0000" */ /************************************************************************/ /* Function : ymdmSyncProtocol */ /* Purpose : Get the protocol sync character */ /* Inputs : Time to wait in seconds */ /* Outputs : Sync char or ERROR */ /************************************************************************/ Int16 ymdmSyncProtocol( Nat16 waitTime ) { Reg Int16 ch; Nat16 cnt; for( cnt = 0; cnt < waitTime; cnt++ ) { ch = xgetc_tmout(1); if ( (ch == CRCCHR) || (ch == GCHR) || (ch == NAK) ) return( ch ); if ( (ch == CAN) && (xgetc_tmout(2) == CAN) ) return( ERROR ); } return( ERROR ); } /* ymdmSyncProtocol() */ /************************************************************************/ /* Function : ymdmSendPkt */ /* Purpose : Send one YModem packet */ /* Inputs : Packet, packet number, packet size, flags word */ /* Outputs : OK or ERROR */ /************************************************************************/ Int16 ymdmSendPkt( char *ymdmBuf, Nat16 pktNum, Nat16 pktSize, Word flags ) { Nat16 errCnt, crc; Reg Int16 ch; if ( flags & CRCFLAG ) crc = calcYModemCRC(ymdmBuf, pktSize); else crc = calcYModemChksum(ymdmBuf, pktSize); for ( errCnt = 0; errCnt < ERRORMAX; errCnt++ ) { xflush_ser( 0 ); doputc( (pktSize == SMPKTSIZE) ? SOH : STX ); doputc( pktNum ); doputc( ~pktNum ); xputn( ymdmBuf, pktSize ); if ( flags & CRCFLAG ) doputc( crc >> 8 ); doputc( crc ); if ( (flags & GFLAG) || ((ch = xgetc_tmout(2)) == ACK) ) return( OK ); if ( (ch == CAN) && (xgetc_tmout(2) == CAN) ) return( ERROR ); } return( ERROR ); } /* ymdmSendPkt() */ /************************************************************************/ /* Function : ymdmSendFileName */ /* Purpose : Start YModem protocol, send pkt 0 with file name */ /* Inputs : File name, packet buffer */ /* Outputs : Flag word or ERROR */ /************************************************************************/ Word ymdmSendFileName( char *fileName, char *ymdmBuf ) { Word flags; switch( ymdmSyncProtocol(NAKMAX) ) { case CRCCHR: flags = KPKT | CRCFLAG; break; case GCHR: flags = KPKT | CRCFLAG | GFLAG; break; case NAK: return( 0 ); default: return( ERROR ); } bzero( ymdmBuf, YBUFSIZE ); strcpy( ymdmBuf, fileName); if ( ymdmSendPkt(ymdmBuf, 0, SMPKTSIZE, flags) != OK ) return( ERROR ); return( flags ); } /* ymdmSendFileName() */ /************************************************************************/ /* Function : ymdmGetData */ /* Purpose : Get Log Data to send via YModem */ /* Inputs : YMdmStruct */ /* Outputs : Number of bytes in ymdmBuf */ /************************************************************************/ Int16 ymdmGetData( YMdmStruct *ymdmP ) { Int16 pktBytes; Reg Int16 copyBytes, logBytes; bzero( ymdmP->ymdmBuf, YBUFSIZE ); for ( pktBytes = 0; pktBytes < LGPKTSIZE; ) { logBytes = ymdmP->logBuf.log_hdr.log_len + sizeof(LogRecHdr) - ymdmP->logBytesSent; if ( logBytes <= 0 ) { /* Get next log record */ while ( !logGetRec(&ymdmP->logP, &ymdmP->logBuf) ) { /* If no rcd in this blk, go to next*/ if ( ++ymdmP->logP.lp_blk > ymdmP->endBlk ) return( pktBytes ); ymdmP->logP.lp_addr = LOG_START_ADDR; ymdmP->logP.lp_rcd = 0; } ymdmP->logBytesSent = 0; } else { copyBytes = LGPKTSIZE - pktBytes; if ( logBytes < copyBytes ) copyBytes = logBytes; bcopy( (Byte *)(&ymdmP->logBuf) + ymdmP->logBytesSent, (Byte *)ymdmP->ymdmBuf + pktBytes, copyBytes ); pktBytes += copyBytes; ymdmP->logBytesSent += copyBytes; } } return( pktBytes ); } /* ymdmGetData() */ /************************************************************************/ /* Function : ymdmSendFile */ /* Purpose : Send log data via YMODEM */ /* Inputs : YMdmStruct */ /* Outputs : OK or ERROR */ /************************************************************************/ Int16 ymdmSendFile( YMdmStruct *ymdmP ) { Word flags; Nat16 pktNum; Int16 bytesToSend; char *pktP; char nameBuf[32]; /* Send file name, then resync the protocol */ strcpy( nameBuf, YMODEM_FILENAME); decToAscii( nameBuf + YMODEM_NAMESIZE, ymodemFileNum ); if ( (flags = ymdmSendFileName(nameBuf, ymdmP->ymdmBuf)) == ERROR ) return( ERROR ); if ( flags ) /* If not XMODEM, resync */ if ( ymdmSyncProtocol(RESYNCMAX) == ERROR ) return( ERROR ); /* Send the data */ pktNum = 1; ymodemFileNum++; while ( (bytesToSend = ymdmGetData(ymdmP)) > 0 ) { pktP = ymdmP->ymdmBuf; if ( (flags & KPKT) && (bytesToSend >= (6 * 128)) ) { /* Normal case */ if ( ymdmSendPkt(pktP, pktNum, LGPKTSIZE, flags) != OK ) return( ERROR ); pktNum++; } else while ( bytesToSend > 0 ) { /* Last data segment, < 1024 bytes */ if ( ymdmSendPkt(pktP, pktNum, SMPKTSIZE, flags) != OK ) return( ERROR ); pktNum++; bytesToSend -= SMPKTSIZE; pktP += SMPKTSIZE; } } /* Send EOT, wait for ACK */ for ( pktNum = 0; pktNum < EOTMAX; pktNum++ ) { doputc( EOT ); if ( xgetc_tmout(2) == ACK ) return( OK ); } return( ERROR ); } /* ymdmSendFile() */ /************************************************************************/ /* Function : dump */ /* Purpose : Dump entire log block(s) */ /* Inputs : Parm Mask, block number, number of blocks */ /* Outputs : OK or ERROR */ /************************************************************************/ Int16 dump( Nat16 pmask, Nat16 blk, Nat16 nblks ) { YMdmStruct *ymdmP; Int16 rtn; if ( (ymdmP = (YMdmStruct *)tmpMalloc(sizeof(YMdmStruct))) == NULL ) { xprintf("Out of memory\n"); return( ERROR ); /* Get log buffer, rtn if none */ } xprintf("Sending via YMODEM protocol\n"); xprintf("Please start download on receiver with YMODEM (batch) protocol\n"); bzero( ymdmP, sizeof(YMdmStruct) ); ymdmP->logP.lp_blk = 0; ymdmP->logP.lp_addr = LOG_START_ADDR; ymdmP->endBlk = nextFreeLog.lp_blk; if ( pmask & 1) { ymdmP->logP.lp_blk = blk; ymdmP->endBlk = (pmask & 2) ? (blk + nblks - 1) : 1; } if ( (rtn = ymdmSendFile(ymdmP)) == OK ) ymdmSendFileName("", ymdmP->ymdmBuf); else xputs("\030\030\030\030\030"); tmpFree( (char *)ymdmP ); return( rtn ); } /* dump() */ #endif @