📄 xmodem.c
字号:
* character in the response. */ if (xip->pktcnt == -1) c = getchar(); return(c);}/* getPacket(): * Used by Xdown to retrieve packets. */static int getPacket(uchar *tmppkt, struct xinfo *xip){ int i; char *pkt; uchar seq[2]; if (getbytes(seq,2,1) != 2) return(-1); if (xip->flags & VERIFY) { if (getbytes(tmppkt,xip->pktlen,1) != xip->pktlen) return(-1); for(i=0;i<xip->pktlen;i++) { if (tmppkt[i] != ((char *)xip->dataddr)[i]) { if (xip->errcnt++ == 0) xip->firsterrat = (char *)(xip->dataddr+i); } } pkt = (char *)tmppkt; } else { if (getbytes((char *)xip->dataddr,xip->pktlen,1) != xip->pktlen) return(-1); pkt = (char *)xip->dataddr; } if (xip->flags & USECRC) { ushort crc, xcrc; /* An "endian independent way to combine the CRC bytes. */ crc = (ushort)getchar() << 8; crc += (ushort)getchar(); xcrc = xcrc16((uchar *)pkt,(ulong)(xip->pktlen)); if (crc != xcrc) { rputchar(NAK); //Mtrace("CRC %04x != %04x",crc,xcrc); return(0); } } else { uchar csum, xcsum; xcsum = (uchar)getchar(); csum = 0; for(i=0;i<xip->pktlen;i++) csum += *pkt++; if (csum != xcsum) { rputchar(NAK); //Mtrace("CSUM %02x != %02x (%d)",csum,xcsum,xip->pktlen); return(0); } //Mtrace("CSUM %02x (%d)",csum,xip->pktlen); } /* Test the sequence number compliment... */ if ((uchar)seq[0] != (uchar)~seq[1]) { rputchar(NAK); //Mtrace("SNOCMP %02x != %02x",(uchar)seq[0],(uchar)~(seq[1])); return(0); } /* Verify that the incoming sequence number is the expected value... */ if ((uchar)seq[0] != xip->sno) { /* If the incoming sequence number is one less than the expected * sequence number, then we assume that the sender did not recieve * our previous ACK, and they are resending the previously received * packet. In that case, we send ACK and don't process the * incoming packet... */ if ((uchar)seq[0] == xip->sno-1) { //Mtrace("R_ACK"); rputchar(ACK); return(0); } /* Otherwise, something's messed up... */ rputchar(CAN); //Mtrace("SNO: %02x != %02x",seq[0],xip->sno); return(-1); } /* First packet of YMODEM contains information about the transfer: * FILENAME SP FILESIZE SP MOD_DATE SP FILEMODE SP FILE_SNO * Only the FILENAME is required and if others are present, then none * can be skipped. */ if ((xip->flags & YMODEM) && (xip->pktcnt == 0)) { char *slash, *space, *fname; slash = strrchr((char *)(xip->dataddr),'/'); space = strchr((char *)(xip->dataddr),' '); if (slash) fname = slash+1; else fname = (char *)(xip->dataddr); //Mtrace("<fname=%s>",fname); if (space) { *space = 0; xip->size = atoi(space+1); } strcpy(xip->fname,fname); if (fname[0]) xip->filcnt++; } else xip->dataddr += xip->pktlen; xip->sno++; xip->pktcnt++; xip->xfertot += xip->pktlen; //Mtrace("ACK"); rputchar(ACK); if (xip->flags & YMODEM) { if (xip->fname[0] == 0) { printf("\nRcvd %d file%c\n", xip->filcnt,xip->filcnt > 1 ? 's' : ' '); return(1); } } return(0);}/* Xup(): * Called when a transfer from target to host is being made (considered * an upload). */static int Xup(struct xinfo *xip){ unsigned char c, buf[PKTLEN_128]; int done, pktlen; long actualsize; //Mtrace("Xup starting"); actualsize = xip->size; if (xip->size & 0x7f) { xip->size += 128; xip->size &= 0xffffff80L; } printf("Upload %ld bytes from 0x%lx\n",xip->size,(ulong)xip->base); /* Startup synchronization... */ /* Wait to receive a NAK or 'C' from receiver. */ done = 0; while(!done) { c = (uchar)getchar(); switch(c) { case NAK: done = 1; //Mtrace("CSM"); break; case 'C': xip->flags |= USECRC; done = 1; //Mtrace("CRC"); break; case 'q': /* ELS addition, not part of XMODEM spec. */ return(0); default: break; } } /* look for ymodem if (xip->flags & YMODEM) { //Mtrace("SNO_0"); xip->sno = 0; xip->pktcnt = -1; memset((char *)buf,0,PKTLEN_128); sprintf(buf,"%s",xip->fname); pktlen = xip->pktlen; xip->pktlen = PKTLEN_128; putPacket(buf,xip); xip->pktlen = pktlen; } */ done = 0; xip->sno = 1; xip->pktcnt = 0; while(!done) { c = (uchar)putPacket((uchar *)(xip->dataddr),xip); switch(c) { case ACK: xip->sno++; xip->pktcnt++; xip->size -= xip->pktlen; xip->dataddr += xip->pktlen; //Mtrace("A"); break; case NAK: //Mtrace("N"); break; case CAN: done = -1; //Mtrace("C"); break; case EOT: done = -1; //Mtrace("E"); break; default: done = -1; //Mtrace("<%2x>",c); break; } if (xip->size <= 0) { rputchar(EOT); getchar(); /* Flush the ACK */ break; } //Mtrace("!"); } //Mtrace("Xup_almost"); /* if ((done != -1) && (xip->flags & YMODEM)) { xip->sno = 0; memset((char *)buf,0,PKTLEN_128); pktlen = xip->pktlen; xip->pktlen = PKTLEN_128; putPacket(buf,xip); xip->pktlen = pktlen; } */ //Mtrace("Xup_done."); return(0);}/* Xdown(): * Called when a transfer from host to target is being made (considered * an download). */static int Xdown(struct xinfo *xip){ long timeout; char c, *tmppkt; int done; /* tmppkt = malloc(PKTLEN_1K); if (!tmppkt) { //Mtrace("malloc failed"); return(-1); } */nextfile: /*if (xip->flags & YMODEM) xip->sno = 0x00; else*/ xip->sno = 0x01; xip->pktcnt = 0; xip->errcnt = 0; xip->xfertot = 0; xip->firsterrat = 0; /* Startup synchronization... */ /* Continuously send NAK or 'C' until sender responds. */restart: //Mtrace("Xdown"); while(1) { if (xip->flags & USECRC) rputchar('C'); else rputchar(NAK); timeout = LoopsPerSecond * xip->nakresend; while(!gotachar() && timeout) timeout--; if (timeout) break; } done = 0; //Mtrace("Got response"); while(done == 0) { c = (char)getchar(); switch(c) { case SOH: /* 128-byte incoming packet */ //Mtrace("O"); xip->pktlen = 128; done = getPacket(tmppkt,xip); if (done < 0) //Mtrace("GP_%d",done); if (!done && (xip->pktcnt == 1) && (xip->flags & YMODEM)) goto restart; break; case STX: /* 1024-byte incoming packet */ //Mtrace("T"); xip->pktlen = 1024; done = getPacket(tmppkt,xip); if (done < 0) //Mtrace("GP_%d",done); if (!done && (xip->pktcnt == 1) && (xip->flags & YMODEM)) goto restart; break; case CAN: //Mtrace("C"); done = -1; break; case EOT: //Mtrace("E"); rputchar(ACK);/* if (xip->flags & YMODEM) {#if INCLUDE_TFS if (!xip->size) xip->size = xip->pktcnt * xip->pktlen; if (xip->fname[0]) tfsadd(xip->fname,0,0,(uchar *)xip->base,xip->size); xip->dataddr = xip->base;#endif goto nextfile; } else {*/ done = xip->xfertot; printf("\nRcvd %d pkt%c (%d bytes)\n",xip->pktcnt, xip->pktcnt > 1 ? 's' : ' ',xip->xfertot); /* If the transfer is complete and no file add is to * be done, then we flush d-cache and invalidate * i-cache across the memory space that was just * copied to. This is necessary in case the * binary data that was just transferred is code. */ /* flushDcache((char *)xip->base,xip->xfertot); invalidateIcache((char *)xip->base,xip->xfertot); }*/ break; case ESC: /* User-invoked abort */ //Mtrace("X"); done = -1; break; default: //Mtrace("<%02x>",c); done = -1; break; } //Mtrace("!"); } if (xip->flags & VERIFY) { if (xip->errcnt) printf("%d errors, first at 0x%lx\n", xip->errcnt,(ulong)(xip->firsterrat)); else printf("verification passed\n"); } free(tmppkt); return(done);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -