telephonyserverplugins/simtsy/src/csimsmartcardeap.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/telephonyserverplugins/simtsy/src/csimsmartcardeap.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/simtsy/src/csimsmartcardeap.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,1338 +1,1338 @@
-// Copyright (c) 2006-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:
-// Defines the CSimSmartCardEap class componenet
-// 
-//
-
-/**
- @file
-*/
-
-#include <testconfigfileparser.h>
-#include "csimsmartcardeap.h"
-#include "Simlog.h"
-#include "etelext.h"
-
-// CSimSmartCardEapManager implementation; related to CSimSmartCardEap //
-
-/**
-Default constructor to initialise Ptrs.
-*/
-TEapChngResp::TEapChngResp()
-: iChallenge(NULL), iResp(NULL),
-  iAuthStatus(RMobileSmartCardEap::ENoAuthStarted)
-	{
-	}
-
-/**
-Default constructor to initialise Ptrs.
-*/
-TEapProcedureData::TEapProcedureData()
-: iEapKey(NULL), iEapExtKey(NULL), iEapId(NULL), iEapPsId(NULL)
-	{
-	}
-
-/**
-Factory constructor.
-*/
-CSimSmartCardEapManager* CSimSmartCardEapManager::NewL(CSimPhone *aPhone)
-	{
-	CSimSmartCardEapManager* phone = new(ELeave) CSimSmartCardEapManager(aPhone);
-	CleanupStack::PushL(phone);
-	phone->ConstructL();
-	CleanupStack::Pop();
-	return phone;
-	}
-
-/**
-Default constructor, initialises a pointer to the owner phone object.
-*/
-CSimSmartCardEapManager::CSimSmartCardEapManager(CSimPhone *aPhone)
-: iPhone(aPhone)
-	{
-	}
-
-/**
-Second-phase constructor.
-*/
-void CSimSmartCardEapManager::ConstructL()
-	{
-	LOGPHONE1("CSimSmartCardEapManager second phase construction created");
-
-	ParseEapInfoL();
-
-	LOGPHONE1("CSimSmartCardEapManager second phase construction completed");
-	}
-
-/**
-If this is destroyed then so should all EAP sub-session objects.
-*/
-CSimSmartCardEapManager::~CSimSmartCardEapManager()
-	{
-	LOGPHONE1("CSimSmartCardEapManager destructing");
-
-	for (TInt jj = iSubSessionObjs.Count()-1; jj >= 0; jj--)
-		{
-		delete iSubSessionObjs[jj];
-		}
-
-	iSubSessionObjs.Close();
-
-	ClearParsedData();
-
-	LOGPHONE1("CSimSmartCardEapManager destructed");
-	}
-
-void CSimSmartCardEapManager::ClearParsedData()
-	{
-	// Cleanup remaining unused parsed EAP procedure data
-	for (TInt jjj = 0; jjj < iEapProcData.Count(); jjj++)
-		{
-		for (TInt aa = 0; aa < iEapProcData[jjj].iChResp.Count(); aa++)
-			{
-			TEapChngResp& temp = iEapProcData[jjj].iChResp[aa];
-			delete (temp.iChallenge);
-			delete (temp.iResp);
-			temp.iChallenge = NULL;
-			temp.iResp = NULL;
-			}
-		iEapProcData[jjj].iChResp.Close();
-
-		delete iEapProcData[jjj].iEapKey;
-		delete iEapProcData[jjj].iEapExtKey;
-		delete iEapProcData[jjj].iEapId;
-		delete iEapProcData[jjj].iEapPsId;
-		iEapProcData[jjj].iEapKey = NULL;
-		iEapProcData[jjj].iEapExtKey = NULL;
-		iEapProcData[jjj].iEapId = NULL;
-		iEapProcData[jjj].iEapPsId = NULL;
-		}
-
-	iEapProcData.Close();
-	iDiscardedProcedure.Close();
-	}
-
-/**
-Returns a pointer to the selected config.txt file section.
-*/
-const CTestConfigSection* CSimSmartCardEapManager::CfgFile()
-	{
-	return iPhone->CfgFile();
-	}
-
-/**
-Parses the UICC App EAP specific settings from the config.txt.
-*/
-void CSimSmartCardEapManager::ParseEapInfoL()
-	{
-	LOGPHONE1("CSimSmartCardEapManager::ParseEapInfoL called");
-
-	CTestConfigItem* item = NULL;
-
-	LOGPHONE1("Starting to Parse Smart Card EAP Info");
-	TInt count = CfgFile()->ItemCount(KScEapProcedures);
-
-	// Used in parsing to keep track of the nested items
-	TInt nestedKeyTag = 0;
-	TInt nestedExtKeyTag = 0;
-	TInt nestedIdTag = 0;
-	TInt nestedPsIdTag = 0;
-	TInt nestedChlTag = 0;
-
-	// Counts of the total number of tags (considered as nested tags)
-	TInt countKey = CfgFile()->ItemCount(KScEapKeyMSK);
-	TInt countExtKey = CfgFile()->ItemCount(KScEapKeyEMSK);
-	TInt countId = CfgFile()->ItemCount(KScEapIdentity);
-	TInt countPsId = CfgFile()->ItemCount(KScEapPsIdentity);
-	TInt countChl = CfgFile()->ItemCount(KScEapChallenge);
-
-
-	for (TInt index = 0; index < count; index++)
-		{
-		item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapProcedures, index));
-		if(item == NULL)
-			{
-			LOGPHONE2("WARNING CONFIGURATION FILE PARSING: SC EAP PROC INFO tag not read [%d]", index);
-			continue;
-			}
-
-		TInt dataFrmt = 0;
-		TInt numChallenges = 0;
-		TInt ret = KErrNone;
-		TPtrC8 appId, eapType;
-
-		// To be populated and appended to iEapProcData later
-		TEapProcedureData procInfo;
-
-		// Get AID; convert to bin if required
-		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, appId);
-		if(ret != KErrNone)
-			{
-			LOGPARSERR("appId", ret,0,&KScEapProcedures);
-			continue;
-			}
-		else
-			{
-			procInfo.iAID = appId;
-
-			// AID is always in binary format (because of the RMobileSmartCardEap::Open construction)
-			ParseMixedBinaryAsciiDataL(procInfo.iAID);
-			}
-
-		// Get eap type
-		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 1, eapType);
-		if(ret != KErrNone)
-			{
-			LOGPARSERR("eapType", ret,1,&KScEapProcedures);
-			continue;
-			}
-		else
-			{
-			// EAP type is always in ASCII
-			procInfo.iEapType = eapType;
-			}
-
-		// Find number of challenges
-		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 2, numChallenges);
-		if(ret != KErrNone)
-			{
-			LOGPARSERR("numChallenges", ret,2,&KScEapProcedures);
-			continue;
-			}
-		else if (numChallenges > (countChl - nestedChlTag))
-			{
-			LOGPHONE2("ERROR CONFIGURATION FILE PARSING: error SC EAP PROC INFO specifies more challenges than available [%d]", index);
-			continue;
-			}
-		else if (numChallenges < 0)
-			{
-			LOGPHONE2("ERROR CONFIGURATION FILE PARSING: error SC EAP PROC INFO specifies -ve challenge number [%d]", index);
-			continue;
-			}
-
-		// Get optional data format; this format is used for all data of this parsed procedure
-		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 3, dataFrmt);
-		if(ret != KErrNone)
-			{
-			LOGPHONE2("CONFIGURATION FILE PARSING: SC EAP PROC INFO tag with no data format [%d]", index);
-			}
-		else if (dataFrmt >= EMaxConfigDataFormat)
-			{
-			LOGPHONE2("WARNING IN CONFIGURATION FILE PARSING - error wrong data format value SC EAP PROC INFO tag [%d] (ASCII format will be used)", index);
-			dataFrmt = EConfigDataFormatAscii;
-			}
-
-		TPtrC8 ptr;
-		TPtr8 tempPtr(NULL,0);
-		HBufC8* startData = NULL;
-
-		// Get MSK
-		if (nestedKeyTag < countKey)
-			{
-			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapKeyMSK, nestedKeyTag++));
-
-			// parse delay and key
-			if (item == NULL)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Key tag [%d]", nestedKeyTag-1);
-				}
-			else
-				{
-				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
-				if (ret != KErrNone)
-					{
-					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Key tag's data [%d]", nestedKeyTag-1);
-					}
-				else
-					{
-					TRAPD(kAllocErr, startData = ptr.AllocL());
-					if (kAllocErr != KErrNone)
-						{
-						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Key data [%d]", nestedKeyTag-1);
-						}
-					else
-						{
-						tempPtr.Set(startData->Des());
-						switch (dataFrmt)
-							{
-						case EConfigDataFormatMixedBinaryAndAscii:
-							ParseMixedBinaryAsciiDataL(tempPtr);
-							break;
-						//case EConfigDataFormatAscii: // Do nothing
-						//default:
-							}
-						// need to re-copy because converting to binary changes size
-						TRAP(kAllocErr, procInfo.iEapKey = tempPtr.AllocL());
-						if (kAllocErr != KErrNone)
-							{
-							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Key data copy [%d]", nestedKeyTag-1);
-							}
-						delete startData;
-						startData = NULL;
-						}
-					}
-				}
-			}
-		else
-			{
-			LOGPHONE1("ERROR CONFIGURATION FILE PARSING: NO SC EAP KEY INFO TAG");
-			}
-
-		// Get EMSK
-		if (nestedExtKeyTag < countExtKey)
-			{
-			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapKeyEMSK, nestedExtKeyTag++));
-
-			// parse key
-			if (item == NULL)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Ext Key tag [%d]", nestedExtKeyTag-1);
-				}
-			else
-				{
-				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
-				if (ret != KErrNone)
-					{
-					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Ext Key tag's data [%d]", nestedExtKeyTag-1);
-					}
-				else
-					{
-					TRAPD(kAllocErr, startData = ptr.AllocL());
-					if (kAllocErr != KErrNone)
-						{
-						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Ext Key data [%d]", nestedExtKeyTag-1);
-						}
-					else
-						{
-						tempPtr.Set(startData->Des());
-						switch (dataFrmt)
-							{
-						case EConfigDataFormatMixedBinaryAndAscii:
-							ParseMixedBinaryAsciiDataL(tempPtr);
-							break;
-						//case EConfigDataFormatAscii: // Do nothing
-						//default:
-							}
-						// need to re-copy because converting to binary changes size
-						TRAP(kAllocErr, procInfo.iEapExtKey = tempPtr.AllocL());
-						if (kAllocErr != KErrNone)
-							{
-							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Ext Key data copy [%d]", nestedExtKeyTag-1);
-							}
-						delete startData;
-						startData = NULL;
-						}
-					}
-				}
-			}
-		else
-			{
-			LOGPHONE1("ERROR CONFIGURATION FILE PARSING: NO SC EAP EXT KEY INFO TAG");
-			}
-
-		// Get Permanent Identity
-		if (nestedIdTag < countId)
-			{
-			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapIdentity, nestedIdTag++));
-
-			// parse id
-			if (item == NULL)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP id tag [%d]", nestedIdTag-1);
-				}
-			else
-				{
-				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
-				if (ret != KErrNone)
-					{
-					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Id tag's data [%d]", nestedIdTag-1);
-					}
-				else
-					{
-					TRAPD(idAllocErr, startData = ptr.AllocL());
-					if (idAllocErr != KErrNone)
-						{
-						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Id data [%d]", nestedIdTag-1);
-						}
-					else
-						{
-						TPtr8 tempPtr(NULL,0);
-						tempPtr.Set(startData->Des());
-						switch (dataFrmt)
-							{
-						case EConfigDataFormatMixedBinaryAndAscii:
-							ParseMixedBinaryAsciiDataL(tempPtr);
-							break;
-						//case EConfigDataFormatAscii: // Do nothing
-						//default:
-							}
-						// need to re-copy because converting to binary changes size
-						TRAP(idAllocErr, procInfo.iEapId = tempPtr.AllocL());
-						if (idAllocErr != KErrNone)
-							{
-							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Id data copy [%d]", nestedIdTag-1);
-							}
-						delete startData;
-						startData = NULL;
-						}
-					}
-				}
-			}
-		else
-			{
-			LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO SC EAP ID INFO TAG");
-			}
-
-		// Get Pseudonym Identity
-		if (nestedPsIdTag < countPsId)
-			{
-			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapPsIdentity, nestedPsIdTag++));
-
-			// parse id
-			if (item == NULL)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Pseudonym id tag [%d]", nestedPsIdTag-1);
-				}
-			else
-				{
-				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
-				if (ret != KErrNone)
-					{
-					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Pseudonym Id tag's data [%d]", nestedPsIdTag-1);
-					}
-				else
-					{
-					TRAPD(idAllocErr, startData = ptr.AllocL());
-					if (idAllocErr != KErrNone)
-						{
-						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Pseudonym Id data [%d]", nestedPsIdTag-1);
-						}
-					else
-						{
-						TPtr8 tempPtr(NULL,0);
-						tempPtr.Set(startData->Des());
-						switch (dataFrmt)
-							{
-						case EConfigDataFormatMixedBinaryAndAscii:
-							ParseMixedBinaryAsciiDataL(tempPtr);
-							break;
-						//case EConfigDataFormatAscii: // Do nothing
-						//default:
-							}
-						// need to re-copy because converting to binary changes size
-						TRAP(idAllocErr, procInfo.iEapPsId = tempPtr.AllocL());
-						if (idAllocErr != KErrNone)
-							{
-							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Pseudonym Id data copy [%d]", nestedPsIdTag-1);
-							}
-						delete startData;
-						startData = NULL;
-						}
-					}
-				}
-			}
-		else
-			{
-			LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO SC EAP PS ID INFO TAG");
-			}
-
-		// Get challenges
-		// numChallenges is what is parsed from config.txt and will be
-		//    decremented in loop till zero is reached.
-		// nestedChlTag keeps track of the current KScEapChallenge tag
-		//    being read of the total; i.e. not just nested.
-		// countChl is the total number of KScEapChallenge found.
-		while (numChallenges != 0)
-			{
-			if (nestedChlTag >= countChl)
-				{
-				LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO MORE SC EAP Challenge INFO TAG");
-				break;
-				}
-
-			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapChallenge, nestedChlTag++));
-			numChallenges--;
-
-			// parse delay and challenge/response and auth status
-			if (item == NULL)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP challenge tag [%d]", nestedChlTag-1);
-				continue;
-				}
-
-			// Parse challenge
-			ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
-			if (ret != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP challenge data [%d]", nestedChlTag-1);
-				continue;
-				}
-
-			TRAPD(leaveErr, startData = ptr.AllocL());
-			if (leaveErr != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge data [%d]", nestedChlTag-1);
-				continue;
-				}
-			tempPtr.Set(startData->Des());
-			switch (dataFrmt)
-				{
-			case EConfigDataFormatMixedBinaryAndAscii:
-				ParseMixedBinaryAsciiDataL(tempPtr);
-				break;
-			//case EConfigDataFormatAscii: // Do nothing
-			//default:
-				}
-			TEapChngResp newChRespData;
-			TRAP(leaveErr, newChRespData.iChallenge = tempPtr.AllocL());
-			if (leaveErr != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge data copy [%d]", nestedKeyTag-1);
-				}
-			delete startData;
-			startData = NULL;
-
-			// Parse response
-			ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 1, ptr);
-			if (ret != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP response data [%d]", nestedChlTag-1);
-				continue;
-				}
-
-			TRAP(leaveErr, startData = ptr.AllocL());
-			if (leaveErr != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP response data [%d]", nestedChlTag-1);
-				continue;
-				}
-			tempPtr.Set(startData->Des());
-			switch (dataFrmt)
-				{
-			case EConfigDataFormatMixedBinaryAndAscii:
-				ParseMixedBinaryAsciiDataL(tempPtr);
-				break;
-			//case EConfigDataFormatAscii: // Do nothing
-			//default:
-				}
-			TRAP(leaveErr, newChRespData.iResp = tempPtr.AllocL());
-			if (leaveErr != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP response data copy [%d]", nestedKeyTag-1);
-				}
-			delete startData;
-			startData = NULL;
-
-			// Parse status
-			TInt stat;
-			ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 2, stat);
-			if (ret != KErrNone)
-				{
-				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP auth status [%d]", nestedChlTag-1);
-				continue;
-				}
-
-			newChRespData.iAuthStatus = static_cast<RMobileSmartCardEap::TEapAuthStatus>(stat);
-
-			leaveErr = procInfo.iChResp.Append(newChRespData);
-			if (leaveErr != KErrNone)
-				{
-				LOGPHONE3("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge/resp data [%d] [err=%d]", nestedChlTag-1, leaveErr);
-				}
-			} // end while
-
-		TInt errAppend = iEapProcData.Append(procInfo);
-		if (errAppend != KErrNone)
-			{
-			LOGPHONE2("ERROR CONFIGURATION FILE PARSING: Could not store parsed EAP procedure data [err=%d]", errAppend);
-			}
-		else
-			{
-			iDiscardedProcedure.Append(EFalse);
-			}
-		} // end for; parsing EAP procedures from config.txt
-
-	LOGPHONE1("CSimSmartCardEapManager::ParseEapInfoL completed");
-	}
-
-/**
-Function leaves if <aAID,aEapType> is not in config file.
-
-@leave KErrNotFound if <aAID,aEapType> is not found.
-*/
-void CSimSmartCardEapManager::AID_EapType_ExistsInConfigL(const RMobilePhone::TAID& aAID, const RMobileSmartCardEap::TEapType& aEapType)
-	{
-	for (TInt ii = 0; ii < iEapProcData.Count(); ii++)
-		{
-		TEapProcedureData& temp = iEapProcData[ii];
-		if (temp.iAID == aAID)
-			{
-			// two ifs rather than && to help debug
-			if (temp.iEapType == aEapType)
-				{
-				if (!iDiscardedProcedure[ii])
-					{
-					return;
-					}
-				}
-			}
-		}
-	User::Leave(KErrNotFound);
-	}
-
-CTelObject* CSimSmartCardEapManager::CreateScEapSubSessionL(RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType)
-	{
-	LOGPHONE1("CSimSmartCardEapManager::CreateScEapSubSessionL called");
-	// If no config exists for this eapAID,eapType pair, then this will leave
-	AID_EapType_ExistsInConfigL(aAID, aEapType);
-
-	// If exists then phoneScEap guaranteed to get data in
-	// InitialiseEapMethod, since only one object can be created
-	// using the unique <iAID,iEapType> pair.
-
-	CSimSmartCardEap* phoneScEap = NULL;
-	TRAPD(err, phoneScEap = CSimSmartCardEap::NewL(iPhone, this, aAID, aEapType));
-
-	if (err != KErrNone)
-		{
-		LOGPHONE2("ERROR could not create CSimSmartCardEap object [err=%d]", err);
-		User::Leave(err);
-		}
-
-	return phoneScEap;
-	}
-
-/**
-Returns the first procedure data section, as parsed from the
-config.txt, with aAID and aEapType.
-
-@param aAID
-@param aEapType
-@return The first procedure data with aAID and aEapType from the
-        config.txt.  NULL if no such procedure data is found.
-*/
-TEapProcedureData* CSimSmartCardEapManager::ProcData(const RMobilePhone::TAID& aAID, const RMobileSmartCardEap::TEapType& aEapType)
-	{
-	for (TInt ii = 0; ii < iEapProcData.Count(); ii++)
-		{
-		if (iEapProcData[ii].iAID == aAID)
-			{
-			// two ifs rather than && to help debug
-			if (iEapProcData[ii].iEapType == aEapType)
-				{
-				if (!iDiscardedProcedure[ii])
-					{
-					return &iEapProcData[ii];
-					}
-				}
-			}
-		}
-	return NULL;
-	}
-
-void CSimSmartCardEapManager::ProcDataUseCompleted(const TEapProcedureData* aProcData)
-	{
-	if (aProcData == NULL)
-		{
-		return;
-		}
-
-	TInt pos = KErrNotFound;
-
-	for (TInt ii = 0; ii < iEapProcData.Count(); ii++)
-		{
-		if ((&iEapProcData[ii]) == aProcData)
-			{
-			pos = ii;
-			break;
-			}
-		}
-
-	if (pos != KErrNotFound)
-		{
-		iDiscardedProcedure[pos] = ETrue;
-		}
-	}
-
-/**
-Register a sub-session object.  At the present time, list is maintained
-for clean-up only; i.e. this object stores pointers to all EAP sub-
-session objects.
-*/
-void CSimSmartCardEapManager::RegisterSubSessionL(CSimSmartCardEap* aToRegister)
-	{
-	iSubSessionObjs.AppendL(aToRegister);
-	}
-
-/**
-Remove a sub-session object from list of active sub-sessions.
-*/
-TInt CSimSmartCardEapManager::DeRegisterSubSession(const CSimSmartCardEap* aToDeRegister)
-	{
-	TInt index = iSubSessionObjs.Find(aToDeRegister);
-
-	if (index < 0)
-		{
-		return index;
-		}
-
-	iSubSessionObjs.Remove(index);
-	iSubSessionObjs.Compress();
-
-	return KErrNone;
-	}
-
-// CSimSmartCardEap implementation //
-
-CSimSmartCardEap* CSimSmartCardEap::NewL(CSimPhone *aPhone, CSimSmartCardEapManager* aEapMan, RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType)
-	{
-	CSimSmartCardEap* phone = new(ELeave) CSimSmartCardEap(aPhone, aAID, aEapType);
-	CleanupStack::PushL(phone);
-	phone->ConstructL(aEapMan);
-	CleanupStack::Pop();
-	return phone;
-	}
-
-CSimSmartCardEap::CSimSmartCardEap(CSimPhone *aPhone, RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType)
-: iPhone(aPhone), iProcedureData(NULL), iSSInitialised(EFalse),
-  iAccessStatus(RMobileSmartCardEap::EEapMethodAvailable), iAuthStatus(RMobileSmartCardEap::ENoAuthStarted),
-  iCliTerminationListener(NULL), iCurrentChallenge(0)
-	{
-	iAID = aAID;
-	iEapType = aEapType;
-	}
-
-void CSimSmartCardEap::ConstructL(CSimSmartCardEapManager* aEapMan)
-	{
-	LOGPHONE1("CSimSmartCardEap: starting second phase construction");
-
-	iSemaphr.CreateGlobal(KNullDesC, EOwnerThread);
-	aEapMan->RegisterSubSessionL(this);
-	iEapMan = aEapMan;
-
-	LOGPHONE1("CSimSmartCardEap created");
-	}
-
-CSimSmartCardEap::~CSimSmartCardEap()
-	{
-	if (iCliTerminationListener != NULL)
-		{
-		delete iCliTerminationListener;
-		iCliTerminationListener = NULL;
-		}
-	iSemaphr.Close();
-
-	// remove config entry from manager
-	if (iProcedureData != NULL)
-		{
-		iEapMan->ProcDataUseCompleted(iProcedureData);
-		iProcedureData = NULL;
-		}
-
-	TInt err = iEapMan->DeRegisterSubSession(this);
-	LOGPHONE2("CSimSmartCardEap destroyed, deregistering returned %d", err);
-
-	iEapMan = NULL;
-	}
-
-
-void CSimSmartCardEap::Init()
-	{
-	// server calls this function once it has created the sub-session
-	// it gives the TSY chance to do any initialisation it may need to do for
-	// this sub-session
-	}
-
-CTelObject* CSimSmartCardEap::OpenNewObjectByNameL(const TDesC& /*aName*/)
-	{
-	// Server calls this function when a client is opening an object from the phone
-	// for the first time.
-	// Multiple clients opening handles to the same sub-session object will be dealt with
-	// by the server - i.e. by reference counting
-	User::Leave(KErrNotSupported);
-	return NULL;
-	}
-
-CTelObject* CSimSmartCardEap::OpenNewObjectL(TDes& /*aNewName*/)
-	{
-	// all objects opened from the phone are opened by name, hence this method
-	// is not supported
-	User::Leave(KErrNotSupported);
-	return NULL;
-	}
-
-CTelObject::TReqMode CSimSmartCardEap::ReqModeL(const TInt aIpc)
-	{
-	// ReqModeL is called from the server's CTelObject::ReqAnalyserL
-	// in order to check the type of request it has
-
-	// The following are example request types for this dummy TSY
-	// All TSYs do not have to have these request types but they have been given
-	// "sensible" values in this test code
-
-	CTelObject::TReqMode ret = 0;
-
-	switch (aIpc)
-		{
-	// Non flow-controlled requests
-	case EMobileSmartCardEapInitialiseEapMethod:
-	case EMobileSmartCardEapGetUserIdentity:
-	case EMobileSmartCardEapGetAuthenticationStatus:
-	case EMobileSmartCardEapGetEapKey:
-	case EMobileSmartCardEapAuthenticationPhase1:
-	case EMobileSmartCardEapAuthenticationPhase2:
-	case EMobileSmartCardEapReleaseEapMethod:
-	case EMobileSmartCardEapGetEapMethodAccessStatus:
-		break;
-
-	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
-		ret = KReqModeMultipleCompletionEnabled;
-		break;
-
-	default:
-		User::Leave(KErrNotSupported);
-		break;
-		}
-
-	return ret;
-	}
-
-TInt CSimSmartCardEap::RegisterNotification(const TInt /*aIpc*/)
-	{
-	// RegisterNotification is called when the server recognises that this notification
-	// is being posted for the first time on this sub-session object.
-
-	// It enables the TSY to "turn on" any regular notification messages that it may 
-	// receive from the phone
-
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::DeregisterNotification(const TInt /*aIpc*/)
-	{
-	// DeregisterNotification is called when the server recognises that this notification
-	// will not be posted again because the last client to have a handle on this sub-session
-	// object has just closed the handle.
-
-	// It enables the TSY to "turn off" any regular notification messages that it may
-	// receive from the phone
-
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::NumberOfSlotsL(const TInt aIpc)
-	{
-	// NumberOfSlotsL is called by the server when it is registering a new notification
-	// It enables the TSY to tell the server how many buffer slots to allocate for
-	// "repost immediately" notifications that may trigger before clients collect them
-
-	TInt numberOfSlots = 1;
-
-	switch (aIpc)
-		{
-	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
-		numberOfSlots = 3;
-		break;
-
-	default:
-		// Unknown or invalid Phone IPC
-		User::Leave(KErrNotSupported);
-		break;
-		}
-
-	return numberOfSlots;
-	}
-
-TInt CSimSmartCardEap::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,
-                               const TDataPackage& aPackage)
-	{
-	// ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request 
-	// for the TSY to process
-	// A request handle, request type and request data are passed to the TSY
-
-	TAny* dataPtr = aPackage.Ptr1();
-	TAny* dataPtr2 = aPackage.Ptr2();
-
-	// The request data has to extracted from TDataPackage and the TAny* pointers have to
-	// be "cast" to the expected request data type
-
-	switch(aIpc)
-		{
-	// Non-Flow controlled requests
-
-	case EMobileSmartCardEapInitialiseEapMethod:
-		return SimInitialiseEapMethod(aTsyReqHandle,
-		         reinterpret_cast<TThreadId*>(dataPtr));
-
-	case EMobileSmartCardEapGetUserIdentity:
-		return SimGetUserIdentity(aTsyReqHandle,
-		         reinterpret_cast<RMobileSmartCardEap::TEapUserIdType*>(dataPtr),
-		         aPackage.Des2n());
-
-	case EMobileSmartCardEapGetAuthenticationStatus:
-		return SimGetAuthenticationStatus(aTsyReqHandle, 
-		         reinterpret_cast<RMobileSmartCardEap::TEapAuthStatus*>(dataPtr));
-
-	case EMobileSmartCardEapGetEapKey:
-		return SimGetEapKey(aTsyReqHandle,
-		         reinterpret_cast<RMobileSmartCardEap::TEapKeyTag*>(dataPtr),
-		         aPackage.Des2n());
-
-	case EMobileSmartCardEapAuthenticationPhase1:
-		return SimSetAuthenticateDataForPhase1(aTsyReqHandle,
-		         aPackage.Des1n(), reinterpret_cast<TInt*>(dataPtr2));
-
-	case EMobileSmartCardEapAuthenticationPhase2:
-		return SimGetAuthenticateDataForPhase2(aTsyReqHandle,
-		         aPackage.Des1n(), aPackage.Des2n());
-
-	case EMobileSmartCardEapReleaseEapMethod:
-		return SimReleaseEapMethod(aTsyReqHandle);
-
-	case EMobileSmartCardEapGetEapMethodAccessStatus:
-		return SimGetEapMethodAccessStatus(aTsyReqHandle,
-		         reinterpret_cast<RMobileSmartCardEap::TEapMethodAccessStatus*>(dataPtr));
-
-	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
-		return SimNotifyEapMethodAccessStatusChange(aTsyReqHandle,
-		         reinterpret_cast<RMobileSmartCardEap::TEapMethodAccessStatus*>(dataPtr));
-
-	default:
-		return KErrNotSupported;
-		}
-	}
-
-TInt CSimSmartCardEap::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
-	{
-	// CancelService is called by the server when it is "cleaning-up" any still outstanding
-	// asynchronous requests before closing a client's sub-session.
-	// This will happen if a client closes its R-class handle without cancelling outstanding
-	// asynchronous requests.
-
-	switch (aIpc)
-		{
-	case EMobileSmartCardEapGetUserIdentity:
-		return SimGetUserIdentityCancel(aTsyReqHandle);
-	case EMobileSmartCardEapGetAuthenticationStatus:
-		return SimGetAuthenticationStatusCancel(aTsyReqHandle);
-	case EMobileSmartCardEapGetEapKey:
-		return SimGetEapKeyCancel(aTsyReqHandle);
-	case EMobileSmartCardEapInitialiseEapMethod:
-		return SimInitialiseEapMethodCancel(aTsyReqHandle);
-	case EMobileSmartCardEapAuthenticationPhase1:
-	case EMobileSmartCardEapAuthenticationPhase2:
-		return SimSmartCardEapAuthenticationCancel(aTsyReqHandle);
-	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
-		return SimNotifyEapMethodAccessStatusChangeCancel(aTsyReqHandle);
-	default:
-		return KErrNotSupported;
-		}
-	}
-
-RHandleBase* CSimSmartCardEap::GlobalKernelObjectHandle()
-	{
-	return &iSemaphr;
-	}
-
-TInt CSimSmartCardEap::SimInitialiseEapMethod(const TTsyReqHandle aTsyReqHandle, TThreadId* aThreadId)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimInitialiseEapMethod called");
-	// This can only be called through RMobileSmartCardEap for one instance
-
-	if (iSSInitialised)
-		{
-		// re-initialise request sent, so will be treated as a mistake
-		// and nothing will happen!
-		ReqCompleted(aTsyReqHandle, KErrNone);
-		}
-	else
-		{
-		delete iCliTerminationListener;
-		TRAPD(err, iCliTerminationListener = CThreadTerminationListener::NewL(this, *aThreadId));
-		if (err != KErrNone)
-			{
-			LOGPHONE2("ERROR could not create a client termination listener [err=%d] (not initialised)", err);
-			ReqCompleted(aTsyReqHandle, err);
-			}
-		else
-			{
-			iProcedureData = iEapMan->ProcData(iAID, iEapType);
-			if (iProcedureData == NULL)
-				{
-				LOGPHONE1("ERROR could not find sub-session's procedure");
-				ReqCompleted(aTsyReqHandle, KErrNotFound);
-				return KErrNone;
-				}
-
-			iSSInitialised = ETrue;
-			iCliTerminationListener->Start();
-			iAccessStatus = RMobileSmartCardEap::EEapMethodInUseApplicationActive;
-			SimCompleteNotifyEapMethodAccessStatusChange();
-			ReqCompleted(aTsyReqHandle, KErrNone);
-			}
-		}
-
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimInitialiseEapMethodCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimInitialiseEapMethodCancel called");
-	iProcedureData = NULL;
-	iSSInitialised = EFalse;
-	iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
-	SimCompleteNotifyEapMethodAccessStatusChange();
-	ReqCompleted(aTsyReqHandle, KErrCancel);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimGetUserIdentity(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapUserIdType* aEapIdType, TDes8* aUserId)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetUserIdentity called");
-
-	RMobileSmartCardEap::TEapUserIdentityV6Pckg *userIdPckg = reinterpret_cast<RMobileSmartCardEap::TEapUserIdentityV6Pckg*>(aUserId);
-	RMobileSmartCardEap::TEapUserIdentityV6 &userId = (*userIdPckg)();
-	
-	// Check that the data structure is supported by the simulated TSY version
-	TInt err = iPhone->CheckSimTsyVersion(userId);
-		if(err != KErrNone)
-			{
-			iPhone->ReqCompleted(aTsyReqHandle, err);
-			return KErrNone;
-			}
-
-	if (*aEapIdType == RMobileSmartCardEap::EPermanentIdentity)
-		{
-		if (iProcedureData->iEapId == NULL)
-			{
-			ReqCompleted(aTsyReqHandle, KErrNotFound);
-			LOGPHONE1("ERROR EAP sub-session does not contain EPermanentIdentity");
-			return KErrNone;
-			}
-
-		userId.iEapId = iProcedureData->iEapId->Des();
-		}
-	else if (*aEapIdType == RMobileSmartCardEap::EPseudonymIdentity)
-		{
-		if (iProcedureData->iEapPsId == NULL)
-			{
-			ReqCompleted(aTsyReqHandle, KErrNotFound);
-			LOGPHONE1("ERROR EAP sub-session does not contain EPseudonymIdentity");
-			return KErrNone;
-			}
-
-		userId.iEapId = iProcedureData->iEapPsId->Des();
-		}
-	else
-		{
-		ReqCompleted(aTsyReqHandle, KErrArgument);
-		LOGPHONE2("ERROR invalid EAP id type requested [tag=%d]", *aEapIdType);
-		return KErrNone;
-		}
-
-	ReqCompleted(aTsyReqHandle, KErrNone);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimGetUserIdentityCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetUserIdentityCancel called");
-	ReqCompleted(aTsyReqHandle, KErrCancel);
-	return KErrNone;
-	}
-	
-TInt CSimSmartCardEap::SimGetAuthenticationStatus(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapAuthStatus* aAuthStatus)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetAuthenticationStatus called");
-
-	(*aAuthStatus) = iAuthStatus;
-
-	ReqCompleted(aTsyReqHandle, KErrNone);
-	return KErrNone;
-	}
-	
-TInt CSimSmartCardEap::SimGetAuthenticationStatusCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetAuthenticationStatusCancel called");
-	ReqCompleted(aTsyReqHandle, KErrCancel);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimGetEapKey(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapKeyTag* aEapKeyTag, TDes8* aKey)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetEapKey called");
-
-	RMobileSmartCardEap::TEapKeyV6Pckg *keyPckg = reinterpret_cast<RMobileSmartCardEap::TEapKeyV6Pckg*>(aKey);
-	RMobileSmartCardEap::TEapKeyV6 &key = (*keyPckg)();
-
-	// Check that the data structure is supported by the simulated TSY version
-	TInt err = iPhone->CheckSimTsyVersion(key);
-		if(err != KErrNone)
-			{
-			iPhone->ReqCompleted(aTsyReqHandle, err);
-			return KErrNone;
-			}
-
-	if (*aEapKeyTag == RMobileSmartCardEap::EEapKeyMSK)
-		{
-		if (iProcedureData->iEapKey == NULL)
-			{
-			ReqCompleted(aTsyReqHandle, KErrNotFound);
-			LOGPHONE1("ERROR EAP sub-session does not contain EEapKeyMSK");
-			return KErrNone;
-			}
-
-		key.iEapKey = iProcedureData->iEapKey->Des();
-		}
-	else if (*aEapKeyTag == RMobileSmartCardEap::EEapKeyEMSK)
-		{
-		if (iProcedureData->iEapExtKey == NULL)
-			{
-			ReqCompleted(aTsyReqHandle, KErrNotFound);
-			LOGPHONE1("ERROR EAP sub-session does not contain EEapKeyEMSK");
-			return KErrNone;
-			}
-
-		key.iEapKey = iProcedureData->iEapExtKey->Des();
-		}
-	else
-		{
-		ReqCompleted(aTsyReqHandle, KErrArgument);
-		LOGPHONE2("ERROR invalid EAP key tag requested [tag=%d]", *aEapKeyTag);
-		return KErrNone;
-		}
-
-	ReqCompleted(aTsyReqHandle, KErrNone);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimGetEapKeyCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetEapKeyCancel called");
-	ReqCompleted(aTsyReqHandle, KErrCancel);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimSetAuthenticateDataForPhase1(const TTsyReqHandle aTsyReqHandle, TDes8* aEapAuthData, TInt* aPhase1Size)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimSetAuthenticateDataForPhase1 called");
-
-	if (iCurrentChallenge >= iProcedureData->iChResp.Count())
-		{
-		ReqCompleted(aTsyReqHandle, KErrAccessDenied);
-		return KErrNone;
-		}
-
-	RMobileSmartCardEap::CEapAuthenticateRequestDataV6* authReq = NULL;
-	TRAPD(err, authReq = RMobileSmartCardEap::CEapAuthenticateRequestDataV6::NewL());
-	if (err != KErrNone)
-		{
-		LOGPHONE2("ERR Could not allocate memory for challenge request object [err=%d]", err);
-		ReqCompleted(aTsyReqHandle, err);
-		return KErrNone;
-		}
-
-	TRAP(err, authReq->InternalizeL(*aEapAuthData));
-	if (err != KErrNone)
-		{
-		LOGPHONE2("ERR Could not allocate memory for challenge request [err=%d]", err);
-		ReqCompleted(aTsyReqHandle, err);
-		return KErrNone;
-		}
-
-	TPtr8 reqPacket = authReq->GetEapReqPacket();
-
-	TPtr8 tempPtr(NULL, 0);
-	tempPtr.Set(iProcedureData->iChResp[iCurrentChallenge].iChallenge->Des());
-
-	if (reqPacket != tempPtr)
-		{
-		LOGPHONE2("ERR challenge request does not match config [currentChallenge=%d]", iCurrentChallenge);
-		ReqCompleted(aTsyReqHandle, KErrCorrupt);
-		return KErrNone;
-		}
-
-	(*aPhase1Size) = iProcedureData->iChResp[iCurrentChallenge].iResp->Length();
-
-	ReqCompleted(aTsyReqHandle, KErrNone);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimGetAuthenticateDataForPhase2(const TTsyReqHandle aTsyReqHandle, TDes8* /*aEapAuthData*/, TDes8* aPhase2Resp)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimSetAuthenticateDataForPhase2 called");
-
-	if (iCurrentChallenge >= iProcedureData->iChResp.Count())
-		{
-		ReqCompleted(aTsyReqHandle, KErrAccessDenied);
-		return KErrNone;
-		}
-
-	TPtr8 tempPtr(NULL, 0);
-	tempPtr.Set(iProcedureData->iChResp[iCurrentChallenge].iResp->Des());
-
-	aPhase2Resp->Copy(tempPtr);
- 	iAuthStatus = iProcedureData->iChResp[iCurrentChallenge].iAuthStatus;
- 	iCurrentChallenge++;
-
-	ReqCompleted(aTsyReqHandle, KErrNone);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimSmartCardEapAuthenticationCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimSmartCardEapAuthenticationCancel called");
-	ReqCompleted(aTsyReqHandle, KErrCancel);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimReleaseEapMethod(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimReleaseEapMethod called");
-	iSSInitialised = EFalse;
-	iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
-	ReqCompleted(aTsyReqHandle, KErrNone);
-
-	SimCompleteNotifyEapMethodAccessStatusChange();
-
-	// remove config entry from manager
-	iEapMan->ProcDataUseCompleted(iProcedureData);
-	iProcedureData = NULL;
-
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimGetEapMethodAccessStatus(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapMethodAccessStatus* aEapState)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimGetEapMethodAccessStatus called");
-	*aEapState = iAccessStatus;
-	ReqCompleted(aTsyReqHandle, KErrNone);
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimNotifyEapMethodAccessStatusChange(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapMethodAccessStatus* aEapState)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimNotifyEapMethodAccessStatusChange called");
-	__ASSERT_ALWAYS(!iEapAccessNotifyData.iNotifyPending, PanicClient(EEtelPanicRequestAsyncTwice));
-
-	iEapAccessNotifyData.iNotifyPending = ETrue;
-	iEapAccessNotifyData.iNotifyHandle = aTsyReqHandle;
-	iEapAccessNotifyData.iNotifyData = aEapState;
-
-	return KErrNone;
-	}
-
-TInt CSimSmartCardEap::SimNotifyEapMethodAccessStatusChangeCancel(const TTsyReqHandle aTsyReqHandle)
-	{
-	LOGPHONE1("CSimSmartCardEap::SimNotifyEapMethodAccessStatusChangeCancel called");
-	if(iEapAccessNotifyData.iNotifyPending)
-		{
-		iEapAccessNotifyData.iNotifyPending = EFalse;
-		ReqCompleted(aTsyReqHandle, KErrCancel);
-		return KErrNone;
-		}	
-
-//	iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
-	return KErrNone;
-	}
-
-void CSimSmartCardEap::SimCompleteNotifyEapMethodAccessStatusChange()
-	{
-	LOGPHONE1("CSimSmartCardEap::SimCompleteNotifyEapMethodAccessStatusChange called");
-
-	if(iEapAccessNotifyData.iNotifyPending)
-		{
-		iEapAccessNotifyData.iNotifyPending = EFalse;
-		*(reinterpret_cast<RMobileSmartCardEap::TEapMethodAccessStatus*>(iEapAccessNotifyData.iNotifyData)) = iAccessStatus;
-		ReqCompleted(iEapAccessNotifyData.iNotifyHandle, KErrNone);
-		}
-	}
-
-void CSimSmartCardEap::ClientHasTerminated(TInt /*aExitReason*/)
-	{
-	// Can TSY do anything with the thread's exit reason?
-	// Exit code can be a zero (e.g. for KERN-EXEC 0) a positive value
-	// (e.g. for KERN-EXEC 3) or a negative error.
-
-	switch (iAccessStatus)
-		{
-	case RMobileSmartCardEap::EEapMethodInUseApplicationActive:
-		iSSInitialised = EFalse;
-		iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
-		SimCompleteNotifyEapMethodAccessStatusChange();
-		iSemaphr.Signal();
-
-		// remove config entry from manager
-		iEapMan->ProcDataUseCompleted(iProcedureData);
-		iProcedureData = NULL;
-
-		break;
-
-	case RMobileSmartCardEap::EEapMethodInUseApplicationInactive:
-		iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
-		SimCompleteNotifyEapMethodAccessStatusChange();
-		iSemaphr.Signal();
-		break;
-
-	default:
-		;
-		}
-	}
-
-//
-// Class definition for monitoring thread termination
-//
-
-CSimSmartCardEap::CThreadTerminationListener* CSimSmartCardEap::CThreadTerminationListener::NewL(CSimSmartCardEap* aSubSess, const TThreadId& aId)
-	{
-	CThreadTerminationListener* self = new(ELeave) CThreadTerminationListener(aSubSess);
-	CleanupStack::PushL(self);
-	self->ConstructL(aId);
-	CleanupStack::Pop(self);
-	return self;
-	}
-
-CSimSmartCardEap::CThreadTerminationListener::CThreadTerminationListener(CSimSmartCardEap* aSubSess)
-: CActive(EPriorityStandard), iSubSess(aSubSess)
-	{
-	}
-
-void CSimSmartCardEap::CThreadTerminationListener::ConstructL(const TThreadId& aId)
-	{
-	TInt openTh = iCliThread.Open(aId);
-	User::LeaveIfError(openTh);
-    CActiveScheduler::Add(this);
-	}
-
-void CSimSmartCardEap::CThreadTerminationListener::Start()
-	{
-	iCliThread.Logon(iStatus);
-	SetActive();
-	}
-
-void CSimSmartCardEap::CThreadTerminationListener::RunL()
-	{
-	iSubSess->ClientHasTerminated(iStatus.Int());
-	}
-
-void CSimSmartCardEap::CThreadTerminationListener::DoCancel()
-	{
-	iCliThread.LogonCancel(iStatus);
-	}
-
-CSimSmartCardEap::CThreadTerminationListener::~CThreadTerminationListener()
-	{
-	Cancel();
-	iCliThread.Close();
-	}
+// Copyright (c) 2006-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:
+// Defines the CSimSmartCardEap class componenet
+// 
+//
+
+/**
+ @file
+*/
+
+#include <testconfigfileparser.h>
+#include "csimsmartcardeap.h"
+#include "Simlog.h"
+#include "etelext.h"
+
+// CSimSmartCardEapManager implementation; related to CSimSmartCardEap //
+
+/**
+Default constructor to initialise Ptrs.
+*/
+TEapChngResp::TEapChngResp()
+: iChallenge(NULL), iResp(NULL),
+  iAuthStatus(RMobileSmartCardEap::ENoAuthStarted)
+	{
+	}
+
+/**
+Default constructor to initialise Ptrs.
+*/
+TEapProcedureData::TEapProcedureData()
+: iEapKey(NULL), iEapExtKey(NULL), iEapId(NULL), iEapPsId(NULL)
+	{
+	}
+
+/**
+Factory constructor.
+*/
+CSimSmartCardEapManager* CSimSmartCardEapManager::NewL(CSimPhone *aPhone)
+	{
+	CSimSmartCardEapManager* phone = new(ELeave) CSimSmartCardEapManager(aPhone);
+	CleanupStack::PushL(phone);
+	phone->ConstructL();
+	CleanupStack::Pop();
+	return phone;
+	}
+
+/**
+Default constructor, initialises a pointer to the owner phone object.
+*/
+CSimSmartCardEapManager::CSimSmartCardEapManager(CSimPhone *aPhone)
+: iPhone(aPhone)
+	{
+	}
+
+/**
+Second-phase constructor.
+*/
+void CSimSmartCardEapManager::ConstructL()
+	{
+	LOGPHONE1("CSimSmartCardEapManager second phase construction created");
+
+	ParseEapInfoL();
+
+	LOGPHONE1("CSimSmartCardEapManager second phase construction completed");
+	}
+
+/**
+If this is destroyed then so should all EAP sub-session objects.
+*/
+CSimSmartCardEapManager::~CSimSmartCardEapManager()
+	{
+	LOGPHONE1("CSimSmartCardEapManager destructing");
+
+	for (TInt jj = iSubSessionObjs.Count()-1; jj >= 0; jj--)
+		{
+		delete iSubSessionObjs[jj];
+		}
+
+	iSubSessionObjs.Close();
+
+	ClearParsedData();
+
+	LOGPHONE1("CSimSmartCardEapManager destructed");
+	}
+
+void CSimSmartCardEapManager::ClearParsedData()
+	{
+	// Cleanup remaining unused parsed EAP procedure data
+	for (TInt jjj = 0; jjj < iEapProcData.Count(); jjj++)
+		{
+		for (TInt aa = 0; aa < iEapProcData[jjj].iChResp.Count(); aa++)
+			{
+			TEapChngResp& temp = iEapProcData[jjj].iChResp[aa];
+			delete (temp.iChallenge);
+			delete (temp.iResp);
+			temp.iChallenge = NULL;
+			temp.iResp = NULL;
+			}
+		iEapProcData[jjj].iChResp.Close();
+
+		delete iEapProcData[jjj].iEapKey;
+		delete iEapProcData[jjj].iEapExtKey;
+		delete iEapProcData[jjj].iEapId;
+		delete iEapProcData[jjj].iEapPsId;
+		iEapProcData[jjj].iEapKey = NULL;
+		iEapProcData[jjj].iEapExtKey = NULL;
+		iEapProcData[jjj].iEapId = NULL;
+		iEapProcData[jjj].iEapPsId = NULL;
+		}
+
+	iEapProcData.Close();
+	iDiscardedProcedure.Close();
+	}
+
+/**
+Returns a pointer to the selected config.txt file section.
+*/
+const CTestConfigSection* CSimSmartCardEapManager::CfgFile()
+	{
+	return iPhone->CfgFile();
+	}
+
+/**
+Parses the UICC App EAP specific settings from the config.txt.
+*/
+void CSimSmartCardEapManager::ParseEapInfoL()
+	{
+	LOGPHONE1("CSimSmartCardEapManager::ParseEapInfoL called");
+
+	CTestConfigItem* item = NULL;
+
+	LOGPHONE1("Starting to Parse Smart Card EAP Info");
+	TInt count = CfgFile()->ItemCount(KScEapProcedures);
+
+	// Used in parsing to keep track of the nested items
+	TInt nestedKeyTag = 0;
+	TInt nestedExtKeyTag = 0;
+	TInt nestedIdTag = 0;
+	TInt nestedPsIdTag = 0;
+	TInt nestedChlTag = 0;
+
+	// Counts of the total number of tags (considered as nested tags)
+	TInt countKey = CfgFile()->ItemCount(KScEapKeyMSK);
+	TInt countExtKey = CfgFile()->ItemCount(KScEapKeyEMSK);
+	TInt countId = CfgFile()->ItemCount(KScEapIdentity);
+	TInt countPsId = CfgFile()->ItemCount(KScEapPsIdentity);
+	TInt countChl = CfgFile()->ItemCount(KScEapChallenge);
+
+
+	for (TInt index = 0; index < count; index++)
+		{
+		item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapProcedures, index));
+		if(item == NULL)
+			{
+			LOGPHONE2("WARNING CONFIGURATION FILE PARSING: SC EAP PROC INFO tag not read [%d]", index);
+			continue;
+			}
+
+		TInt dataFrmt = 0;
+		TInt numChallenges = 0;
+		TInt ret = KErrNone;
+		TPtrC8 appId, eapType;
+
+		// To be populated and appended to iEapProcData later
+		TEapProcedureData procInfo;
+
+		// Get AID; convert to bin if required
+		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, appId);
+		if(ret != KErrNone)
+			{
+			LOGPARSERR("appId", ret,0,&KScEapProcedures);
+			continue;
+			}
+		else
+			{
+			procInfo.iAID = appId;
+
+			// AID is always in binary format (because of the RMobileSmartCardEap::Open construction)
+			ParseMixedBinaryAsciiDataL(procInfo.iAID);
+			}
+
+		// Get eap type
+		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 1, eapType);
+		if(ret != KErrNone)
+			{
+			LOGPARSERR("eapType", ret,1,&KScEapProcedures);
+			continue;
+			}
+		else
+			{
+			// EAP type is always in ASCII
+			procInfo.iEapType = eapType;
+			}
+
+		// Find number of challenges
+		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 2, numChallenges);
+		if(ret != KErrNone)
+			{
+			LOGPARSERR("numChallenges", ret,2,&KScEapProcedures);
+			continue;
+			}
+		else if (numChallenges > (countChl - nestedChlTag))
+			{
+			LOGPHONE2("ERROR CONFIGURATION FILE PARSING: error SC EAP PROC INFO specifies more challenges than available [%d]", index);
+			continue;
+			}
+		else if (numChallenges < 0)
+			{
+			LOGPHONE2("ERROR CONFIGURATION FILE PARSING: error SC EAP PROC INFO specifies -ve challenge number [%d]", index);
+			continue;
+			}
+
+		// Get optional data format; this format is used for all data of this parsed procedure
+		ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 3, dataFrmt);
+		if(ret != KErrNone)
+			{
+			LOGPHONE2("CONFIGURATION FILE PARSING: SC EAP PROC INFO tag with no data format [%d]", index);
+			}
+		else if (dataFrmt >= EMaxConfigDataFormat)
+			{
+			LOGPHONE2("WARNING IN CONFIGURATION FILE PARSING - error wrong data format value SC EAP PROC INFO tag [%d] (ASCII format will be used)", index);
+			dataFrmt = EConfigDataFormatAscii;
+			}
+
+		TPtrC8 ptr;
+		TPtr8 tempPtr(NULL,0);
+		HBufC8* startData = NULL;
+
+		// Get MSK
+		if (nestedKeyTag < countKey)
+			{
+			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapKeyMSK, nestedKeyTag++));
+
+			// parse delay and key
+			if (item == NULL)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Key tag [%d]", nestedKeyTag-1);
+				}
+			else
+				{
+				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
+				if (ret != KErrNone)
+					{
+					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Key tag's data [%d]", nestedKeyTag-1);
+					}
+				else
+					{
+					TRAPD(kAllocErr, startData = ptr.AllocL());
+					if (kAllocErr != KErrNone)
+						{
+						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Key data [%d]", nestedKeyTag-1);
+						}
+					else
+						{
+						tempPtr.Set(startData->Des());
+						switch (dataFrmt)
+							{
+						case EConfigDataFormatMixedBinaryAndAscii:
+							ParseMixedBinaryAsciiDataL(tempPtr);
+							break;
+						//case EConfigDataFormatAscii: // Do nothing
+						//default:
+							}
+						// need to re-copy because converting to binary changes size
+						TRAP(kAllocErr, procInfo.iEapKey = tempPtr.AllocL());
+						if (kAllocErr != KErrNone)
+							{
+							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Key data copy [%d]", nestedKeyTag-1);
+							}
+						delete startData;
+						startData = NULL;
+						}
+					}
+				}
+			}
+		else
+			{
+			LOGPHONE1("ERROR CONFIGURATION FILE PARSING: NO SC EAP KEY INFO TAG");
+			}
+
+		// Get EMSK
+		if (nestedExtKeyTag < countExtKey)
+			{
+			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapKeyEMSK, nestedExtKeyTag++));
+
+			// parse key
+			if (item == NULL)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Ext Key tag [%d]", nestedExtKeyTag-1);
+				}
+			else
+				{
+				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
+				if (ret != KErrNone)
+					{
+					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Ext Key tag's data [%d]", nestedExtKeyTag-1);
+					}
+				else
+					{
+					TRAPD(kAllocErr, startData = ptr.AllocL());
+					if (kAllocErr != KErrNone)
+						{
+						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Ext Key data [%d]", nestedExtKeyTag-1);
+						}
+					else
+						{
+						tempPtr.Set(startData->Des());
+						switch (dataFrmt)
+							{
+						case EConfigDataFormatMixedBinaryAndAscii:
+							ParseMixedBinaryAsciiDataL(tempPtr);
+							break;
+						//case EConfigDataFormatAscii: // Do nothing
+						//default:
+							}
+						// need to re-copy because converting to binary changes size
+						TRAP(kAllocErr, procInfo.iEapExtKey = tempPtr.AllocL());
+						if (kAllocErr != KErrNone)
+							{
+							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Ext Key data copy [%d]", nestedExtKeyTag-1);
+							}
+						delete startData;
+						startData = NULL;
+						}
+					}
+				}
+			}
+		else
+			{
+			LOGPHONE1("ERROR CONFIGURATION FILE PARSING: NO SC EAP EXT KEY INFO TAG");
+			}
+
+		// Get Permanent Identity
+		if (nestedIdTag < countId)
+			{
+			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapIdentity, nestedIdTag++));
+
+			// parse id
+			if (item == NULL)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP id tag [%d]", nestedIdTag-1);
+				}
+			else
+				{
+				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
+				if (ret != KErrNone)
+					{
+					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Id tag's data [%d]", nestedIdTag-1);
+					}
+				else
+					{
+					TRAPD(idAllocErr, startData = ptr.AllocL());
+					if (idAllocErr != KErrNone)
+						{
+						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Id data [%d]", nestedIdTag-1);
+						}
+					else
+						{
+						TPtr8 tempPtr(NULL,0);
+						tempPtr.Set(startData->Des());
+						switch (dataFrmt)
+							{
+						case EConfigDataFormatMixedBinaryAndAscii:
+							ParseMixedBinaryAsciiDataL(tempPtr);
+							break;
+						//case EConfigDataFormatAscii: // Do nothing
+						//default:
+							}
+						// need to re-copy because converting to binary changes size
+						TRAP(idAllocErr, procInfo.iEapId = tempPtr.AllocL());
+						if (idAllocErr != KErrNone)
+							{
+							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Id data copy [%d]", nestedIdTag-1);
+							}
+						delete startData;
+						startData = NULL;
+						}
+					}
+				}
+			}
+		else
+			{
+			LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO SC EAP ID INFO TAG");
+			}
+
+		// Get Pseudonym Identity
+		if (nestedPsIdTag < countPsId)
+			{
+			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapPsIdentity, nestedPsIdTag++));
+
+			// parse id
+			if (item == NULL)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Pseudonym id tag [%d]", nestedPsIdTag-1);
+				}
+			else
+				{
+				ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
+				if (ret != KErrNone)
+					{
+					LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Pseudonym Id tag's data [%d]", nestedPsIdTag-1);
+					}
+				else
+					{
+					TRAPD(idAllocErr, startData = ptr.AllocL());
+					if (idAllocErr != KErrNone)
+						{
+						LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Pseudonym Id data [%d]", nestedPsIdTag-1);
+						}
+					else
+						{
+						TPtr8 tempPtr(NULL,0);
+						tempPtr.Set(startData->Des());
+						switch (dataFrmt)
+							{
+						case EConfigDataFormatMixedBinaryAndAscii:
+							ParseMixedBinaryAsciiDataL(tempPtr);
+							break;
+						//case EConfigDataFormatAscii: // Do nothing
+						//default:
+							}
+						// need to re-copy because converting to binary changes size
+						TRAP(idAllocErr, procInfo.iEapPsId = tempPtr.AllocL());
+						if (idAllocErr != KErrNone)
+							{
+							LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Pseudonym Id data copy [%d]", nestedPsIdTag-1);
+							}
+						delete startData;
+						startData = NULL;
+						}
+					}
+				}
+			}
+		else
+			{
+			LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO SC EAP PS ID INFO TAG");
+			}
+
+		// Get challenges
+		// numChallenges is what is parsed from config.txt and will be
+		//    decremented in loop till zero is reached.
+		// nestedChlTag keeps track of the current KScEapChallenge tag
+		//    being read of the total; i.e. not just nested.
+		// countChl is the total number of KScEapChallenge found.
+		while (numChallenges != 0)
+			{
+			if (nestedChlTag >= countChl)
+				{
+				LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO MORE SC EAP Challenge INFO TAG");
+				break;
+				}
+
+			item = const_cast<CTestConfigItem*>(CfgFile()->Item(KScEapChallenge, nestedChlTag++));
+			numChallenges--;
+
+			// parse delay and challenge/response and auth status
+			if (item == NULL)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP challenge tag [%d]", nestedChlTag-1);
+				continue;
+				}
+
+			// Parse challenge
+			ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr);
+			if (ret != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP challenge data [%d]", nestedChlTag-1);
+				continue;
+				}
+
+			TRAPD(leaveErr, startData = ptr.AllocL());
+			if (leaveErr != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge data [%d]", nestedChlTag-1);
+				continue;
+				}
+			tempPtr.Set(startData->Des());
+			switch (dataFrmt)
+				{
+			case EConfigDataFormatMixedBinaryAndAscii:
+				ParseMixedBinaryAsciiDataL(tempPtr);
+				break;
+			//case EConfigDataFormatAscii: // Do nothing
+			//default:
+				}
+			TEapChngResp newChRespData;
+			TRAP(leaveErr, newChRespData.iChallenge = tempPtr.AllocL());
+			if (leaveErr != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge data copy [%d]", nestedKeyTag-1);
+				}
+			delete startData;
+			startData = NULL;
+
+			// Parse response
+			ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 1, ptr);
+			if (ret != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP response data [%d]", nestedChlTag-1);
+				continue;
+				}
+
+			TRAP(leaveErr, startData = ptr.AllocL());
+			if (leaveErr != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP response data [%d]", nestedChlTag-1);
+				continue;
+				}
+			tempPtr.Set(startData->Des());
+			switch (dataFrmt)
+				{
+			case EConfigDataFormatMixedBinaryAndAscii:
+				ParseMixedBinaryAsciiDataL(tempPtr);
+				break;
+			//case EConfigDataFormatAscii: // Do nothing
+			//default:
+				}
+			TRAP(leaveErr, newChRespData.iResp = tempPtr.AllocL());
+			if (leaveErr != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP response data copy [%d]", nestedKeyTag-1);
+				}
+			delete startData;
+			startData = NULL;
+
+			// Parse status
+			TInt stat;
+			ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 2, stat);
+			if (ret != KErrNone)
+				{
+				LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP auth status [%d]", nestedChlTag-1);
+				continue;
+				}
+
+			newChRespData.iAuthStatus = static_cast<RMobileSmartCardEap::TEapAuthStatus>(stat);
+
+			leaveErr = procInfo.iChResp.Append(newChRespData);
+			if (leaveErr != KErrNone)
+				{
+				LOGPHONE3("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge/resp data [%d] [err=%d]", nestedChlTag-1, leaveErr);
+				}
+			} // end while
+
+		TInt errAppend = iEapProcData.Append(procInfo);
+		if (errAppend != KErrNone)
+			{
+			LOGPHONE2("ERROR CONFIGURATION FILE PARSING: Could not store parsed EAP procedure data [err=%d]", errAppend);
+			}
+		else
+			{
+			iDiscardedProcedure.Append(EFalse);
+			}
+		} // end for; parsing EAP procedures from config.txt
+
+	LOGPHONE1("CSimSmartCardEapManager::ParseEapInfoL completed");
+	}
+
+/**
+Function leaves if <aAID,aEapType> is not in config file.
+
+@leave KErrNotFound if <aAID,aEapType> is not found.
+*/
+void CSimSmartCardEapManager::AID_EapType_ExistsInConfigL(const RMobilePhone::TAID& aAID, const RMobileSmartCardEap::TEapType& aEapType)
+	{
+	for (TInt ii = 0; ii < iEapProcData.Count(); ii++)
+		{
+		TEapProcedureData& temp = iEapProcData[ii];
+		if (temp.iAID == aAID)
+			{
+			// two ifs rather than && to help debug
+			if (temp.iEapType == aEapType)
+				{
+				if (!iDiscardedProcedure[ii])
+					{
+					return;
+					}
+				}
+			}
+		}
+	User::Leave(KErrNotFound);
+	}
+
+CTelObject* CSimSmartCardEapManager::CreateScEapSubSessionL(RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType)
+	{
+	LOGPHONE1("CSimSmartCardEapManager::CreateScEapSubSessionL called");
+	// If no config exists for this eapAID,eapType pair, then this will leave
+	AID_EapType_ExistsInConfigL(aAID, aEapType);
+
+	// If exists then phoneScEap guaranteed to get data in
+	// InitialiseEapMethod, since only one object can be created
+	// using the unique <iAID,iEapType> pair.
+
+	CSimSmartCardEap* phoneScEap = NULL;
+	TRAPD(err, phoneScEap = CSimSmartCardEap::NewL(iPhone, this, aAID, aEapType));
+
+	if (err != KErrNone)
+		{
+		LOGPHONE2("ERROR could not create CSimSmartCardEap object [err=%d]", err);
+		User::Leave(err);
+		}
+
+	return phoneScEap;
+	}
+
+/**
+Returns the first procedure data section, as parsed from the
+config.txt, with aAID and aEapType.
+
+@param aAID
+@param aEapType
+@return The first procedure data with aAID and aEapType from the
+        config.txt.  NULL if no such procedure data is found.
+*/
+TEapProcedureData* CSimSmartCardEapManager::ProcData(const RMobilePhone::TAID& aAID, const RMobileSmartCardEap::TEapType& aEapType)
+	{
+	for (TInt ii = 0; ii < iEapProcData.Count(); ii++)
+		{
+		if (iEapProcData[ii].iAID == aAID)
+			{
+			// two ifs rather than && to help debug
+			if (iEapProcData[ii].iEapType == aEapType)
+				{
+				if (!iDiscardedProcedure[ii])
+					{
+					return &iEapProcData[ii];
+					}
+				}
+			}
+		}
+	return NULL;
+	}
+
+void CSimSmartCardEapManager::ProcDataUseCompleted(const TEapProcedureData* aProcData)
+	{
+	if (aProcData == NULL)
+		{
+		return;
+		}
+
+	TInt pos = KErrNotFound;
+
+	for (TInt ii = 0; ii < iEapProcData.Count(); ii++)
+		{
+		if ((&iEapProcData[ii]) == aProcData)
+			{
+			pos = ii;
+			break;
+			}
+		}
+
+	if (pos != KErrNotFound)
+		{
+		iDiscardedProcedure[pos] = ETrue;
+		}
+	}
+
+/**
+Register a sub-session object.  At the present time, list is maintained
+for clean-up only; i.e. this object stores pointers to all EAP sub-
+session objects.
+*/
+void CSimSmartCardEapManager::RegisterSubSessionL(CSimSmartCardEap* aToRegister)
+	{
+	iSubSessionObjs.AppendL(aToRegister);
+	}
+
+/**
+Remove a sub-session object from list of active sub-sessions.
+*/
+TInt CSimSmartCardEapManager::DeRegisterSubSession(const CSimSmartCardEap* aToDeRegister)
+	{
+	TInt index = iSubSessionObjs.Find(aToDeRegister);
+
+	if (index < 0)
+		{
+		return index;
+		}
+
+	iSubSessionObjs.Remove(index);
+	iSubSessionObjs.Compress();
+
+	return KErrNone;
+	}
+
+// CSimSmartCardEap implementation //
+
+CSimSmartCardEap* CSimSmartCardEap::NewL(CSimPhone *aPhone, CSimSmartCardEapManager* aEapMan, RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType)
+	{
+	CSimSmartCardEap* phone = new(ELeave) CSimSmartCardEap(aPhone, aAID, aEapType);
+	CleanupStack::PushL(phone);
+	phone->ConstructL(aEapMan);
+	CleanupStack::Pop();
+	return phone;
+	}
+
+CSimSmartCardEap::CSimSmartCardEap(CSimPhone *aPhone, RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType)
+: iPhone(aPhone), iProcedureData(NULL), iSSInitialised(EFalse),
+  iAccessStatus(RMobileSmartCardEap::EEapMethodAvailable), iAuthStatus(RMobileSmartCardEap::ENoAuthStarted),
+  iCliTerminationListener(NULL), iCurrentChallenge(0)
+	{
+	iAID = aAID;
+	iEapType = aEapType;
+	}
+
+void CSimSmartCardEap::ConstructL(CSimSmartCardEapManager* aEapMan)
+	{
+	LOGPHONE1("CSimSmartCardEap: starting second phase construction");
+
+	iSemaphr.CreateGlobal(KNullDesC, EOwnerThread);
+	aEapMan->RegisterSubSessionL(this);
+	iEapMan = aEapMan;
+
+	LOGPHONE1("CSimSmartCardEap created");
+	}
+
+CSimSmartCardEap::~CSimSmartCardEap()
+	{
+	if (iCliTerminationListener != NULL)
+		{
+		delete iCliTerminationListener;
+		iCliTerminationListener = NULL;
+		}
+	iSemaphr.Close();
+
+	// remove config entry from manager
+	if (iProcedureData != NULL)
+		{
+		iEapMan->ProcDataUseCompleted(iProcedureData);
+		iProcedureData = NULL;
+		}
+
+	TInt err = iEapMan->DeRegisterSubSession(this);
+	LOGPHONE2("CSimSmartCardEap destroyed, deregistering returned %d", err);
+
+	iEapMan = NULL;
+	}
+
+
+void CSimSmartCardEap::Init()
+	{
+	// server calls this function once it has created the sub-session
+	// it gives the TSY chance to do any initialisation it may need to do for
+	// this sub-session
+	}
+
+CTelObject* CSimSmartCardEap::OpenNewObjectByNameL(const TDesC& /*aName*/)
+	{
+	// Server calls this function when a client is opening an object from the phone
+	// for the first time.
+	// Multiple clients opening handles to the same sub-session object will be dealt with
+	// by the server - i.e. by reference counting
+	User::Leave(KErrNotSupported);
+	return NULL;
+	}
+
+CTelObject* CSimSmartCardEap::OpenNewObjectL(TDes& /*aNewName*/)
+	{
+	// all objects opened from the phone are opened by name, hence this method
+	// is not supported
+	User::Leave(KErrNotSupported);
+	return NULL;
+	}
+
+CTelObject::TReqMode CSimSmartCardEap::ReqModeL(const TInt aIpc)
+	{
+	// ReqModeL is called from the server's CTelObject::ReqAnalyserL
+	// in order to check the type of request it has
+
+	// The following are example request types for this dummy TSY
+	// All TSYs do not have to have these request types but they have been given
+	// "sensible" values in this test code
+
+	CTelObject::TReqMode ret = 0;
+
+	switch (aIpc)
+		{
+	// Non flow-controlled requests
+	case EMobileSmartCardEapInitialiseEapMethod:
+	case EMobileSmartCardEapGetUserIdentity:
+	case EMobileSmartCardEapGetAuthenticationStatus:
+	case EMobileSmartCardEapGetEapKey:
+	case EMobileSmartCardEapAuthenticationPhase1:
+	case EMobileSmartCardEapAuthenticationPhase2:
+	case EMobileSmartCardEapReleaseEapMethod:
+	case EMobileSmartCardEapGetEapMethodAccessStatus:
+		break;
+
+	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
+		ret = KReqModeMultipleCompletionEnabled;
+		break;
+
+	default:
+		User::Leave(KErrNotSupported);
+		break;
+		}
+
+	return ret;
+	}
+
+TInt CSimSmartCardEap::RegisterNotification(const TInt /*aIpc*/)
+	{
+	// RegisterNotification is called when the server recognises that this notification
+	// is being posted for the first time on this sub-session object.
+
+	// It enables the TSY to "turn on" any regular notification messages that it may 
+	// receive from the phone
+
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::DeregisterNotification(const TInt /*aIpc*/)
+	{
+	// DeregisterNotification is called when the server recognises that this notification
+	// will not be posted again because the last client to have a handle on this sub-session
+	// object has just closed the handle.
+
+	// It enables the TSY to "turn off" any regular notification messages that it may
+	// receive from the phone
+
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::NumberOfSlotsL(const TInt aIpc)
+	{
+	// NumberOfSlotsL is called by the server when it is registering a new notification
+	// It enables the TSY to tell the server how many buffer slots to allocate for
+	// "repost immediately" notifications that may trigger before clients collect them
+
+	TInt numberOfSlots = 1;
+
+	switch (aIpc)
+		{
+	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
+		numberOfSlots = 3;
+		break;
+
+	default:
+		// Unknown or invalid Phone IPC
+		User::Leave(KErrNotSupported);
+		break;
+		}
+
+	return numberOfSlots;
+	}
+
+TInt CSimSmartCardEap::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,
+                               const TDataPackage& aPackage)
+	{
+	// ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request 
+	// for the TSY to process
+	// A request handle, request type and request data are passed to the TSY
+
+	TAny* dataPtr = aPackage.Ptr1();
+	TAny* dataPtr2 = aPackage.Ptr2();
+
+	// The request data has to extracted from TDataPackage and the TAny* pointers have to
+	// be "cast" to the expected request data type
+
+	switch(aIpc)
+		{
+	// Non-Flow controlled requests
+
+	case EMobileSmartCardEapInitialiseEapMethod:
+		return SimInitialiseEapMethod(aTsyReqHandle,
+		         reinterpret_cast<TThreadId*>(dataPtr));
+
+	case EMobileSmartCardEapGetUserIdentity:
+		return SimGetUserIdentity(aTsyReqHandle,
+		         reinterpret_cast<RMobileSmartCardEap::TEapUserIdType*>(dataPtr),
+		         aPackage.Des2n());
+
+	case EMobileSmartCardEapGetAuthenticationStatus:
+		return SimGetAuthenticationStatus(aTsyReqHandle, 
+		         reinterpret_cast<RMobileSmartCardEap::TEapAuthStatus*>(dataPtr));
+
+	case EMobileSmartCardEapGetEapKey:
+		return SimGetEapKey(aTsyReqHandle,
+		         reinterpret_cast<RMobileSmartCardEap::TEapKeyTag*>(dataPtr),
+		         aPackage.Des2n());
+
+	case EMobileSmartCardEapAuthenticationPhase1:
+		return SimSetAuthenticateDataForPhase1(aTsyReqHandle,
+		         aPackage.Des1n(), reinterpret_cast<TInt*>(dataPtr2));
+
+	case EMobileSmartCardEapAuthenticationPhase2:
+		return SimGetAuthenticateDataForPhase2(aTsyReqHandle,
+		         aPackage.Des1n(), aPackage.Des2n());
+
+	case EMobileSmartCardEapReleaseEapMethod:
+		return SimReleaseEapMethod(aTsyReqHandle);
+
+	case EMobileSmartCardEapGetEapMethodAccessStatus:
+		return SimGetEapMethodAccessStatus(aTsyReqHandle,
+		         reinterpret_cast<RMobileSmartCardEap::TEapMethodAccessStatus*>(dataPtr));
+
+	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
+		return SimNotifyEapMethodAccessStatusChange(aTsyReqHandle,
+		         reinterpret_cast<RMobileSmartCardEap::TEapMethodAccessStatus*>(dataPtr));
+
+	default:
+		return KErrNotSupported;
+		}
+	}
+
+TInt CSimSmartCardEap::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
+	{
+	// CancelService is called by the server when it is "cleaning-up" any still outstanding
+	// asynchronous requests before closing a client's sub-session.
+	// This will happen if a client closes its R-class handle without cancelling outstanding
+	// asynchronous requests.
+
+	switch (aIpc)
+		{
+	case EMobileSmartCardEapGetUserIdentity:
+		return SimGetUserIdentityCancel(aTsyReqHandle);
+	case EMobileSmartCardEapGetAuthenticationStatus:
+		return SimGetAuthenticationStatusCancel(aTsyReqHandle);
+	case EMobileSmartCardEapGetEapKey:
+		return SimGetEapKeyCancel(aTsyReqHandle);
+	case EMobileSmartCardEapInitialiseEapMethod:
+		return SimInitialiseEapMethodCancel(aTsyReqHandle);
+	case EMobileSmartCardEapAuthenticationPhase1:
+	case EMobileSmartCardEapAuthenticationPhase2:
+		return SimSmartCardEapAuthenticationCancel(aTsyReqHandle);
+	case EMobileSmartCardEapNotifyEapMethodAccessStatusChange:
+		return SimNotifyEapMethodAccessStatusChangeCancel(aTsyReqHandle);
+	default:
+		return KErrNotSupported;
+		}
+	}
+
+RHandleBase* CSimSmartCardEap::GlobalKernelObjectHandle()
+	{
+	return &iSemaphr;
+	}
+
+TInt CSimSmartCardEap::SimInitialiseEapMethod(const TTsyReqHandle aTsyReqHandle, TThreadId* aThreadId)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimInitialiseEapMethod called");
+	// This can only be called through RMobileSmartCardEap for one instance
+
+	if (iSSInitialised)
+		{
+		// re-initialise request sent, so will be treated as a mistake
+		// and nothing will happen!
+		ReqCompleted(aTsyReqHandle, KErrNone);
+		}
+	else
+		{
+		delete iCliTerminationListener;
+		TRAPD(err, iCliTerminationListener = CThreadTerminationListener::NewL(this, *aThreadId));
+		if (err != KErrNone)
+			{
+			LOGPHONE2("ERROR could not create a client termination listener [err=%d] (not initialised)", err);
+			ReqCompleted(aTsyReqHandle, err);
+			}
+		else
+			{
+			iProcedureData = iEapMan->ProcData(iAID, iEapType);
+			if (iProcedureData == NULL)
+				{
+				LOGPHONE1("ERROR could not find sub-session's procedure");
+				ReqCompleted(aTsyReqHandle, KErrNotFound);
+				return KErrNone;
+				}
+
+			iSSInitialised = ETrue;
+			iCliTerminationListener->Start();
+			iAccessStatus = RMobileSmartCardEap::EEapMethodInUseApplicationActive;
+			SimCompleteNotifyEapMethodAccessStatusChange();
+			ReqCompleted(aTsyReqHandle, KErrNone);
+			}
+		}
+
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimInitialiseEapMethodCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimInitialiseEapMethodCancel called");
+	iProcedureData = NULL;
+	iSSInitialised = EFalse;
+	iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
+	SimCompleteNotifyEapMethodAccessStatusChange();
+	ReqCompleted(aTsyReqHandle, KErrCancel);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimGetUserIdentity(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapUserIdType* aEapIdType, TDes8* aUserId)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetUserIdentity called");
+
+	RMobileSmartCardEap::TEapUserIdentityV6Pckg *userIdPckg = reinterpret_cast<RMobileSmartCardEap::TEapUserIdentityV6Pckg*>(aUserId);
+	RMobileSmartCardEap::TEapUserIdentityV6 &userId = (*userIdPckg)();
+	
+	// Check that the data structure is supported by the simulated TSY version
+	TInt err = iPhone->CheckSimTsyVersion(userId);
+		if(err != KErrNone)
+			{
+			iPhone->ReqCompleted(aTsyReqHandle, err);
+			return KErrNone;
+			}
+
+	if (*aEapIdType == RMobileSmartCardEap::EPermanentIdentity)
+		{
+		if (iProcedureData->iEapId == NULL)
+			{
+			ReqCompleted(aTsyReqHandle, KErrNotFound);
+			LOGPHONE1("ERROR EAP sub-session does not contain EPermanentIdentity");
+			return KErrNone;
+			}
+
+		userId.iEapId = iProcedureData->iEapId->Des();
+		}
+	else if (*aEapIdType == RMobileSmartCardEap::EPseudonymIdentity)
+		{
+		if (iProcedureData->iEapPsId == NULL)
+			{
+			ReqCompleted(aTsyReqHandle, KErrNotFound);
+			LOGPHONE1("ERROR EAP sub-session does not contain EPseudonymIdentity");
+			return KErrNone;
+			}
+
+		userId.iEapId = iProcedureData->iEapPsId->Des();
+		}
+	else
+		{
+		ReqCompleted(aTsyReqHandle, KErrArgument);
+		LOGPHONE2("ERROR invalid EAP id type requested [tag=%d]", *aEapIdType);
+		return KErrNone;
+		}
+
+	ReqCompleted(aTsyReqHandle, KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimGetUserIdentityCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetUserIdentityCancel called");
+	ReqCompleted(aTsyReqHandle, KErrCancel);
+	return KErrNone;
+	}
+	
+TInt CSimSmartCardEap::SimGetAuthenticationStatus(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapAuthStatus* aAuthStatus)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetAuthenticationStatus called");
+
+	(*aAuthStatus) = iAuthStatus;
+
+	ReqCompleted(aTsyReqHandle, KErrNone);
+	return KErrNone;
+	}
+	
+TInt CSimSmartCardEap::SimGetAuthenticationStatusCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetAuthenticationStatusCancel called");
+	ReqCompleted(aTsyReqHandle, KErrCancel);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimGetEapKey(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapKeyTag* aEapKeyTag, TDes8* aKey)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetEapKey called");
+
+	RMobileSmartCardEap::TEapKeyV6Pckg *keyPckg = reinterpret_cast<RMobileSmartCardEap::TEapKeyV6Pckg*>(aKey);
+	RMobileSmartCardEap::TEapKeyV6 &key = (*keyPckg)();
+
+	// Check that the data structure is supported by the simulated TSY version
+	TInt err = iPhone->CheckSimTsyVersion(key);
+		if(err != KErrNone)
+			{
+			iPhone->ReqCompleted(aTsyReqHandle, err);
+			return KErrNone;
+			}
+
+	if (*aEapKeyTag == RMobileSmartCardEap::EEapKeyMSK)
+		{
+		if (iProcedureData->iEapKey == NULL)
+			{
+			ReqCompleted(aTsyReqHandle, KErrNotFound);
+			LOGPHONE1("ERROR EAP sub-session does not contain EEapKeyMSK");
+			return KErrNone;
+			}
+
+		key.iEapKey = iProcedureData->iEapKey->Des();
+		}
+	else if (*aEapKeyTag == RMobileSmartCardEap::EEapKeyEMSK)
+		{
+		if (iProcedureData->iEapExtKey == NULL)
+			{
+			ReqCompleted(aTsyReqHandle, KErrNotFound);
+			LOGPHONE1("ERROR EAP sub-session does not contain EEapKeyEMSK");
+			return KErrNone;
+			}
+
+		key.iEapKey = iProcedureData->iEapExtKey->Des();
+		}
+	else
+		{
+		ReqCompleted(aTsyReqHandle, KErrArgument);
+		LOGPHONE2("ERROR invalid EAP key tag requested [tag=%d]", *aEapKeyTag);
+		return KErrNone;
+		}
+
+	ReqCompleted(aTsyReqHandle, KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimGetEapKeyCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetEapKeyCancel called");
+	ReqCompleted(aTsyReqHandle, KErrCancel);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimSetAuthenticateDataForPhase1(const TTsyReqHandle aTsyReqHandle, TDes8* aEapAuthData, TInt* aPhase1Size)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimSetAuthenticateDataForPhase1 called");
+
+	if (iCurrentChallenge >= iProcedureData->iChResp.Count())
+		{
+		ReqCompleted(aTsyReqHandle, KErrAccessDenied);
+		return KErrNone;
+		}
+
+	RMobileSmartCardEap::CEapAuthenticateRequestDataV6* authReq = NULL;
+	TRAPD(err, authReq = RMobileSmartCardEap::CEapAuthenticateRequestDataV6::NewL());
+	if (err != KErrNone)
+		{
+		LOGPHONE2("ERR Could not allocate memory for challenge request object [err=%d]", err);
+		ReqCompleted(aTsyReqHandle, err);
+		return KErrNone;
+		}
+
+	TRAP(err, authReq->InternalizeL(*aEapAuthData));
+	if (err != KErrNone)
+		{
+		LOGPHONE2("ERR Could not allocate memory for challenge request [err=%d]", err);
+		ReqCompleted(aTsyReqHandle, err);
+		return KErrNone;
+		}
+
+	TPtr8 reqPacket = authReq->GetEapReqPacket();
+
+	TPtr8 tempPtr(NULL, 0);
+	tempPtr.Set(iProcedureData->iChResp[iCurrentChallenge].iChallenge->Des());
+
+	if (reqPacket != tempPtr)
+		{
+		LOGPHONE2("ERR challenge request does not match config [currentChallenge=%d]", iCurrentChallenge);
+		ReqCompleted(aTsyReqHandle, KErrCorrupt);
+		return KErrNone;
+		}
+
+	(*aPhase1Size) = iProcedureData->iChResp[iCurrentChallenge].iResp->Length();
+
+	ReqCompleted(aTsyReqHandle, KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimGetAuthenticateDataForPhase2(const TTsyReqHandle aTsyReqHandle, TDes8* /*aEapAuthData*/, TDes8* aPhase2Resp)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimSetAuthenticateDataForPhase2 called");
+
+	if (iCurrentChallenge >= iProcedureData->iChResp.Count())
+		{
+		ReqCompleted(aTsyReqHandle, KErrAccessDenied);
+		return KErrNone;
+		}
+
+	TPtr8 tempPtr(NULL, 0);
+	tempPtr.Set(iProcedureData->iChResp[iCurrentChallenge].iResp->Des());
+
+	aPhase2Resp->Copy(tempPtr);
+ 	iAuthStatus = iProcedureData->iChResp[iCurrentChallenge].iAuthStatus;
+ 	iCurrentChallenge++;
+
+	ReqCompleted(aTsyReqHandle, KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimSmartCardEapAuthenticationCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimSmartCardEapAuthenticationCancel called");
+	ReqCompleted(aTsyReqHandle, KErrCancel);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimReleaseEapMethod(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimReleaseEapMethod called");
+	iSSInitialised = EFalse;
+	iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
+	ReqCompleted(aTsyReqHandle, KErrNone);
+
+	SimCompleteNotifyEapMethodAccessStatusChange();
+
+	// remove config entry from manager
+	iEapMan->ProcDataUseCompleted(iProcedureData);
+	iProcedureData = NULL;
+
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimGetEapMethodAccessStatus(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapMethodAccessStatus* aEapState)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimGetEapMethodAccessStatus called");
+	*aEapState = iAccessStatus;
+	ReqCompleted(aTsyReqHandle, KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimNotifyEapMethodAccessStatusChange(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapMethodAccessStatus* aEapState)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimNotifyEapMethodAccessStatusChange called");
+	__ASSERT_ALWAYS(!iEapAccessNotifyData.iNotifyPending, PanicClient(EEtelPanicRequestAsyncTwice));
+
+	iEapAccessNotifyData.iNotifyPending = ETrue;
+	iEapAccessNotifyData.iNotifyHandle = aTsyReqHandle;
+	iEapAccessNotifyData.iNotifyData = aEapState;
+
+	return KErrNone;
+	}
+
+TInt CSimSmartCardEap::SimNotifyEapMethodAccessStatusChangeCancel(const TTsyReqHandle aTsyReqHandle)
+	{
+	LOGPHONE1("CSimSmartCardEap::SimNotifyEapMethodAccessStatusChangeCancel called");
+	if(iEapAccessNotifyData.iNotifyPending)
+		{
+		iEapAccessNotifyData.iNotifyPending = EFalse;
+		ReqCompleted(aTsyReqHandle, KErrCancel);
+		return KErrNone;
+		}	
+
+//	iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+void CSimSmartCardEap::SimCompleteNotifyEapMethodAccessStatusChange()
+	{
+	LOGPHONE1("CSimSmartCardEap::SimCompleteNotifyEapMethodAccessStatusChange called");
+
+	if(iEapAccessNotifyData.iNotifyPending)
+		{
+		iEapAccessNotifyData.iNotifyPending = EFalse;
+		*(reinterpret_cast<RMobileSmartCardEap::TEapMethodAccessStatus*>(iEapAccessNotifyData.iNotifyData)) = iAccessStatus;
+		ReqCompleted(iEapAccessNotifyData.iNotifyHandle, KErrNone);
+		}
+	}
+
+void CSimSmartCardEap::ClientHasTerminated(TInt /*aExitReason*/)
+	{
+	// Can TSY do anything with the thread's exit reason?
+	// Exit code can be a zero (e.g. for KERN-EXEC 0) a positive value
+	// (e.g. for KERN-EXEC 3) or a negative error.
+
+	switch (iAccessStatus)
+		{
+	case RMobileSmartCardEap::EEapMethodInUseApplicationActive:
+		iSSInitialised = EFalse;
+		iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
+		SimCompleteNotifyEapMethodAccessStatusChange();
+		iSemaphr.Signal();
+
+		// remove config entry from manager
+		iEapMan->ProcDataUseCompleted(iProcedureData);
+		iProcedureData = NULL;
+
+		break;
+
+	case RMobileSmartCardEap::EEapMethodInUseApplicationInactive:
+		iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable;
+		SimCompleteNotifyEapMethodAccessStatusChange();
+		iSemaphr.Signal();
+		break;
+
+	default:
+		;
+		}
+	}
+
+//
+// Class definition for monitoring thread termination
+//
+
+CSimSmartCardEap::CThreadTerminationListener* CSimSmartCardEap::CThreadTerminationListener::NewL(CSimSmartCardEap* aSubSess, const TThreadId& aId)
+	{
+	CThreadTerminationListener* self = new(ELeave) CThreadTerminationListener(aSubSess);
+	CleanupStack::PushL(self);
+	self->ConstructL(aId);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CSimSmartCardEap::CThreadTerminationListener::CThreadTerminationListener(CSimSmartCardEap* aSubSess)
+: CActive(EPriorityStandard), iSubSess(aSubSess)
+	{
+	}
+
+void CSimSmartCardEap::CThreadTerminationListener::ConstructL(const TThreadId& aId)
+	{
+	TInt openTh = iCliThread.Open(aId);
+	User::LeaveIfError(openTh);
+    CActiveScheduler::Add(this);
+	}
+
+void CSimSmartCardEap::CThreadTerminationListener::Start()
+	{
+	iCliThread.Logon(iStatus);
+	SetActive();
+	}
+
+void CSimSmartCardEap::CThreadTerminationListener::RunL()
+	{
+	iSubSess->ClientHasTerminated(iStatus.Int());
+	}
+
+void CSimSmartCardEap::CThreadTerminationListener::DoCancel()
+	{
+	iCliThread.LogonCancel(iStatus);
+	}
+
+CSimSmartCardEap::CThreadTerminationListener::~CThreadTerminationListener()
+	{
+	Cancel();
+	iCliThread.Close();
+	}