recv.c
来自「wince下的源代码集合打包」· C语言 代码 · 共 382 行
C
382 行
/*++Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved.Module Name: recv.cAbstract:Environment:--*/#include "windows.h"#include "tapi.h"#include "ndis.h"#include "ndiswan.h"#include "ndistapi.h"#include "asyncmac.h"#include "frame.h"#include "cclib.h"//// The receive packet data buffer is allocated so as to contain://// 1. 128 bytes of header space reserved for PPP Van Jacobsen TCP/IP header decompression, plus// 2. 2 bytes for PPP protocol field, plus// 3. MaxFrameSize (typically 1500) bytes of PPP frame data, plus// 4. 2 bytes for a 16-bit CRC//// Note that the recv packet buffer does not need to deal with escaped bytes or flags.// Those bytes are processed by the receive state machine and so are never stored in the receive packet buffer.// See RFC 1661 Section 6.1 description of Maximum-Receive-Unit//#define HEADER_BYTES_RESERVED_FOR_VAN_JACOBSEN_DECOMPRESSION 128#define MAX_PROTOCOL_FIELD_LENGTH 2//// Activesync 3.1 seems to send frames that are larger than the default MTU.// So, we add some extra bytes factor to allow it to work with this asyncmac driver.//#define ACTIVESYNC31_EXTRA_BYTES 50#define TRAILER_BYTES_FOR_CRC 2#define RECEIVE_PACKET_SIZE(pAdapter) (HEADER_BYTES_RESERVED_FOR_VAN_JACOBSEN_DECOMPRESSION + \ MAX_PROTOCOL_FIELD_LENGTH + \ (pAdapter)->Info.MaxFrameSize + \ ACTIVESYNC31_EXTRA_BYTES + \ TRAILER_BYTES_FOR_CRC)voidProcessEndOfPacket( PASYNCMAC_OPEN_LINE pOpenLine, PBYTE pRecvPacket, DWORD cbPacketData)//// Process packet data when the closing flag is received.//// Check the CRC and indicate the the packet to the protocol if it is good.//{ USHORT CRCData; NDIS_STATUS Status; PASYNCMAC_ADAPTER pAdapter = pOpenLine->pAdapter; BOOLEAN bGoodCRC = TRUE; DEBUGMSG (ZONE_FUNCTION | ZONE_RECV, (TEXT("AsyncMac: +ProcessEndOfPacket: length=%d\n"), cbPacketData)); if (pOpenLine->WanLinkInfo.RecvFramingBits & PPP_FRAMING) { // Packet must contain at least 1 byte of data + 2 CRC bytes to be valid if (cbPacketData < (1 + TRAILER_BYTES_FOR_CRC)) { DEBUGMSG (ZONE_RECV, (TEXT("MaxRxThread: Discarding short packet of length %d\n"), cbPacketData)); return; } // Extract the 16 bit CRC from the last two bytes of the packet data // Note that the LSB of the CRC is transmitted first CRCData = (pRecvPacket[cbPacketData-1] << 8) | pRecvPacket[cbPacketData-2]; CRCData ^= 0xFFFF; cbPacketData -= TRAILER_BYTES_FOR_CRC; // Validate the CRC bGoodCRC = CRCData == CalcCRCPPP (pRecvPacket, cbPacketData); } if (bGoodCRC) { DEBUGMSG (ZONE_RECV, (TEXT("AsyncMac: MaxRxThread: Have good packet\n"))); NdisMWanIndicateReceive(&Status, pAdapter->hMiniportAdapter, pOpenLine->hNdisLinkContext, pRecvPacket, cbPacketData); NdisMWanIndicateReceiveComplete (pAdapter->hMiniportAdapter, pOpenLine->hNdisLinkContext); if (NDIS_STATUS_SUCCESS != Status) { DEBUGMSG (ZONE_ERROR, (TEXT("MacRxThread: ERROR: NdisMWanIndicateReceive Status=0x%X\n"), Status)); } } else { DEBUGMSG (ZONE_RECV, (TEXT("AsyncMac: CRC Error 0x%X != 0x%X\n"), CRCData, CalcCRCPPP (pRecvPacket, cbPacketData))); }}DWORD WINAPIMacRxThread (LPVOID pVArg){ PASYNCMAC_OPEN_LINE pOpenLine; PBYTE pRecvPacketStart, pRecvPacket, pRecvPacketCurrent, pRecvPacketEnd, pRecvBuffer; BOOL bByteIsEscaped, bFrameTooLong, bPppFraming; COMMTIMEOUTS CommTimeouts; DWORD Error, cbRecvBuffer; // Establish a reference to openline pOpenLine = GetOpenLinePtr(pVArg); if (pOpenLine == NULL) { DEBUGMSG (ZONE_ERROR | ZONE_RECV, (TEXT("\n-MacRxThread: Unable to get reference to pOpenLine\n"))); return 0; } ASSERT (CHK_AOL(pOpenLine)); ASSERT (CHK_AA(pOpenLine->pAdapter)); ASSERT (pOpenLine->hPort != NULL); bPppFraming = (pOpenLine->WanLinkInfo.RecvFramingBits & PPP_FRAMING) != 0; // We are interested in the following events on the comm port: // EV_RXCHAR - data has been received // EV_RLSD - carrier detect line changed state // EV_POWER - WinCE power event (port powered down) SetCommMask(pOpenLine->hPort, EV_RXCHAR | EV_RLSD | EV_POWER ); // Configure the port timeouts to: // 1. Return immediately on a ReadFile (that is, do not block waiting for bytes to arrive) // 2. Allow 500 ms + 2ms/byte before timing out a WriteFile GetCommTimeouts( pOpenLine->hPort, &CommTimeouts ); CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutMultiplier = 2; CommTimeouts.WriteTotalTimeoutConstant = 500; SetCommTimeouts( pOpenLine->hPort, &CommTimeouts ); // // Allocate the receive packet that we will fill in and indicate to PPP. // pRecvPacketStart = AsyncMacAllocateMemory(RECEIVE_PACKET_SIZE(pOpenLine->pAdapter)); if (pRecvPacketStart == NULL) { DEBUGMSG (ZONE_RECV, (TEXT("MacRxThread: Unable to allocate RecvPacket %d bytes\n"), RECEIVE_PACKET_SIZE(pOpenLine->pAdapter))); CloseHandle( pOpenLine->hRxThrd); pOpenLine->hRxThrd = NULL; ReleaseOpenLinePtr(pOpenLine); return 0; } // // Allocate the receive buffer passed to ReadFile to retrieve bytes from serial port. // cbRecvBuffer = pOpenLine->pAdapter->dwRecvBufSize; pRecvBuffer = AsyncMacAllocateMemory(cbRecvBuffer); if (pRecvBuffer == NULL) { DEBUGMSG (ZONE_RECV, (TEXT("MacRxThread: Unable to allocate RecvBuffer %d bytes\n"), cbRecvBuffer)); CloseHandle( pOpenLine->hRxThrd); pOpenLine->hRxThrd = NULL; AsyncMacFreeMemory (pRecvPacketStart, RECEIVE_PACKET_SIZE(pOpenLine->pAdapter)); ReleaseOpenLinePtr(pOpenLine); return 0; } // Get a pointer to the portion of the receive packet that gets filled in by AsyncMac pRecvPacket = pRecvPacketStart + HEADER_BYTES_RESERVED_FOR_VAN_JACOBSEN_DECOMPRESSION; pRecvPacketEnd = pRecvPacketStart + RECEIVE_PACKET_SIZE(pOpenLine->pAdapter); bByteIsEscaped = FALSE; pRecvPacketCurrent = pRecvPacket; bFrameTooLong = TRUE; // Setting this TRUE forces us to see a flag byte (0x7E) before first packet while (pOpenLine->dwFlags & AOL_FLAGS_SENT_LINE_UP) { DWORD Mask; DWORD ModemStatus; DEBUGMSG (ZONE_RECV, (TEXT("AsyncMac: WaitCommEvent...\n"), Mask)); if ( WaitCommEvent( pOpenLine->hPort, &Mask, NULL ) == TRUE ) { ASSERT(AsyncMacGuardRegionOk(pOpenLine, sizeof(ASYNCMAC_OPEN_LINE))); ASSERT(AsyncMacGuardRegionOk(pOpenLine->pAdapter, sizeof(ASYNCMAC_ADAPTER))); ASSERT(AsyncMacGuardRegionOk(pRecvPacketStart, RECEIVE_PACKET_SIZE(pOpenLine->pAdapter))); DEBUGMSG (ZONE_RECV, (TEXT("AsyncMac: ...WaitCommEvent returned: Mask=0x%X\n"), Mask)); if (Mask & (EV_POWER | EV_RLSD)) { // Power loss/DCD change of state Detection ModemStatus = 0; (void)GetCommModemStatus(pOpenLine->hPort, &ModemStatus); if ((Mask & EV_POWER) || !(ModemStatus & MS_RLSD_ON)) { DEBUGMSG( ZONE_RECV | ZONE_ERROR,( TEXT( "AsyncMac: Power=%hs CD=%hs\n"), Mask & EV_POWER ? "OFF" : "ON", ModemStatus & MS_RLSD_ON ? "ON" : "OFF")); // Indicate Mac down due to loss of power or carrier detect (CD) SendLineDown(pOpenLine); break; } } if (Mask & EV_RXCHAR) { // Receive data event BYTE byte; DWORD cbReceiveData, dwBytesRead; PBYTE pbReceiveData; DEBUGMSG(ZONE_RECV, (TEXT( "AsyncMac:RX avail\n" ))); // Read & process data till no more is available. do { pbReceiveData = pRecvBuffer; if (ReadFile(pOpenLine->hPort, pbReceiveData, cbRecvBuffer, &cbReceiveData, 0 ) == FALSE) { // Serial functions will return an error if a PCMCIA card has // been removed. If the error is INVALID_HANDLE or GEN_FAILURE // the PCMCIA card was removed. In this case the MAC layer is // down. Error = GetLastError(); DEBUGMSG( ZONE_RECV | ZONE_ERROR, (TEXT( "AsyncMac:ReadFile failed %d\n"), Error)); if( ((ERROR_INVALID_HANDLE == Error) || Error == ERROR_GEN_FAILURE) && !(pOpenLine->dwFlags & AOL_FLAGS_ERROR_INDICATED) ) { pOpenLine->dwFlags |= AOL_FLAGS_ERROR_INDICATED; SendLineDown (pOpenLine); } goto SerialError; } dwBytesRead = cbReceiveData; DEBUGMSG(ZONE_RECV, (TEXT("->mac:RX %d bytes, spaceLeft=%d pCurr=%x\n" ), cbReceiveData, pRecvPacketEnd - pRecvPacketCurrent, pRecvPacketCurrent));#ifdef DEBUG if (ZONE_RECV) { DEBUGMSG(1, (TEXT("\nAsyncMac ReadFile:\n"))); DumpMem(pbReceiveData, cbReceiveData); DEBUGMSG(1, (TEXT("\n\n"))); }#endif // Run the data through the RX packet state machine // // Note that the state machine does not distinguish between opening and closing // flags. Any flag both terminates a current packet (if any) and begins a new // packet. This allows a shared opening/closing flag between packets. while (cbReceiveData--) { byte = *pbReceiveData++; // // Note the sequence ESC FLAG is illegal, so we don't care whether // we are in the escaped state or not when checking for a flag. // if ( bPppFraming && byte == PPP_FLAG_BYTE || (!bPppFraming && byte == SLIP_END)) { if (pRecvPacketCurrent > pRecvPacket && !bFrameTooLong) { // Indicate the packet to the protocol as appropriate ASSERT(AsyncMacGuardRegionOk(pRecvPacketStart, RECEIVE_PACKET_SIZE(pOpenLine->pAdapter))); ProcessEndOfPacket(pOpenLine, pRecvPacket, pRecvPacketCurrent - pRecvPacket); ASSERT(AsyncMacGuardRegionOk(pRecvPacketStart, RECEIVE_PACKET_SIZE(pOpenLine->pAdapter))); } // Reinitialize state for the next packet pRecvPacketCurrent = pRecvPacket; bFrameTooLong = FALSE; bByteIsEscaped = FALSE; } else if ( bPppFraming && byte == PPP_ESC_BYTE || (!bPppFraming && byte == SLIP_ESC)) { bByteIsEscaped = TRUE; } else // Just a regular byte { // Check that there is space left to store the byte if (pRecvPacketCurrent < pRecvPacketEnd) { if (bByteIsEscaped) { if (bPppFraming) { byte ^= 0x20; } else // SLIP { if (byte == SLIP_ESC_ESC) byte = SLIP_ESC; else if (byte == SLIP_ESC_END) byte = SLIP_END; } bByteIsEscaped = FALSE; } *pRecvPacketCurrent++ = byte; } else // no space left -- frame too long { DEBUGMSG (!bFrameTooLong && ZONE_ERROR, (TEXT("AsyncMac: MacRxThread-ERROR: Packet too long (pCurr=%x byte=%02x, offset=%d), tossing\n"), pRecvPacketCurrent, byte, pbReceiveData - pRecvBuffer)); bFrameTooLong = TRUE; } } } // while (cbReceiveData--) DEBUGMSG( ZONE_RECV, (TEXT( "Mac: RecvPacket size now %d bytes, pCurr=%x\n"), pRecvPacketCurrent - pRecvPacket, pRecvPacketCurrent)); }while( dwBytesRead ); } } else // WaitCommEvent did not return TRUE { Error = GetLastError(); DEBUGMSG( ZONE_RECV | ZONE_ERROR, (TEXT( "Mac:WaitCommEvent failed %d\n"), Error )); // Serial functions will return an error if a PCMCIA card has // been removed. If the error is INVALID_HANDLE or GEN_FAILURE // the PCMCIA card was removed. In this case the MAC layer is // down. if( (Error == ERROR_INVALID_HANDLE || Error == ERROR_GEN_FAILURE) && !(pOpenLine->dwFlags & AOL_FLAGS_ERROR_INDICATED) ) { pOpenLine->dwFlags |= AOL_FLAGS_ERROR_INDICATED; // MacNotifyDown( pOpenLine, ERROR_DEVICE_NOT_READY ); SendLineDown (pOpenLine); } goto SerialError; } }SerialError: CloseHandle( pOpenLine->hRxThrd); pOpenLine->hRxThrd = NULL; AsyncMacFreeMemory (pRecvBuffer, cbRecvBuffer); AsyncMacFreeMemory (pRecvPacketStart, RECEIVE_PACKET_SIZE(pOpenLine->pAdapter)); ReleaseOpenLinePtr(pOpenLine); DEBUGMSG (ZONE_RECV, (TEXT("\nAsyncMac: -MacRxThread: Exiting\n"))); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?