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

📄 zmodem.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                    error( "ReceiveSingleFile: ReadHeader "
                           "returned %d", c );
                    return ERROR;
                }
                SendAttentionString();
                continue;
            case ZSKIP:
                fclose( file );
                status("ReceiveSingleFile: Sender SKIPPED file");
                return c;
            case ZDATA:
                if ( UnpackHeaderIntoLong( received_header ) != rxbytes ) {
                    if ( ++error_count >= 20 )
                        return ERROR;
                    SendAttentionString();
                    continue;
                }
moredata:
                switch ( c = ReadDataFrame( buffer, 1024 ) ) {
                  case ZCAN:
                    error( "ReceiveSingleFile: ReadData returned %d", 
                           c );
                    return ERROR;
                  case ERROR:
                    if ( ++error_count >= 20 ) {
                        error( "ReceiveSingleFile: ReadData "
                               "returned %d", c );
                        return ERROR;
                    }
                    SendAttentionString();
                    continue;
                  case TIMEOUT:
                    if ( ++error_count >= 20 ) {
                        error( "ReceiveSingleFile: ReadData "
                               "returned %d", c );
                        return ERROR;
                    }
                    continue;
                  case GOTCRCW:
                    error_count = 0;
                    fwrite( buffer, 1, Rxcount, file );
                    rxbytes += Rxcount;
                    PackLongIntoHeader( rxbytes );
                    SendHexHeader( 4, ZACK, transmitted_header );
                    SendChar( XON );
                    goto nxthdr;
                  case GOTCRCQ:
                    error_count = 0;
                    fwrite( buffer, 1, Rxcount, file );
                    rxbytes += Rxcount;
                    PackLongIntoHeader( rxbytes );
                    SendHexHeader( 4, ZACK, transmitted_header );
                    goto moredata;
                  case GOTCRCG:
                    error_count = 0;
                    fwrite( buffer, 1, Rxcount, file );
                    rxbytes += Rxcount;
                    goto moredata;
                  case GOTCRCE:
                    error_count = 0;
                    fwrite( buffer, 1, Rxcount, file );
                    rxbytes += Rxcount;
                    goto nxthdr;
                }
        }
    }
#ifdef _MSC_VER
    return 0;  // MSC 7.0 generates an error w/o this line, 
               // although it can never be reached
#endif
}

// This routine just has to decide whether to send the binary 
// header using CRC-16 or CRC-32.  After that it just spits out 
// the data.

void Zmodem::SendBinaryHeader( int length, 
                               int type, 
                               char *header )
{
    int i;
    Crc32 crc32( 0xFFFFFFFFL );
    unsigned long crc32val;
    Crc16 crc16( 0 );

    status( "SendBinaryHeader: %d %s %lx",
            length,
            frametypes[ type + 4 ],
            UnpackHeaderIntoLong( header ) );
    SendChar( ZPAD );
    SendChar( ZDLE );
    if ( receiver_wants_crc32 ) {
        SendChar( ZBIN32 );
        SendEncodedChar( type );
        crc32.update( type );
        for ( i = 0; i < length; i++ ) {
            crc32.update( 0xff & header[ i ] );
            SendEncodedChar( header[ i ] );
        }
        crc32val = ~crc32.value();
        for ( i = 0 ; i < 4 ; i++ ) {
            SendEncodedChar( (int) crc32val );
            crc32val >>= 8;
        }
    } else {
        SendChar( ZBIN );
        SendEncodedChar( type );
        crc16.update( type );
        for ( i = 0 ; i < length ; i++ ) {
            SendEncodedChar( header[ i ] );
            crc16.update( header[ i ] & 0xff );
        }
        crc16.update( 0 );
        crc16.update( 0 );
        SendEncodedChar( crc16.value() >> 8 );
        SendEncodedChar( crc16.value() );
    }
}

// Sending the hex header involves no decisions whatsoever.

