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

📄 serlink.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:


/* This function is used by the next routine to calculate the crc for a
   block of data.
   Input:   old_crc -- crc value so far
             data   -- next byte to be incorporated
   Returns:  the new crc value after data is accounted for               */

static word NewCRC( char data, word old_crc )
{
    word     crc_value;            /* the CRC value of the block */
    int      i;                    /* loop index */
    int      high_bit_on;          /* flag for high bit of value */
    int      data_bit;             /* appropriate bit of data */

    crc_value = old_crc;
    /* Process 0th through 7th bit of the byte */
    for( i = 8; i > 0; --i ) {
        data_bit = data & 1;
        high_bit_on = crc_value & 0x8000;
        crc_value <<= 1;
        crc_value |= data_bit;
        if( high_bit_on ) {
            crc_value ^= CRC_VAL;
        }
        data >>= 1;
    }
    return( crc_value );
}


/*========================================================================*/
/*========================================================================*/


/* This routine calculates the CRC for a block of 8-bit data (plus 3 bytes)
   Input:   extra  points to the extra 3 bytes (blk# & err) that are
                     included in calculating the CRC
              p    is a pointer to the start of the block of data
             num   is the number of data bytes
   Output:   the CRC value                                             */

static word CRC( char *extra, int num, char *p )
{
    word     crc_value = 0;        /* the CRC value of the block */
    int      i;                    /* loop index */

    /* included blk# & err bytes in the front, and 2 padding characters 0xff */
    for( i = 0; i < 3; ++i, ++extra ) {
        crc_value = NewCRC( *extra, crc_value );
    }
    for( i = 0; i < num; ++i, ++p ) {
        crc_value = NewCRC( *p, crc_value );
    }
    crc_value = NewCRC( 0xff, crc_value );
    crc_value = NewCRC( 0xff, crc_value );
    return( crc_value );
}


/*========================================================================*/
/*========================================================================*/


/* This routine builds a block and sends it to the other machine.
   Block format: STX CRC(2) len(2) blk#(2) err(1) data(n) ETX
   where: STX=0x02, crc=16 bit error check value, len=length of data block,
   blk#=number of this block, 0 thru 65535, wrapping, err=no. of Errors for
   previous BlockSend, data=send characters, ETX=0x03

   Entry:    p -- pointer to block of data
             num -- number of bytes in data block
             timeout -- time to wait for proper acknowledgement
   Returns:  SUCCESS or FAIL (due to time-out)                  */

static int BlockSend( unsigned num, char *p, unsigned timeout )
{
    word        crc_value;           /* crc value of block */
    unsigned wait_time;              /* timer for testing time-out */
    int      i;                      /* loop index */
    int      reply;                  /* reply message from other machine */
    char     crc_low, crc_hi, len_low, len_hi;
    char     extra[3];     /* ..[0]=blkno_low, ..[1]=blkno_hi, ..[2]=err */
    unsigned    wait;

    ZeroWaitCount();
    extra[2] = PrevErrors = Errors;
    if( Errors > 255 ) {
        extra[2] = 255;       /* because it is a char, not an int */
    }
    Errors = 0;

    ClearCom();
    /* compose send buffer contents */
    len_low = num & 0xff;              /* low 8 bits of data block length */
    len_hi  = num >> 8;                /* high 8 bits of data block length */
    extra[0] = SendBlkNo & 0xff;      /* low 8 bits of send block no */
    extra[1] = SendBlkNo >> 8;        /* high 8 bits of send block no */
    crc_value = CRC( extra, num, p );  /* calculate crc for (blk#+err+data) */
    crc_low = crc_value & 0xff;        /* low 8 bits of crc_value */
    crc_hi  = crc_value >> 8;          /* high 8 bits of crc_value */

    wait = (MaxBaud == MIN_BAUD) ? SEC(2) : SEC(1);
    for( ;; ) {                 /* send block loop */
        /* send the block */
        StartBlockTrans();
        SendByte( STX );
        SendByte( crc_low );
        SendByte( crc_hi );
        SendByte( len_low );
        SendByte( len_hi );
        SendByte( extra[0] );      /* blkno_low */
        SendByte( extra[1] );      /* blkno_hi */
        SendByte( extra[2] );      /* err */
        for( i = 0; i < num; ++i ) {
            SendByte( p[i] );
        }
        SendByte( ETX );
        StopBlockTrans();

        wait_time = WaitCount() + timeout;
        for( ;; ) {                 /* wait proper acknowledgement loop */
            reply = WaitByte( wait );          /* receive reply */
            if( reply == NO_DATA ) {
                if( (timeout != FOREVER) && (WaitCount() >= wait_time) ) {
                    return( FAIL );    /* time-out */
                } else {
                    SendByte( RLR );     /* request last response */
                    ++Errors;            /* increment error counter */
                }
            } else {
                if( reply == ACK ) {
                    ++SendBlkNo;
                    return( SUCCESS );    /* done, exit from BlockSend() */
                } else if( reply == NAK ) {  /* unsuccessful, re-send block */
                    ++Errors;
                    break;     /* break out of acknowledgement loop;
                                  i.e. back to send block loop */
                } else if( reply == RLR ) {  /* request last response */
                    SendByte( LastResponse );
                    break;     /* break out ackno loop; re-send block */
                } else {       /* things are totally messed up */
                    while( WaitByte( SEC(3)/4 ) != NO_DATA )
                        ;             /* discard all characters sent */
                    SendByte( RLR );     /* request last response */
                    ++Errors;
                }
            }
        }
    }
}


/*========================================================================*/
/*========================================================================*/


/* This routine receives a block, checks CRC, and ACKs its reception.
   The data and err are placed in the appropriate places as described below.
   STX of block should already have been read and discarded.
   The block format is documented in BlockSend().

   Return:  FAIL         --  not enough buffer space to store data block
            FAIL         --  fails for other reason than FAIL_BUFFER
            SUCCESS  --  data block is stored at *p; prev err no. at *err */

static int BlockReceive( char * err, unsigned max_len,
                          char * p )
{
    char buffer[8];     /* storing bytes other than actual data from blocks */
    int  i;             /* loop index */
    unsigned    len;
    word        crc_val;
    unsigned    blkno;
    int         c;
    int         wait;

    ZeroWaitCount();
    BytesReceived = 0;
    wait = (MaxBaud == MIN_BAUD) ? SEC(1)/2 : SEC(1)/4;
    /* Receiving bytes before actual data (up to err byte) */
    for( i = 1; i <= 7; ++i ) {
        c = WaitByte( wait );
        if( c == NO_DATA ) {    /* time-out error */
            LastResponse = NAK;
            SendByte( NAK );  /* send NAK to request resending of block */
            return( FAIL );
        }
        buffer[i] = c;
    }

    len = (buffer[MLEN+1] << 8) | buffer[MLEN];   /* number of data bytes */
    if( len > max_len ) {        /* not enough buffer space to store data */
        ClearCom();
        return( FAIL );
    }

    /* Receiving actual data bytes */
    for( i = 0; i < len; ++i ) {
        c = WaitByte( wait );
        if( c == NO_DATA ) {    /* time-out error */
            LastResponse = NAK;
            SendByte( NAK );  /* send NAK to request resending of block */
            return( FAIL );
        }
        p[i] = c;
    }

    /* Receiving the last byte: ETX */
    buffer[0] = WaitByte( wait );
    if( buffer[0] != ETX ) {    /* time-out error */
        LastResponse = NAK;
        SendByte( NAK );  /* send NAK to request resending of block */
        return( FAIL );
    }

    *err = buffer[MERR];            /* storing command byte */
    blkno = (buffer[MBLKNO+1] << 8) | buffer[MBLKNO];  /* blk# received */
    crc_val = (buffer[MCRC+1] << 8) | buffer[MCRC];  /* crc received */

    if( CRC( &buffer[MBLKNO], len, p ) != crc_val ) {   /* CRC error */
        LastResponse = NAK;
        SendByte( NAK );  /* send NAK to request resending of block */
        return( FAIL );
    }

    if( ReceiveBlkNo != blkno ) {      /* incorrect block */
        ClearCom();
        LastResponse = ACK;
        SendByte( ACK );
        return( FAIL );
    }

    /* Block received successfully */
    LastResponse = ACK;
    SendByte( ACK );
    ++ReceiveBlkNo;
    BytesReceived = len;
    return( SUCCESS );
}


/*========================================================================*/
/*========================================================================*/


/* This routine attempts to receive a block within the time limit defined
      in parameter timeout.

   Return:  FAIL         --  not enough buffer space to store block
            FAIL         --  block is not available/received successfully
            SUCCESS      --  data block is stored at *p; prev err no. at *err */

static int WaitReceive( char * err, unsigned max_len,
                         char * p, unsigned timeout )
{
    unsigned wait_time;               /* timer */
    int      data;                    /* data from other machine */
    int      result;                  /* result of BlockReceive() */

    ZeroWaitCount();
    wait_time = WaitCount() + timeout;
    for( ;; ) {
        data = WaitByte( 1 );
        if( data == STX ) {           /* STX received, get block */
            result = BlockReceive( err, max_len, p );
            if( result ) return( result );
        } else if( data == RLR ) {    /* RLR received */
            SendByte( NAK );          /* tell the other end to resend block */
        } else if( (timeout != FOREVER) && (WaitCount() >= wait_time) ) {
            return( FAIL );           /* time-out */
        }
    }
}

/*========================================================================*/
/*========================================================================*/


/* This routine ReSync speed.  Returns:  SUCCESS or FAIL */

static int ReSync( void )
{
    int result;            /* result of ReSyncing */

    ++BaudCounter;              /* next slower speed */
    if( BaudCounter > MIN_BAUD ) BaudCounter = MIN_BAUD;
    while( SetSyncTime() == FAIL ) ;
    result = Speed();           /* sync */
    return( result );
}


/*========================================================================*/
/*========================================================================*/


/* Function to see if two strings (pointed to by far pointers) are
   identical.   Returns SUCCESS (identical) or FAIL (not identical) */

static int StrEq( char *s1, char *s2 )
{
    while( (*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2) ) {
        ++s1;
        ++s2;
    }
    if( *s1 == '\0' ) {
        return( SUCCESS );
    } else {
        return( FAIL );
    }
}


/*========================================================================*/
/*========================================================================*/


/* Routine used by RemoteLink() to set maximum baud rate */

char *SetMaxBaud( char *str )
{
    int i;              /* loop index */

    for( i = 0; i <= MIN_BAUD; ++i ) {
        if( StrEq( str, BaudTable[i].name ) ) {  /* strings are equal */
            MaxBaud = i;
            return( NULL );
        }

⌨️ 快捷键说明

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