testtoolsconn/wintap/src/wintap.cpp
changeset 0 3da2a79470a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testtoolsconn/wintap/src/wintap.cpp	Mon Mar 08 15:04:18 2010 +0800
@@ -0,0 +1,360 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+
+#include "wintap.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#ifdef EKA2
+#include <platform/emulator.h>
+#endif
+/**
+ *
+ *	The start of most EtherTap specific routines
+ *
+ **/
+
+static TIsr GlobIsr = NULL;
+static void * GlobObj = NULL;
+
+static int MatchTunAdapter(const char* aDevName)
+	{
+	const char match[] = "TAP";
+	const char matchl[] = "tap";
+
+	// Check the first 3 charecters
+	if (aDevName[0] == match[0]
+		&& aDevName[1] == match[1]
+		&& aDevName[2] == match[2])
+		return 1;
+	else if (aDevName[0] == matchl[0]
+		&& aDevName[1] == matchl[1]
+		&& aDevName[2] == matchl[2])
+		return 1;
+	else
+		return 0;
+	}
+
+static int GetIfName(IP_ADAPTER_INFO& iAdapterinfo)
+	{
+	DWORD			numInterfaces;
+    HMODULE hModule = LoadLibraryA("iphlpapi.dll");
+    if(!hModule)
+        return -1;
+    DWORD (WINAPI * pfGetNumberOfInterfaces)(PDWORD) = (DWORD (WINAPI * )(PDWORD))GetProcAddress(hModule, "GetNumberOfInterfaces");
+    DWORD (WINAPI * pfGetAdaptersInfo)(PIP_ADAPTER_INFO,PULONG) = (DWORD (WINAPI *)(PIP_ADAPTER_INFO,PULONG))GetProcAddress(hModule, "GetAdaptersInfo");
+
+	// weiredness alert - windows returns found adapters+1
+	if (pfGetNumberOfInterfaces(&numInterfaces) != ERROR_SUCCESS)
+		return -1;
+
+	ULONG            ulOutBufLen;
+	ulOutBufLen = sizeof(IP_ADAPTER_INFO) * (numInterfaces);
+	
+	IP_ADAPTER_INFO  *pAdapterInfo = NULL;
+
+	pAdapterInfo = new IP_ADAPTER_INFO[numInterfaces];
+	
+	if (pAdapterInfo && (pfGetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS)) 
+		{
+		delete pAdapterInfo;
+		return -1;
+		}
+
+	IP_ADAPTER_INFO  *pCurAdapterInfo = pAdapterInfo;
+	int count = 1, matchCount = 0;
+	while (pCurAdapterInfo != NULL)
+		{	
+		// Optimize for when we already have the index
+		if (iAdapterinfo.Index == pCurAdapterInfo->Index)
+			{
+			matchCount++;
+			iAdapterinfo = *pCurAdapterInfo;
+			break;
+			}
+
+		if (MatchTunAdapter(pCurAdapterInfo->Description))
+			{
+			matchCount++;
+			iAdapterinfo = *pCurAdapterInfo;
+			}
+
+		pCurAdapterInfo = pCurAdapterInfo->Next;
+		count++;
+		}
+
+	if (matchCount == 0)
+		{
+		delete[] pAdapterInfo;
+		return -1;
+		}
+	else if (matchCount > 1)
+		{}
+	iAdapterinfo.Next = NULL;
+	delete[] pAdapterInfo;
+	return 0;
+	}
+
+static int WorkThread(HANDLE * iWinTapHandle);
+
+int InitDriver(HANDLE& iWinTapHandle, HANDLE& iThreadHandle, PACKET& iWritePacket, IP_ADAPTER_INFO& iAdapterinfo)
+// Sets up the PDD
+	{
+	int ret = 0;
+
+	if ((ret = GetIfName(iAdapterinfo)) != 0)
+		return ret;	
+
+	// Fromat the GUID to get the file name
+	char szFileName[256];	
+	sprintf(szFileName, ("%s%s%s"), ("\\\\.\\"), iAdapterinfo.AdapterName, (".tap"));
+
+	iWinTapHandle = CreateFileA(szFileName,
+								GENERIC_READ | GENERIC_WRITE,
+								FILE_SHARE_READ | FILE_SHARE_WRITE,
+								NULL,
+								OPEN_EXISTING,
+								FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
+								NULL);
+
+	if (iWinTapHandle == INVALID_HANDLE_VALUE)
+		{
+		//OUTPUT_ERROR("could not open file handle\n");
+		CloseHandle(iWinTapHandle);
+		ret = -1;
+		return ret;
+		}
+
+	
+	// set the device to connected
+	ULONG status = 1;
+	DWORD len;
+	if (!DeviceIoControl(iWinTapHandle,
+		TAP_IOCTL_SET_MEDIA_STATUS ,&status, sizeof(status), &status, sizeof(status), &len, NULL))
+		{
+		// FUDGE alert
+		if (!DeviceIoControl(iWinTapHandle,
+			TAP_IOCTL_SET_MEDIA_STATUS_V8 ,&status, sizeof(status), &status, sizeof(status), &len, NULL))
+			{
+			//OUTPUT_ERROR("Could not set media status to open\n");
+			return ret;
+			}
+		}
+	
+	// Call GetDriverName again, this time to reset the correct info for the connected Device
+	if((ret = GetIfName(iAdapterinfo)) != 0)
+		return ret;
+
+	iWritePacket.OverLapped.hEvent 		= CreateEvent(NULL, TRUE, FALSE, NULL);
+
+	u_long WorkerThreadId;
+	    
+	if ((iThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WorkThread, &iWinTapHandle,
+		CREATE_SUSPENDED,&WorkerThreadId)) != NULL)
+		{
+		ret = 0;
+		}
+	else
+		{
+		//OUTPUT_ERROR("CreateThread() failed to create worker thread");
+		}
+
+	return ret;
+	}
+
+void DoClose(HANDLE& iWinTapHandle, HANDLE& iThreadHandle, PACKET& iWritePacket)
+	{
+	if (iWinTapHandle != INVALID_HANDLE_VALUE)
+		{
+		// Cancel reads, Writes 
+		CancelIo(iWinTapHandle);
+
+		// Close read and write events
+		CloseHandle(iWritePacket.OverLapped.hEvent);
+		
+		// Close the read thread
+		if (!TerminateThread(iThreadHandle, 0))
+			{
+			//__KTRACE_OPT(KHARDWARE, Kern::Printf("Could not Terminate thread\n"));
+			}
+		CloseHandle(iThreadHandle);
+
+		DWORD status = 0, len;
+		if (!DeviceIoControl(iWinTapHandle,
+			TAP_IOCTL_SET_MEDIA_STATUS ,&status, sizeof(status), &status, sizeof(status), &len, NULL))
+			{
+			// Big fudge --
+			if (!DeviceIoControl(iWinTapHandle,
+				TAP_IOCTL_SET_MEDIA_STATUS_V8 ,&status, sizeof(status), &status, sizeof(status), &len, NULL))
+				{
+				//__KTRACE_OPT(KHARDWARE, Kern::Printf("Could not set media status to close\n"));
+				}
+			}
+
+		CloseHandle(iWinTapHandle);
+		iWinTapHandle = INVALID_HANDLE_VALUE;
+		}
+	}
+
+void SetIsr(void * aObject, TIsr aIsr)
+	{
+	assert(aIsr != NULL);
+	assert(aObject != NULL);
+	GlobObj = aObject;
+	GlobIsr = aIsr;
+	}
+
+static int WorkThread(HANDLE * iWinTapHandle)
+	{
+    //__KTRACE_OPT(KHARDWARE, Kern::Printf("WorkThread(DEthernetWins * aDEthernetWins)"));
+	int err = 0;
+
+	u_char			buffer[2000];
+	PACKET			m_ReadPacket;
+
+	m_ReadPacket.OverLapped.hEvent 		= CreateEvent(NULL, TRUE, FALSE, NULL);
+	
+	while( err == 0 )
+		{		
+		m_ReadPacket.OverLapped.Offset 		= 0;
+		m_ReadPacket.OverLapped.OffsetHigh 	= 0;
+		m_ReadPacket.OverLapped.Internal	= 0;
+		m_ReadPacket.OverLapped.InternalHigh= 0;
+		m_ReadPacket.Buffer					= buffer;
+		m_ReadPacket.Length					= 0;
+
+    	//__KTRACE_OPT(KHARDWARE, Kern::Printf("Starting to Read \n"));
+	    if (*iWinTapHandle != INVALID_HANDLE_VALUE)
+			{
+			if (!ReadFile(*iWinTapHandle, m_ReadPacket.Buffer, 2000, 
+				&(m_ReadPacket.Length), &m_ReadPacket.OverLapped))
+				{
+				if(GetLastError() != ERROR_IO_PENDING) 
+					{
+					//__KTRACE_OPT(KHARDWARE, Kern::Printf("m_ReadPacket() Failed "));
+					err = -3;
+					break;
+					}
+				
+				DWORD Result = WaitForSingleObject(m_ReadPacket.OverLapped.hEvent, INFINITE);
+
+				switch(Result)
+					{
+					// OVERLAPPED structure's event has been signaled. 
+					case WAIT_OBJECT_0:
+						if (GetOverlappedResult(*iWinTapHandle, &m_ReadPacket.OverLapped, 
+							&m_ReadPacket.Length, FALSE) == 0)
+							{
+    						//__KTRACE_OPT(KHARDWARE, Kern::Printf("** Error in m_ReadPacket() **\n"));
+							err = -3;
+							}
+						else
+							{
+							// m_ReadPacket operation completed successfully.
+    						//__KTRACE_OPT(KHARDWARE, Kern::Printf("** Completed in m_ReadPacket() **\n"));
+							err = 0;
+							}
+						break;
+					default:
+						 // An error has occurred in WaitForSingleObject.
+						 // This usually indicates a problem with the
+						// OVERLAPPED structure's event handle.
+						err = -3;
+						break;
+					}
+				}
+			else
+				{
+				err = 0;
+    			//__KTRACE_OPT(KHARDWARE, Kern::Printf("** Completed in m_ReadPacket() **\n"));
+				}			
+			}
+		else
+			{
+    		//__KTRACE_OPT(KHARDWARE, Kern::Printf("ReadPacket() No adaptor open\n"));
+			err = -1;
+			}
+		GlobIsr(GlobObj, err, buffer, &m_ReadPacket.Length);
+		}
+	CloseHandle(m_ReadPacket.OverLapped.hEvent);
+	return -3;
+	}
+
+int DoSend(PACKET& iWritePacket, HANDLE& iWinTapHandle)
+	{
+    //__KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send(TBuf8<KMaxEthernetPacket+32> &aBuffer)"));
+    int err;
+    if ( iWinTapHandle != INVALID_HANDLE_VALUE )
+		{
+		iWritePacket.OverLapped.Offset 		= 0;
+		iWritePacket.OverLapped.OffsetHigh 	= 0;
+		iWritePacket.OverLapped.Internal		= 0;
+		iWritePacket.OverLapped.InternalHigh	= 0;
+		
+		if(!WriteFile(iWinTapHandle, iWritePacket.Buffer, iWritePacket.Length, NULL, &iWritePacket.OverLapped))
+			{
+			if(GetLastError() != ERROR_IO_PENDING) 
+				{
+				//__KTRACE_OPT(KHARDWARE, Kern::Printf("WriteFile() Failed  "));
+				err = -23; //KErrWrite
+				return err;
+				}
+			else	//Pending Write
+				{
+				DWORD written;
+				DWORD Result = WaitForSingleObject(iWritePacket.OverLapped.hEvent, INFINITE);
+				switch(Result)
+					{
+					// OVERLAPPED structure's event has been signaled. 
+					case WAIT_OBJECT_0:
+						if (!GetOverlappedResult(iWinTapHandle, &iWritePacket.OverLapped, &written, FALSE))
+							{
+			            	//__KTRACE_OPT(KHARDWARE, Kern::Printf("** Error in WritePacket() **\n"));
+							err = -23; //KErrWrite
+							}
+						else
+							{
+							// Write operation completed successfully.
+            				//__KTRACE_OPT(KHARDWARE, Kern::Printf("** Completed in WritePacket() **"));
+							err = 0;
+							}
+						break;
+					default:
+						 // An error has occurred in WaitForSingleObject.
+						 // This usually indicates a problem with the
+						// OVERLAPPED structure's event handle.
+						err = -23; //KErrWrite
+						break;
+					}
+				}
+			}
+		else //Write went fine
+			{
+            //__KTRACE_OPT(KHARDWARE, Kern::Printf("** Completed in WritePacket() **\n"));
+			err = 0;
+			}
+		}
+    else
+		{
+        //__KTRACE_OPT(KHARDWARE, Kern::Printf("WritePacket() No adaptor open\n"));
+		err = -12; //KErrPathNotFound
+		}
+    return err;
+	}