void Zmodem::SendHexHeader( int len, int type, char *header )
{
    int n;
    Crc16 crc( 0 );

    status( "SendHexHeader: %d %s %lx", len,
            frametypes[type+4], UnpackHeaderIntoLong( header ) );
    SendChar( ZPAD );
    SendChar( ZPAD );
    SendChar( ZDLE );
    SendChar( ZHEX );
    SendHexEncodedChar( type );
    crc.update( type );
    for ( n = 0 ; n < len ; n++ ) {
        SendHexEncodedChar( header[ n ] );
        crc.update( 0xff & header[ n ] );
    }
    crc.update( 0 );
    crc.update( 0 );
    SendHexEncodedChar( crc.value() >> 8 );
    SendHexEncodedChar( crc.value() );
    SendChar( CR );
    SendChar( LF | 0x80 );
    if ( type != ZFIN && type != ZACK )
        SendChar( XON );
}

// Reading in headers and data subpackets is a relatively 
// difficult job. The next four routines combine to read in 
// headers.  The first routine dispatches one of the next three, 
// depending on what the header type is.

int Zmodem::ReadHeader( char *header )
{
    int c;
    int n;
    int cancount;
    Settings settings;

    port->ReadSettings( settings );
    n = 1400;
    n += ( settings.BaudRate > 19200L ) ? 
            19200 : (int) settings.BaudRate;

startover:
    cancount = 0;
again:
    switch ( c = ReadChar( 10000L ) ) {
        case TIMEOUT:
            goto finished;
        case CAN:
gotcan:
            if ( ++cancount >= 5 ) {
                c = ZCAN;
                goto finished;
            }
            switch ( c = ReadChar( 100 ) ) {
                case TIMEOUT:
                    goto again;
                case ZCRCW:
                switch ( ReadChar( 100 ) ) {
                    case TIMEOUT:
                        c = ERROR;
                        goto finished;
                    default:
                        goto agn2;
                }
                default:
                    break;
                case CAN:
                    if ( ++cancount >= 5 ) {
                        c = ZCAN;
                        goto finished;
                    }
                    goto again;
            }
        default:
agn2:
            if ( --n == 0 ) {
                c = GARBAGE_COUNT;
                goto finished;
             }
             goto startover;
        case ZPAD | 0x80:        /* This is what we want. */
        case ZPAD:
             break;
    }
    cancount = 0;
splat:
    switch ( c = ReadUnencodedByte() ) {
        case ZPAD:
            goto splat;
        case TIMEOUT:
            goto finished;
        default:
            goto agn2;
        case ZDLE:        /* This is what we want. */
            break;
    }

    c = ReadUnencodedByte();
    switch ( c ) {
        case ZBIN32:
            current_frame_uses_crc32 = 1;
            c = ReadBinaryHeaderCRC32( header );
            break;
        case TIMEOUT:
            goto finished;
        case ZBIN:
            current_frame_uses_crc32 = 0;
            c = ReadBinaryHeaderCRC16( header );
            break;
        case ZHEX:
            current_frame_uses_crc32 = 0;
            c = ReadHexHeaderCRC16( header );
            break;
        case CAN:
            goto gotcan;
        default:
            goto agn2;
    }
    received_file_position = header[ ZP3 ] & 0xff;
    received_file_position <<= 8;
    received_file_position += header[ ZP2 ] & 0xff;
    received_file_position <<= 8;
    received_file_position += header[ ZP1 ] & 0xff;
    received_file_position <<= 8;
    received_file_position += header[ ZP0 ] & 0xff;
finished:
    switch ( c ) {
        case GOTCAN:
            c = ZCAN;
        /* **** FALL THRU TO **** */
        case ZNAK:
        case ZCAN:
        case ERROR:
        case TIMEOUT:
        case GARBAGE_COUNT:
            error( "Got %s", frametypes[ c + 4 ] );
        /* **** FALL THRU TO **** */
        default:
            if ( c >= -4 && c <= 22 )
                error( "ReadHeader: %s %lx",
                       frametypes[ c + 4 ], 
                       received_file_position );
            else
                error( "ReadHeader: %d %lx", 
                       c, 
                       received_file_position );
    }
    return c;
}

// At this point most of the hard work has been done.  The next 
//three routines just read in the type of header and the data 
// associated with it, then check to see if the CRC is correct.

int Zmodem::ReadBinaryHeaderCRC16( char *header )
{
    int c;
    int i;
    Crc16 crc( 0 );
    int header_type;

    if ( ( c = ReadEncodedByte() ) & ~0xff )
        return c;
    header_type = c;
    crc.update( c );

    for ( i = 0 ; i < 4 ; i++ ) {
        if ( ( c = ReadEncodedByte() ) & ~0xff )
            return c;
        crc.update( c );
        header[ i ] = (char) c;
    }
    if ( ( c = ReadEncodedByte() ) & ~0xff )
        return c;
    crc.update( c );
    if ( ( c = ReadEncodedByte() ) & ~0xff )
        return c;
    crc.update( c );
    if ( crc.value() & 0xFFFF ) {
        error( "Bad CRC" );
        return ERROR;
    }
    return header_type;
}

int Zmodem::ReadBinaryHeaderCRC32( char *header )
{
    int c;
    int i;
    Crc32 crc( 0xFFFFFFFFL );
    int header_type;

    if ( ( c = ReadEncodedByte() ) & ~0xff )
        return c;
    header_type = c;
    crc.update( c );

    for ( i = 0 ; i < 4 ; i++ ) {
        if ( ( c = ReadEncodedByte() ) & ~0xff )
            return c;
        crc.update( c );
        header[ i ] = (char) c;
    }
    for ( i = 0; i < 4 ; i++ ) {
        if ( ( c = ReadEncodedByte() ) & ~0xff )
            return c;
        crc.update( c );
    }
    if ( crc.value() != 0xDEBB20E3L ) {
        error( "Bad CRC" );
        return ERROR;
    }
    return header_type;
}

int Zmodem::ReadHexHeaderCRC16( char *header )
{
    int c;
    Crc16 crc( 0 );
    int i;
    int header_type;

    if ( ( c = ReadHexByte() ) < 0 )
        return c;
    header_type = c;
    crc.update( c );

    for ( i = 0 ; i < 4 ; i++ ) {
        if ( ( c = ReadHexByte() ) < 0 )
            return c;
        crc.update( c );
        header[ i ] = (char) c;
    }
    if ( ( c = ReadHexByte() ) < 0 )
        return c;
    crc.update( c );
    if ( ( c = ReadHexByte() ) < 0 )
        return c;
    crc.update( c );
    if ( crc.value() & 0xFFFF ) {
        error( "Bad CRC" );
        return ERROR;
    }
    switch ( c = ReadChar( 100 ) ) {
        case CR :
        case CR | 0x80 :
            ReadChar( 100 );
    }
    return header_type;
}

// The next three routines are used to read in binary data
// subpackets.  This code is somewhat simpler than the code
// used to read in a header, mostly because there are fewer
// things to go wrong.

int Zmodem::ReadDataFrame( char *buffer, int length )
{
    if ( current_frame_uses_crc32 )
        return ReadDataFrameCRC32( buffer, length );
    else
        return ReadDataFrameCRC16( buffer, length );
}

int Zmodem::ReadDataFrameCRC32( char *buffer, int length )
{
    int c;
    Crc32 crc( 0xFFFFFFFFL );
    char *end;
    int d;

    Rxcount = 0;
    end = buffer + length;
    while ( buffer <= end ) {
        if ( ( c = ReadEncodedByte() ) & ~0xff ) {
crcfoo:
            switch ( c ) {
                case GOTCRCE:
                case GOTCRCG:
                case GOTCRCQ:
                case GOTCRCW:
                    d = c;
                    c &= 0xff;
                    crc.update( c );
                    if ( ( c = ReadEncodedByte() ) & ~0xff )
                        goto crcfoo;
                    crc.update( c );
                    if ( ( c = ReadEncodedByte() ) & ~0xff )
                        goto crcfoo;
                    crc.update( c );
                    if ( ( c = ReadEncodedByte() ) & ~0xff )
                        goto crcfoo;
                    crc.update( c );
                    if ( ( c = ReadEncodedByte() ) & ~0xff )
                        goto crcfoo;
                    crc.update( c );
                    if ( crc.value() != 0xDEBB20E3L ) {
                        error( "Bad CRC" );
                        return ERROR;
                    }
                    Rxcount = (int) ( length - (end - buffer) );
                    error( "ReadDataFrameCRC32: %d %s",
                           Rxcount, 
                           Zendnames[ d - GOTCRCE & 3 ] );
                    return d;
                case GOTCAN:
                    error( "Sender Canceled" );
                    return ZCAN;
                case TIMEOUT:

⌨️ 快捷键说明

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