⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xyzmodem.c

📁 x,y,z,Modem协议实现的源码-C语言
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    // Verify checksum/CRC    if (xyz.crc_mode) {        cksum = cyg_crc16(xyz.pkt, xyz.len);        if (cksum != ((xyz.crc1 << 8) | xyz.crc2)) {            ZM_DEBUG(zm_dprintf("CRC error - recvd: %02x%02x, computed: %x\n",                                 xyz.crc1, xyz.crc2, cksum & 0xFFFF));            return xyzModem_cksum;        }    } else {        cksum = 0;        for (i = 0;  i < xyz.len;  i++) {            cksum += xyz.pkt[i];        }        if (xyz.crc1 != (cksum & 0xFF)) {            ZM_DEBUG(zm_dprintf("Checksum error - recvd: %x, computed: %x\n", xyz.crc1, cksum & 0xFF));            return xyzModem_cksum;        }    }    // If we get here, the message passes [structural] muster    return 0;}int xyzModem_stream_open(connection_info_t *info, int *err){    int console_chan, stat;    int retries = xyzModem_MAX_RETRIES;    int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;//    ZM_DEBUG(zm_out = zm_out_start);#ifdef xyzModem_zmodem    if (info->mode == xyzModem_zmodem) {        *err = xyzModem_noZmodem;        return -1;    }#endif    // Set up the I/O channel.  Note: this allows for using a different port in the future    console_chan = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);    if (info->chan >= 0) {        CYGACC_CALL_IF_SET_CONSOLE_COMM(info->chan);    } else {        CYGACC_CALL_IF_SET_CONSOLE_COMM(console_chan);    }    xyz.__chan = CYGACC_CALL_IF_CONSOLE_PROCS();    CYGACC_CALL_IF_SET_CONSOLE_COMM(console_chan);    CYGACC_COMM_IF_CONTROL(*xyz.__chan, __COMMCTL_SET_TIMEOUT, xyzModem_CHAR_TIMEOUT);    xyz.len = 0;    xyz.crc_mode = true;    xyz.at_eof = false;    xyz.tx_ack = false;    xyz.mode = info->mode;    xyz.total_retries = 0;    xyz.total_SOH = 0;    xyz.total_STX = 0;    xyz.total_CAN = 0;#ifdef USE_YMODEM_LENGTH    xyz.read_length = 0;    xyz.file_length = 0;#endif    while (retries-- > 0) {        stat = xyzModem_get_hdr();        if (stat == 0) {            // Y-modem file information header            if (xyz.blk == 0) {#ifdef USE_YMODEM_LENGTH                // skip filename                while (*xyz.bufp++);                // get the length                parse_num(xyz.bufp, &xyz.file_length, NULL, " ");#endif                // The rest of the file name data block quietly discarded                xyz.tx_ack = true;            }            xyz.next_blk = 1;            xyz.len = 0;            return 0;        } else         if (stat == xyzModem_timeout) {            if (--crc_retries <= 0) xyz.crc_mode = false;            CYGACC_CALL_IF_DELAY_US(5*100000);   // Extra delay for startup            CYGACC_COMM_IF_PUTC(*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));            xyz.total_retries++;            ZM_DEBUG(zm_dprintf("NAK (%d)\n", __LINE__));        }        if (stat == xyzModem_cancel) {            break;        }    }    *err = stat;    ZM_DEBUG(zm_flush());    return -1;}int xyzModem_stream_read(char *buf, int size, int *err){    int stat, total, len;    int retries;    total = 0;    stat = xyzModem_cancel;    // Try and get 'size' bytes into the buffer    while (!xyz.at_eof && (size > 0)) {        if (xyz.len == 0) {            retries = xyzModem_MAX_RETRIES;            while (retries-- > 0) {                stat = xyzModem_get_hdr();                if (stat == 0) {                    if (xyz.blk == xyz.next_blk) {                        xyz.tx_ack = true;                        ZM_DEBUG(zm_dprintf("ACK block %d (%d)\n", xyz.blk, __LINE__));                        xyz.next_blk = (xyz.next_blk + 1) & 0xFF;                        // Data blocks can be padded with ^Z (EOF) characters                        // This code tries to detect and remove them#ifdef xyzModem_zmodem                        if (xyz.mode != xyzModem_zmodem) {#else                        if (1) {#endif                            if ((xyz.bufp[xyz.len-1] == EOF) &&                                (xyz.bufp[xyz.len-2] == EOF) &&                                (xyz.bufp[xyz.len-3] == EOF)) {                                while (xyz.len && (xyz.bufp[xyz.len-1] == EOF)) {                                    xyz.len--;                                }                            }                        }#ifdef USE_YMODEM_LENGTH                        // See if accumulated length exceeds that of the file.                        // If so, reduce size (i.e., cut out pad bytes)                        // Only do this for Y-modem (and Z-modem should it ever                        // be supported since it can fall back to Y-modem mode).                        if (xyz.mode != xyzModem_xmodem && 0 != xyz.file_length) {                            xyz.read_length += xyz.len;                            if (xyz.read_length > xyz.file_length) {                                xyz.len -= (xyz.read_length - xyz.file_length);                            }                        }#endif                        break;                    } else if (xyz.blk == ((xyz.next_blk - 1) & 0xFF)) {                        // Just re-ACK this so sender will get on with it                        CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK);                        continue;  // Need new header                    } else {                        stat = xyzModem_sequence;                    }                }                if (stat == xyzModem_cancel) {                    break;                }                if (stat == xyzModem_eof) {                    CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK);                    ZM_DEBUG(zm_dprintf("ACK (%d)\n", __LINE__));                    if (xyz.mode == xyzModem_ymodem) {                        CYGACC_COMM_IF_PUTC(*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));                        xyz.total_retries++;                        ZM_DEBUG(zm_dprintf("Reading Final Header\n"));                        stat = xyzModem_get_hdr();                                                CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK);                        ZM_DEBUG(zm_dprintf("FINAL ACK (%d)\n", __LINE__));                    }                    xyz.at_eof = true;                    break;                }                CYGACC_COMM_IF_PUTC(*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));                xyz.total_retries++;                ZM_DEBUG(zm_dprintf("NAK (%d)\n", __LINE__));            }            if (stat < 0) {                *err = stat;                xyz.len = -1;                return total;            }        }        // Don't "read" data from the EOF protocol package        if (!xyz.at_eof) {            len = xyz.len;            if (size < len) len = size;            memcpy(buf, xyz.bufp, len);            size -= len;            buf += len;            total += len;            xyz.len -= len;            xyz.bufp += len;        }    }    return total;}voidxyzModem_stream_close(int *err){    diag_printf("xyzModem - %s mode, %d(SOH)/%d(STX)/%d(CAN) packets, %d retries\n",                 xyz.crc_mode ? "CRC" : "Cksum",                xyz.total_SOH, xyz.total_STX, xyz.total_CAN,                xyz.total_retries);//    ZM_DEBUG(zm_flush());}// Need to be able to clean out the input buffer, so have to take the// getcvoid xyzModem_stream_terminate(bool abort, int (*getc)(void)){  int c;  if (abort) {      ZM_DEBUG(zm_dprintf("!!!! TRANSFER ABORT !!!!\n"));      switch (xyz.mode) {	case xyzModem_xmodem:	case xyzModem_ymodem:	  // The X/YMODEM Spec seems to suggest that multiple CAN followed by an equal	  // number of Backspaces is a friendly way to get the other end to abort.	  CYGACC_COMM_IF_PUTC(*xyz.__chan,CAN);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,CAN);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,CAN);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,CAN);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,BSP);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,BSP);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,BSP);	  CYGACC_COMM_IF_PUTC(*xyz.__chan,BSP);	  // Now consume the rest of what's waiting on the line.	  ZM_DEBUG(zm_dprintf("Flushing serial line.\n"));	  xyzModem_flush();          xyz.at_eof = true;	break;#ifdef xyzModem_zmodem	case xyzModem_zmodem:	  // Might support it some day I suppose.#endif	break;      }  } else {      ZM_DEBUG(zm_dprintf("Engaging cleanup mode...\n"));      // Consume any trailing crap left in the inbuffer from      // previous recieved blocks. Since very few files are an exact multiple      // of the transfer block size, there will almost always be some gunk here.      // If we don't eat it now, RedBoot will think the user typed it.      ZM_DEBUG(zm_dprintf("Trailing gunk:\n"));      while ((c = (*getc)()) > -1) ;      ZM_DEBUG(zm_dprintf("\n"));      // Make a small delay to give terminal programs like minicom      // time to get control again after their file transfer program      // exits.      CYGACC_CALL_IF_DELAY_US((cyg_int32)250000);  }}char *xyzModem_error(int err){    switch (err) {    case xyzModem_access:        return "Can't access file";        break;    case xyzModem_noZmodem:        return "Sorry, zModem not available yet";        break;    case xyzModem_timeout:        return "Timed out";        break;    case xyzModem_eof:        return "End of file";        break;    case xyzModem_cancel:        return "Cancelled";        break;    case xyzModem_frame:        return "Invalid framing";        break;    case xyzModem_cksum:        return "CRC/checksum error";        break;    case xyzModem_sequence:        return "Block sequence error";        break;    default:        return "Unknown error";        break;    }}//// RedBoot interface//GETC_IO_FUNCS(xyzModem_io, xyzModem_stream_open, xyzModem_stream_close,              xyzModem_stream_terminate, xyzModem_stream_read, xyzModem_error);RedBoot_load(xmodem, xyzModem_io, false, false, xyzModem_xmodem);RedBoot_load(ymodem, xyzModem_io, false, false, xyzModem_ymodem);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -