📄 ian_xmodem.c
字号:
} if ( r != sno ) { /* block sequence number is not quite right, but it might still do */ if ( (lsno == 0) || ( sno - r != 1 && r - sno != 0xff ) ) { /* shit! desperately out of sync. CAN the whole thing */ Mtrace("S<%02x != %02x>", r, sno); doCAN(); done = XERR_SYNC; } else { /* no worries, it's just a retransmission */ Mtrace("S"); rputchar(ACK); if (lsno == 1) { Mtrace("0"); rputchar(nak); } } } else { /* seq. number just fine */ Mtrace("s"); if ( lsno == 0 ) { Mtrace("0"); rputchar(ACK); } done = 1; } break; case CAN: Mtrace("C"); /* wait for a second CAN */ c = (char)waitchar(CHAR_TMO); if (c != CAN) { Mtrace("<%02x>", c); waitclear(); rputchar(nak); } else { Mtrace("C"); done = XERR_CAN; } break; case ESC: /* User-invoked abort */ Mtrace("X"); /* wait for a second ESC */ c = (char)waitchar(CHAR_TMO); if (c != ESC) { waitclear(); rputchar(nak); done = 0; } else { done = XERR_UCAN; } break; case EOT: Mtrace("E"); /* first make sure that this is really an EOT, and not a corrupted start-frame; use the fact that self-respecting EOTs always come alone, not followed by other characters. */ c = waitchar(CHAR_TMO); if ( c >= 0 ) { /* probably not an EOT, request retransmission */ Mtrace("<%02x>", c); waitclear(); rputchar(nak); break; } /* ok it is probably a true EOT, send an ACK */ rputchar(ACK); Mtrace("a", c); if (lsno != 0) { done = 2; } break; default: /* request retransmission */ Mtrace("?<%02x>",c); waitclear(); rputchar(nak); break; } } while (!done); if (done == 1) { rval = 0; } else if (done == 2) { rval = 1; } else { rval = done; } return rval;}/***************************************************************************//* Xdown(): * * Download, or verify a file using the XMODEM protocol * * Arguments: * - xip - structure containing transfer info: * usecrc IN - use 16bit-CRC instead of 8bit-checksum. * verify IN - operate in verification mode. * dataddr: IN - downloaded file will be stored starting from here. * in verification mode, downloaded file will be * compared with data starting from here. * size: OUT - size of received file in bytes. * pktcnt: OUT - number of frames transfered. * errcnt: OUT - number of errors, if mode is verification. * firsterrat: OUT - address of first error, if mode is verification. * - proto - protocol type (y-modem or x-modem); Used to make very small * adjustment to the operation of the function. * * Returns: * On success: something non-negative. * On error: something negative. * XERR_GEN : General error * XERR_TOUT : Timeout * XERR_SYNC : Lost synchronization * XERR_CAN : Operation canceled * XERR_UCAN : Operation canceled by user */static intXdown(struct xinfo *xip, int proto){ int i, r; ulong sno; int psize; char *tmppkt, *dataddr; Mtrace("--XD--"); dataddr = (char *)(xip->dataddr); if ( xip->verify ) { tmppkt = pktbuff; } else { tmppkt = (char *)(xip->dataddr); } sno = 1; xip->pktcnt = 0; xip->errcnt = 0; xip->firsterrat = 0; xip->size = 0; do { r = waitPacket(tmppkt, &psize, sno, xip->usecrc); if ( r == 0 ) { sno++; xip->pktcnt++; xip->size += psize; if ( xip->verify ) { for (i = 0; i < psize; i++, dataddr++) { if (tmppkt[i] != *dataddr) { if (xip->errcnt++ == 0) xip->firsterrat = (ulong)dataddr; } } } else { tmppkt += psize; } } } while ( ! r ); if ( r == 1 && proto == XMODEM ) { /* send a couple more ACKs to make sure that at least one reaches its destination */ rputchar(ACK); rputchar(ACK); rputchar(ACK); rputchar(ACK); rputchar(ACK); rputchar(ACK); /* send backspaces in-case ACKs have reached the user's terminal */ rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); rputchar(BS); } if (proto == XMODEM) { /* trash any final garbage send by the transmiter */ waitclear(); } return r;}/***************************************************************************//* Ydown(): * * Download (uMon <-- Host) a file using the YMODEM protocol * * Arguments: * - yip - structure containing transfer info: * usecrc IN - use 16bit CRC instead of 8bit checksum. * onek x * verify IN - verify the downloaded file against stored data. * baseaddr: IN - download the first file here. * flags IN - TFS flags to use when writing to TFS. * info IN - TFS info to use when writing to TFS. * filecnt OUT - Number of files successfully downloaded. * fname[i] OUT - Name of the i'th file downloaded. * size[i]: OUT - size of the i'th file downloaded in bytes. * pktcnt[i]: OUT - nr of frames transfered when downloading i'th file. * errcnt[i]: OUT - number of errors detected when verifying i'th file. * firsterrat[i]: OUT - address of the first error of the i'th file. * * Returns: * On success: something non-negative. * On error: something negative. * XERR_GEN : General error * XERR_TOUT : Timeout * XERR_NOFILE : File not found (verification mode) * XERR_TFS : TFS error * XERR_SYNC : Synchronization error * XERR_CAN : Operation canceled * XERR_UCAN : Operation canceled by user */static intYdown(struct yinfo *yip){ TFILE *tfp; int rval, r, psize; char *tmppkt; ulong dataddr; char *fname, *basename, *s1, *fsize; rval = 0; yip->filecnt = 0; tmppkt = pktbuff; dataddr = yip->baseaddr; do { yip->dataddr[yip->filecnt] = dataddr; yip->size[yip->filecnt] = 0; yip->pktcnt[yip->filecnt] = 0; yip->errcnt[yip->filecnt] = 0; yip->firsterrat[yip->filecnt] = 0; /* * receive and parse the header-block */ r = waitPacket(tmppkt, &psize, 0, 1); if ( r < 0 ) { rval = r; break; } /* first comes the file-name */ fname = (char *)(tmppkt); /* buggy ymodems delimit fields with SP instead of NULL. Cope. */ s1 = strchr(fname,' '); if (s1) *s1 = '\0'; /* if file-name contains path, cut it off and just keep the stem */ basename = strrchr(fname,'/'); if (! basename) basename = fname; /* after the file-name comes the file-size */ fsize = basename + strlen(basename) + 1; /* buggy ymodems delimit fields with SP instead of NULL. cope. */ s1 = strchr(fsize,' '); if (s1) *s1 = '\0'; /* copy info to xip fields */ yip->size[yip->filecnt] = atoi(fsize); strcpy(yip->fname[yip->filecnt], basename); Mtrace("<f=%s>",yip->fname[yip->filecnt]); Mtrace("<z=%d>",yip->size[yip->filecnt]); Mtrace("]"); if ( ! yip->fname[yip->filecnt][0] ) break; /* * receive file-data */ xif.dataddr = dataddr; xif.usecrc = yip->usecrc; xif.verify = yip->verify; if ( yip->verify ) {#if INCLUDE_TFS if (! (tfp = tfsstat(yip->fname[yip->filecnt])) ) { waitclear(); doCAN(); rval = XERR_NOFILE; break; } memcpy((char *)(xif.dataddr), TFS_BASE(tfp), tfp->filsize);#endif } r = Xdown(&xif, YMODEM); if ( r < 0 ) { rval = r; break; } if (yip->size[yip->filecnt] <= 0) { yip->size[yip->filecnt] = xif.size; } yip->pktcnt[yip->filecnt] = xif.pktcnt; yip->errcnt[yip->filecnt] = xif.errcnt; yip->firsterrat[yip->filecnt] = xif.firsterrat; /* * write file to TFS */ if ( ! yif.verify ) {#if INCLUDE_TFS if ( yip->size[yip->filecnt] > 0 ) { /* save file to TFS */ r = tfsadd(yip->fname[yip->filecnt], yip->info, yip->flags, (uchar *)(yip->dataddr[yip->filecnt]), yip->size[yip->filecnt]); if (r != TFS_OKAY) { doCAN(); rval = XERR_TFS; tfserr = r; break; } }#endif }#if INCLUDE_TFS dataddr = yip->baseaddr;#else dataddr += yip->size[yip->filecnt];#endif yip->filecnt++; } while (yip->filecnt < YFILES_MAX); if ( yip->filecnt >= YFILES_MAX ) { /* Cancel the transaction. Let the transmiter know that we can receiver no more files */ waitclear(); doCAN(); } /* trash any final garbage send by the transmiter */ waitclear(); return rval;}/*************************************************************************** * UPLOAD STUFF **************************************************************************//* * putPacket * * Send an X-Modem or Y-Modem packet */static voidputPacket (uchar *pkt, int len, int sno, int usecrc){ int i; ushort chksm; chksm = 0; /* Send start of frame. */ if ( (len == PKTLEN_128) || (sno == 0) ) { rputchar(SOH); } else { rputchar(STX); } /* Send sequence number and its complement */ rputchar(sno); rputchar((uchar)~(sno)); /* Send data. Calculate CRC or checksum. Send CRC or checksum. */ if ( usecrc ) { for(i=0; i < len; i++) { rputchar(*pkt); chksm = (chksm << 8) ^ xcrc16tab[ (chksm>>8) ^ *pkt++ ]; } rputchar((uchar)(chksm >> 8)); rputchar((uchar)(chksm & 0x00ff)); } else { for(i=0; i < len; i++) { rputchar(*pkt); chksm = ((chksm+*pkt++)&0xff); } rputchar((uchar)(chksm&0x00ff)); }}/***************************************************************************//* * sendPacket * * Send and X or Y modem protocol packet. * * Transmits the given frame and waits for acknowledgment. * Handles retransmitions and cancel requests as well. * * Arguments: * - pb - packet (frame) buffer. The packet to send is here. * - len - length (in bytes) of the frame to send.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -