xmodem.cpp
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C++ 代码 · 共 464 行
CPP
464 行
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
xmodem.cxx
Abstract:
This module implements xmodem transfer protocal class functions
Author:
Jun Liu 2-Aug-1996
Revision History:
John Cooper (johncoop) 97-Oct-24: Ported to LC2 platform
--*/
#include <windows.h>
#include "alt_def.h"
#include "bootldr.h"
#include "xmodem.hpp"
#include "uart.h"
#include "romdef.h"
#define ASC_ESC 0x1b /* Escape */
extern "C" VOID
startcount(
);
extern "C" ULONG
checkcount(
);
PVUCHAR pUart = (PVUCHAR) (UART2_BASE | KSEG1_BASE);
/////////////////////////////////////////////////////////////////////
///+
BOOL CXModem::RxData( UCHAR &inData )
///
/// Check for incoming data
///
/// Return: TRUE - Incoming data received
/// FALSE - No incoming data
///
{
ULONG Status;
Status = pUart[LINE_STATUS];
if ( ((PSP_LINE_STATUS)(&Status))->DataReady ) {
inData = (UCHAR) pUart[RECEIVE_BUFFER];
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////
///+
void CXModem::TxData( UCHAR outData )
///
/// Send a byte of data
///
{
ULONG Status;
Status = pUart[LINE_STATUS];
while ( !((PSP_LINE_STATUS)(&Status))->TransmitHoldingEmpty ) {
Status = pUart[LINE_STATUS];
}
pUart[TRANSMIT_BUFFER] = outData;
}
/////////////////////////////////////////////////////////////////////
///+
void CXModem::AddCRC( UCHAR data )
///
/// Add data into CRC
///
{
INT i;
crc_computed = crc_computed ^ (INT)data << 8;
for (i=0; i<8; ++i) {
if ( crc_computed & 0x8000 ) {
crc_computed = crc_computed << 1 ^ 0x1021;
} else {
crc_computed = crc_computed << 1;
}
}
}
/////////////////////////////////////////////////////////////////////
///+
BOOL CXModem::WaitStart()
///
/// Wait for XMODEM receiving to start
///
/// Return: TRUE - XMODEM downloading started
/// FALSE - XMODEM downloading aborted
///
/// Note: User can press ESC to abort the downloading.
///
{
UCHAR data;
startcount();
ResetXModem();
while (1) {
//
// Wait for hand shake ack
//
if ( RxData(data) ) {
if ( data == MODEM_SOH ) {
blockSize = 128;
lastBlockSize = blockSize;
return TRUE;
}
if ( data == MODEM_STX ) {
blockSize = 1024;
lastBlockSize = blockSize;
return TRUE;
}
if ( data == ASC_ESC ) {
AssertXMError( User_Abort );
return FALSE;
}
}
//
// Send out hand shake signal once a while
//
if ( checkcount() > C_TIMEOUT ) {
TxData(MODEM_C);
startcount();
}
}
}
/////////////////////////////////////////////////////////////////////
///+
BOOL CXModem::WaitBlockNumber()
///
/// Wait for XMODEM receiving the block number complement
///
/// Return: TRUE - XMODEM received block number complement
/// (May not be correct)
/// FALSE - Timeout, should restart the XModem
///
{
UCHAR data;
UCHAR receivedblockCount;
//
// Wait for block number
//
startcount();
while (1) {
// Check if block number is received
if ( RxData(receivedblockCount) ) break;
// Check for timeout
if ( checkcount() > DATA_TIMEOUT ) {
AssertXMError( Block_Number_Timeout );
return FALSE;
}
}
//
// Wait for block number complement
//
startcount();
while (1) {
// Check block number
if ( RxData(data) ) {
// Check if complement matches
if ( (data+receivedblockCount) != 0xff ) {
AssertXMError( Block_Number_Unmatch );
}
// Check if it is re-doing the last block
// or reciving the very first block
if ( receivedblockCount == blockCount) {
ClrCRC();
return TRUE;
}
// Check if it is a new block
if ( (receivedblockCount == blockCount+1) ||
((receivedblockCount==0) && (blockCount==0xff)) ) {
blockCount = receivedblockCount;
blockPtr += lastBlockSize;
lastBlockSize = blockSize;
ClrCRC();
return TRUE;
}
// Error: the block number doesn't make sense
AssertXMError( Non_Sequential_Block_Number );
return TRUE;
}
// Check for timeout
if ( checkcount() > DATA_TIMEOUT ) {
AssertXMError( Complement_Block_Number_Timeout );
return FALSE;
}
}
}
/////////////////////////////////////////////////////////////////////
///+
BOOL CXModem::WaitData()
///
/// Wait for data
///
/// Return: TRUE - XMODEM received data block
/// FALSE - Timeout, should restart the XModem
///
{
UCHAR data;
UINT i;
for (i = 0; i<blockSize; i++) {
startcount();
while (1) {
if ( RxData(data) ) {
*(UCHAR*)(blockPtr+i) = data;
AddCRC( data );
break;
};
if ( checkcount() > DATA_TIMEOUT ) {
AssertXMError( Data_Timeout);
return FALSE;
};
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
///+
BOOL CXModem::WaitCRC()
///
/// Wait for CRC check sum
///
/// Return: TRUE - XMODEM received check sum
/// FALSE - Timeout, should restart the XModem
///
{
UCHAR data;
INT crc_received;
//
// Wait CRC check sum high byte
//
startcount();
while (1) {
// Wait for CRC check sum high byte
if ( RxData(data) ) {
crc_received = data << 8;
break;
}
// Check for timeout
if ( checkcount() > DATA_TIMEOUT ) {
AssertXMError( Checksum_High_Timeout );
return FALSE;
}
}
//
// Wait CRC check sum low byte
//
startcount();
while (1) {
// Wait for CRC check sum low byte
if ( RxData(data) ) {
crc_received |= data ;
break;
}
// Check for timeout
if ( checkcount() > DATA_TIMEOUT ) {
AssertXMError( Checksum_High_Timeout );
return FALSE;
}
}
if ( crc_received != GetCRC() ) {
AssertXMError( Bad_Checksum );
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
///+
BOOL CXModem::WaitSOH()
///
/// Wait for SOH control character
///
/// Return: TRUE - SOH or STX or EOT recived
/// FALSE - Timeout
///
///
{
UCHAR data;
startcount();
while (1) {
// Wait for hand shake (SOH or EOT)
if ( RxData(data) ) {
if ( data == MODEM_SOH ) {
blockSize = 128;
return TRUE;
}
if ( data == MODEM_STX ) {
blockSize = 1024;
return TRUE;
}
if ( data == MODEM_EOT ) {
TxData(MODEM_ACK);
AssertXMError( EOT_received );
return TRUE;
}
startcount();
}
// Send out hand shake signal once a while
if ( checkcount() > SOH_TIMEOUT ) {
AssertXMError( SOH_Timeout );
return FALSE;
}
}
}
/////////////////////////////////////////////////////////////////////
///+
UINT CXModem::Receive( ADDRESS buf )
///
/// Start XModem receive
///
/// Return: The number of bytes received
/// If it is zero, an error condition has occurred.
///
{
// Initialize the buffer pointer
target_buffer = buf;
// Clear error count
errCount = 0;
// Wait X Modem start
if ( !WaitStart() ) {
return 0;
}
//
// X Modem main loop
//
do {
if ( !WaitBlockNumber() ) {
if ( !WaitStart() ) {
return 0;
}
} else if ( !WaitData() ) {
if ( !WaitStart() ) {
return 0;
}
} else if ( !WaitCRC() ) {
if ( !WaitStart() ) {
return 0;
}
} else {
if ( modemError == No_Error ) {
TxData(MODEM_ACK);
if ( !WaitSOH() )
if ( !WaitStart() ) return 0;
} else {
modemError = No_Error;
if ( errCount > XMODEM_MAX_ERROR ) {
TxData(MODEM_CAN);
errCount = 0;
if ( !WaitStart() ) return 0;
} else {
TxData(MODEM_NCK);
if ( !WaitSOH() )
if ( !WaitStart() ) return 0;
}
}
}
} while ( modemError != EOT_received );
return (UINT)(blockPtr - target_buffer + blockSize);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?