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

📄 rndis.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  
    rndis.c

Abstract:  
	This module understands RNDIS messages..	

Functions:

    
--*/

#include <windows.h>
#include <ndis.h>
#include <halether.h>
#undef ZONE_INIT
#undef ZONE_WARNING
#include <string.h>
#include <rndismini.h>
#include "mddpriv.h"
#include "rneutil.h"
#include "rndis.h"
#define __THIS_FILE__   TEXT("rndis.cpp")
#ifdef	CELOGMSG 
#undef	CELOGMSG
#endif
#define CELOGMSG(Cond, Printf_exp) ((void)0)//DEBUGCELOGMSG(Cond, Printf_exp) 
#define CELOGDUMPDATA(Cond, ID, Data, Len) ((void)0)//DEBUGCELOG(Cond, ID, Data, Len)
#define	ZONE_RNDIS		DEBUGZONE(1)
#define ZONE_DATA		DEBUGZONE(5)
#define ZONE_ERROR		DEBUGZONE(15)

#define DEBUG_SINGLE_CHAR 1
#include <celog.h>

////////////////////////////////////////////////////////////////////////////////
//	For convenience..
//

#define GET_PTR_TO_RNDIS_DATA_BUFF(_Message)                    \
    ((PVOID) ((PUCHAR)(_Message) +  _Message->DataOffset))

#define RESERVED_FROM_RECV_PACKET(_Packet)						\
    ((PRCV_RNDIS_PACKET *)((_Packet)->MiniportReserved))

#define	NDIS_PACKET_MINIPORTRESERVED(_Packet)					\
	((_Packet)->MiniportReserved)

#define MIN(x,y) ((x > y) ? y : x)

DWORD OEMEthGetSecs(void);


////////////////////////////////////////////////////////////////////////////////
//	Externs..
//

//extern NPAGED_LOOKASIDE_LIST	DataWrapperLookAsideList;



////////////////////////////////////////////////////////////////////////////////
//	Global variable for RNDIS MDD..
//

RNDIS_MDD				RndisMdd;				
//NPAGED_LOOKASIDE_LIST	RcvRndisPacketLookAsideList;
//NDIS_HANDLE				NdisPacketPool;
//NDIS_HANDLE				NdisBufferPool;
//HANDLE					g_TxEvent;

// RNDIS Message Buffer
static BufferDescript MsgBufferDesc;
static BYTE MsgBuffer[MAX_PACKET_SIZE+4*(sizeof(DATA_WRAPPER)+sizeof(DWORD))];

// Ethernet Frame
#define MAX_ETH_BLOCK 1520
static BufferDescript EthBufferDesc;
static BYTE EthBuffer[(MAX_ETH_BLOCK+sizeof(DWORD))*10];



////////////////////////////////////////////////////////////////////////////////
//	RndisStartRNDISMINI1()
//
//	Routine Description:
//
//		Thread that instantiate the virtual adapter instance.
//	
//	Arguments:
//
//		None.
//
//	Return Value:
//
//		None.
//
//void
//RndisStartRNDISMINI1(void)
//{
//	VMiniInstantiateMiniport(TRUE);
//
//}	//	RndisStartRNDISMINI1()



////////////////////////////////////////////////////////////////////////////////
//	RndisForceReturnCEVminiPackets()
//
//	Routine Description:
//
//		Force return all packets we queued in listVMiniNdisPackets.
//	
//	Arguments:
//
//		None.
//
//	Return Value:
//	
//		None.
//	
//	Note:
//
//		** WARNING ** This function should only be called in the INTERRUPT
//		context!!!
//	
/*
void
RndisForceReturnCEVminiPackets(void)
{
	PLIST_ENTRY		pLink;
	PNDIS_PACKET	pNdisPacket;	


	EnterCriticalSection(&RndisMdd.lockVMiniNdisPackets);

	while (!IsListEmpty(&(RndisMdd.listVMiniNdisPackets)))
	{
		ASSERT(RndisMdd.dwTotalVMiniPendings);

		pLink = RemoveHeadList(&(RndisMdd.listVMiniNdisPackets));

		RndisMdd.dwTotalVMiniPendings--;

		pNdisPacket = CONTAINING_RECORD(
							pLink,
							NDIS_PACKET,
							MiniportReserved);

		//
		//	Return the NdisPacket to VMini now..
		//	Can't be in CS since VMiniIndicatePacketDone() will use NDIS CS
		//	and NDIS may be calling RndisSendPacket() hence a deadlock!
		//

		LeaveCriticalSection(&RndisMdd.lockVMiniNdisPackets);
		VMiniIndicatePacketDone(
			pNdisPacket);
		EnterCriticalSection(&RndisMdd.lockVMiniNdisPackets);
	}

	LeaveCriticalSection(&RndisMdd.lockVMiniNdisPackets);

}	//	RndisForceReturnCEVminiPackets()
*/


////////////////////////////////////////////////////////////////////////////////
//	RndisRestart()
//
//	Routine Description:
//
//		DeInitialize RNDISMINI1 and get us back to RNDIS_UNINITIALIZED state
//		ready for new connection..
//	
//	Arguments:
//
//		bResetPDD :: TRUE if we need to reset the PDD, FALSE otherwise.
//
//	Return Value:
//	
//		None.
//	
//	Note:
//
//		** WARNING ** This function should only be called in the INTERRUPT
//		context!!!
//	
void
RndisRestart(BOOL bResetPDD)
{
	CELOGMSG  (ZONE_INIT, (TEXT("RNDISMINI --- RESTART ---\r\n")));
	
	EdbgOutputDebugString("RNDISMINI --- RESET ---\r\n");

	RndisMdd.dwDeviceState = RNDIS_UNINITIALIZED;

	//	
	//	1. Deinitialize RNDISMINI1 which in its ShutDownHandler() will get
	//		  us to return all its pending TX packets.
	//
	//	2. Hard Reset PDD.
	//		  This should cause PDD to return all pending RNDIS messages that
	//		  it may be half sending, and reset its hw to ready a future
	//		  new connection.
	//

	//
	//	Tear down CE Miniport driver RNDISMINI1
	//		

//	VMiniInstantiateMiniport(FALSE);	

	if (bResetPDD)
	{
		//
		//	HardReset the hardware here..
		//	Somehow we need to wait a while till host is not looking to do this.
		//	Otherwise host will fail to unload cleanly the rndis host 
		//	driver (???)
		//

//		Sleep(500);
		DWORD dwStartSec=OEMEthGetSecs();
		while (dwStartSec==OEMEthGetSecs()); // Wait 1 second.


		RndisMdd.PddCharacteristics.SetHandler(
			REQ_ID_HARD_RESET,
			NULL,
			0x00);
//		PDD_Set(
//			REQ_ID_HARD_RESET,
//			NULL,
//			0x00);
	}
//	else
//		RndisMdd.PddCharacteristics.SetHandler(
//			REQ_ID_SOFT_RESET,
//			NULL,
//			0x00);
//		PDD_Set(
//			REQ_ID_SOFT_RESET,
//			NULL,
//			0x00);

	// Reset to internal flag
	RndisMdd.dwCurrentPacketFilter=0;
	//InBuffer.dwDataSize==0;
	//BufferReset();
}	//	RndisRestart()



////////////////////////////////////////////////////////////////////////////////
//	RndisPrepareRndisPacket()
//	
//	Routine Description:
//
//		This function forms a linke DATA_WRAPPER and queue that to pListEntry.
//	
//	Arguments:
//
//		pNdisPacket	:: The NdisPacket that contains user data.
//		pListEntry	:: Where we link the DATA_WRAPPER containing RNDIS_PACKET
//							data header and the NdisBuffer from NdisPacket.
//							The newly formed DATA_WRAPPER will be linked at the
//							end of this list.
//		pdwTotalLen	::	Total Length of the collection of RNDIS_PACKETs so far..
//
//	Return Value:
//
//		SUCCESS, ERROR_NO_MEM, ERROR_MAX_REACHED
//

#define	SUCCESS				0x00000000
#define	ERROR_MAX_REACHED	0x00000002
DWORD
RndisPrepareRndisPacket(
	PBYTE		pDataBuffer,	
	DWORD		dwDataLen,
	PRNDIS_MESSAGE pRndisMessage,
	DWORD dwTotalMessageBufferSize)

{
	DWORD			dwCurrentPacketLength;
//	DWORD			dwTotalDataLength;
//	PRNDIS_MESSAGE	pRndisMessage;
	PRNDIS_PACKET	pRndisPacket;
//	PNDIS_BUFFER	pNdisBuffer;	

	CELOGMSG (ZONE_RNDIS,
				(TEXT("RNdis:: PrePareRndisPacket (%d Bytes)\r\n"),dwDataLen));

	if (pRndisMessage) {
		dwCurrentPacketLength =
			RNDIS_MESSAGE_SIZE (RNDIS_PACKET) + 
			dwDataLen;

		//
		//	Pad it to multiple of 8 bytes (required by RNDIS host).
		//
		
		dwCurrentPacketLength += (8 - (dwCurrentPacketLength % 8));

		if (dwCurrentPacketLength > dwTotalMessageBufferSize)
		{
			EdbgOutputDebugString("RNdis:: Too much outgoing, bailing out!\r\n");			

			CELOGMSG (ZONE_RNDIS,(TEXT("RNdis:: Max[%d] SoFar[%d] CurentPacket[%d]\r\n"),
				dwTotalMessageBufferSize,
				0,
				dwCurrentPacketLength));			

			return  ERROR_MAX_REACHED;
		}	



		//
		//	Okay, it fits.. make it..
		//
		//	Fill up the RNDIS_PACKET header
		//
		
		
		pRndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
		pRndisMessage->MessageLength   = dwCurrentPacketLength;	

		pRndisPacket = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pRndisMessage);

		pRndisPacket->DataOffset			= sizeof(RNDIS_PACKET);
		pRndisPacket->DataLength			= dwDataLen;
		pRndisPacket->OOBDataOffset			= 0x00;
		pRndisPacket->OOBDataLength			= 0x00;
		pRndisPacket->NumOOBDataElements	= 0x00;
		pRndisPacket->PerPacketInfoOffset	= 0x00;
		pRndisPacket->PerPacketInfoLength	= 0x00;
		pRndisPacket->VcHandle				= 0x00;
		pRndisPacket->Reserved				= 0x00;
		

		//
		//	Now, handle the NDIS_BUFFERs
		//

		memcpy(pRndisPacket+1,pDataBuffer,dwDataLen);

		//
		//	Outta here with flying color..
		//	Here is the new offset..
		//

		
	};
	return SUCCESS;

}	//	RndisPrepareRndisPacket()

// Rndis SendPacket flag
BOOL bRndisSendPacketEmpty=TRUE;
BOOL PDD_IsPacketSend(void)
{
	return bRndisSendPacketEmpty;
}
void
MddSendRndisPacketComplete(PDATA_WRAPPER	pDataWrapper)
{
	bRndisSendPacketEmpty=TRUE;
}	//	MddSendRndisPacketComplete()

////////////////////////////////////////////////////////////////////////////////
//	RndisSendPacket()
//	
//	Routine Description:
//
//		When VMini has packet to indicate up to the Rndis host..
//		If we are not already sending, then start the PDD to send otherwise
//		queue this NdisPacket.
//	
//	Arguments:
//
//		pNdisPacket	:: The Ndis packet.
//
//	Return Value:
//
//		TRUE if we want to keep the packet, FALSE otherwise.
//
#define RNDIS_MESSAGE_HEAD_SIZE (sizeof(RNDIS_MESSAGE) - sizeof(RNDIS_MESSAGE_CONTAINER))

UINT16 RndisEDbgSendFrame(BYTE * pData, DWORD dwLength)
{
	DWORD	dwTotalLen  = 0x00;
	DWORD	dwWaitMSec=0;
	BOOL	bSuccess = FALSE;
	static BYTE bTempBuffer[MAX_PACKET_SIZE];
	PRNDIS_MESSAGE pRndisMessage=(PRNDIS_MESSAGE)bTempBuffer;
	DWORD dwTotalMessageBufferSize=MAX_PACKET_SIZE- RNDIS_MESSAGE_HEAD_SIZE;
	DWORD dwStartSec=OEMEthGetSecs();

	CELOGMSG (ZONE_DATA,(TEXT("Rndis::RndisEDbgSendFrame(dwLength=%d)\r\n"),dwLength));
	
	while  (RndisMdd.dwCurrentPacketFilter == 0 && 	OEMEthGetSecs()- dwStartSec <2) 
		//PDD_ISR();
		RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);

	if (RndisMdd.dwCurrentPacketFilter == 0)
	{
		CELOGMSG (ZONE_DATA,(TEXT("Rndis::RndisSendPacket() to host:: Reject! filter == 0\r\n")));
		return 1;
	}
	


	if (RndisPrepareRndisPacket(pData,dwLength,pRndisMessage,dwTotalMessageBufferSize)
		==SUCCESS) {

		static DATA_WRAPPER DataWrapper;
		
		dwStartSec=OEMEthGetSecs();
		DataWrapper.Link.Flink= DataWrapper.Link.Blink=NULL;
		DataWrapper.pucData=bTempBuffer;
		DataWrapper.dwDataSize=pRndisMessage->MessageLength + RNDIS_MESSAGE_HEAD_SIZE;
		bRndisSendPacketEmpty=FALSE;

		do
		{	
			//
			//	PDD is idling, kick start the sending process..
			//
//			if (PDD_SendRndisPacket(&DataWrapper)) {
			RndisMdd.PddCharacteristics.SendRndisPacketHandler(&DataWrapper);
			bSuccess = TRUE;

//			}
//			PDD_ISR();
			RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);

		}while (!bSuccess && (OEMEthGetSecs()-dwStartSec<2));

		if (bSuccess) { // Loop until success.
			while (!PDD_IsPacketSend())
//				PDD_ISR();
				RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);
		}

	}

//	PDD_ISR();
	RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);
//	EdbgOutputDebugString("Rndis::RndisEDbgSendFrame return (%d) Byte (%d)\r\n",bSuccess,dwLength);
	return (bSuccess?0:1);

}	//	RndisSendPacket()


void
MddSendRndisMessageComplete(PDATA_WRAPPER pDataWrapper)	
{

	if (FreeBuffer(&MsgBufferDesc, pDataWrapper)==FALSE) {
		EdbgOutputDebugString("ASSERT! Rndis::MddSendRndisMessageComplete return FALSE\r\n");
	}
}	//	MddSendRndisMessageComplete();

////////////////////////////////////////////////////////////////////////////////
//	RndisSendRndisMessage()
//	
//	Routine Description:
//
//		This function creates RNDIS message and send it out.  
//	
//	Arguments:
//
//		None.
//

⌨️ 快捷键说明

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