// Copyright (c) 2002-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:
// Implements the Phone Smart Card application and file manipulation code.
//
//
/**
@file
*/
#include <testconfigfileparser.h>
#include <etelmmerr.h>
#include "CSimPhone.h"
#include "Simlog.h"
//
// CSimPhoneSmartCardApp
//
CSimPhoneSmartCardApp* CSimPhoneSmartCardApp::NewL(CSimPhone* aPhone)
/**
* Standard two phase constructor.
* @param aPhone The phone object from which the Phone Smart Card applications will open
*/
{
CSimPhoneSmartCardApp* obj=new(ELeave) CSimPhoneSmartCardApp(aPhone);
CleanupStack::PushL(obj);
obj->ConstructL();
CleanupStack::Pop();
return obj;
}
CSimPhoneSmartCardApp::CSimPhoneSmartCardApp(CSimPhone* aPhone)
: iPhone(aPhone), iCurrentSelection(RMobilePhone::EUSimSelectionAutomatic),
iFoundScAppTags(EFalse)
/**
* Trivial first phase constructor.
* @param aPhone The phone object from which this Phone SmartCard App was opened.
*/
{}
void CSimPhoneSmartCardApp::Init()
{}
void CSimPhoneSmartCardApp::ConstructL()
/**
* Second phase of the 2-phase constructor.
* Constructs all the member data and retrieves all the data from the config file specific to this class.
*
* @leave Leaves due to not enough memory or if any data member does not construct for any reason.
*/
{
LOGPHONE1("Starting to parse Phone Smart Card applications additional config parameters...");
ParseSmartCardApplicationInfoL();
ParseSmartCardFileInfoL();
MapUSimAppsL();
LOGPHONE1("Finished parsing Phone Smart Card applications additional config parameters...");
}
CSimPhoneSmartCardApp::~CSimPhoneSmartCardApp()
/**
* Standard destructor. Any objects created by the ::ConstructL() function
* will be destroyed here.
*/
{
delete iTimer;
if(iSmartCardAppEventList)
{
iSmartCardAppEventList->Delete(0, iSmartCardAppEventList->Count());
delete iSmartCardAppEventList;
}
if(iSmartCardAppList)
{
iSmartCardAppList->Delete(0, iSmartCardAppList->Count());
delete iSmartCardAppList;
}
if (iSmartCardFileList)
{
iSmartCardFileList->ResetAndDestroy();
delete iSmartCardFileList;
}
if(iUSimAppList)
{
iUSimAppList->Close();
delete iUSimAppList;
}
}
TInt CSimPhoneSmartCardApp::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc, const TDataPackage& aPckg)
/**
* ExtFunc is called by the server when it has an "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
*
* @param aTsyReqHandle The request handle for completing the request
* @param aIpc Ipc representing the request
* @param aPackage any data associated with the request
* @return err KErrNone if request completes ok
*/
{
TAny* dataPtr = aPckg.Ptr1();
TAny* dataPtr2 = aPckg.Ptr2();
// The following requests can be completed even if the completion of another request is pending.
switch(aIpc)
{
case EMobilePhoneGetCurrentActiveUSimApplication:
return GetCurrentActiveUSimApplication(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TAID*>(dataPtr));
case EMobilePhoneEnumerateUSimApplications:
return EnumerateUSimApplications(aTsyReqHandle,
reinterpret_cast<TInt*> (dataPtr),
reinterpret_cast<RMobilePhone::TAID*> (dataPtr2));
case EMobilePhoneSetUSimApplicationStatus:
return SetUSimApplicationStatus(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TAID*> (dataPtr),
reinterpret_cast<RMobilePhone::TUSimAppAction*> (dataPtr2));
case EMobilePhoneGetUSimApplicationsInfo:
return GetUSimApplicationInfo(aTsyReqHandle,
reinterpret_cast<TInt*> (dataPtr),
aPckg.Des2n());
case EMobilePhoneNotifyUSimApplicationsInfoChange:
return NotifyUSimApplicationsInfoChange(aTsyReqHandle,
reinterpret_cast<TInt*> (dataPtr),
reinterpret_cast<RMobilePhone::TAID*> (dataPtr2));
case EMobilePhoneEnumerateSmartCardApplications:
return EnumerateScApplications(aTsyReqHandle,
reinterpret_cast<TUint*>(dataPtr));
case EMobilePhoneGetSmartCardApplicationInfo:
return GetScApplicationInfo(aTsyReqHandle,
reinterpret_cast<TInt*>(dataPtr),
aPckg.Des2n());
case EMobilePhoneSetSmartCardApplicationStatus:
return SetScApplicationStatus(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TAID*>(dataPtr),
reinterpret_cast<RMobilePhone::TSmartCardApplicationAction*>(dataPtr2));
case EMobilePhoneNotifySmartCardApplicationInfoChange:
return NotifyScApplicationInfoChange(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TAID*>(dataPtr),
reinterpret_cast<RMobilePhone::TSmartCardApplicationEvent*>(dataPtr2));
case EMobilePhoneGetUSimAppsSelectionMode:
return GetUSimAppsSelectionMode(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TUSimSelectionMode*>(dataPtr));
case EMobilePhoneSetUSimAppsSelectionMode:
return SetUSimAppsSelectionMode(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TUSimSelectionMode*>(dataPtr));
case EMobilePhoneNotifyUSimAppsSelectionModeChange:
return NotifyUSIMAppsSelectionModeChange(aTsyReqHandle,
reinterpret_cast<RMobilePhone::TUSimSelectionMode*>(dataPtr));
case EMobilePhoneGetScFileInfo:
return GetScFileInfo(aTsyReqHandle,
*reinterpret_cast<RMobilePhone::TScFilePath*>(dataPtr),
aPckg.Des2n());
case EMobilePhoneReadScFile:
return ReadScFile(aTsyReqHandle,
*reinterpret_cast<RMobilePhone::TScFilePathWithAccessOffsets*>(dataPtr),
aPckg.Des2n());
case EMobilePhoneUpdateScFile:
return UpdateScFile(aTsyReqHandle,
*reinterpret_cast<RMobilePhone::TScFilePathWithAccessOffsets*>(dataPtr),
aPckg.Des2n());
default:
break;
}
return KErrNotSupported;
}
CTelObject::TReqMode CSimPhoneSmartCardApp::ReqModeL(const TInt aIpc)
/**
* This function returns the Request Mode for the request with the passed IPC value.
* The function leaves if the IPC is not found.
*
* @param aIpc The IPC number of the request.
* @return TReqMode The request mode.
*/
{
CTelObject::TReqMode ret=0;
switch(aIpc)
{
case EMobilePhoneGetCurrentActiveUSimApplication:
case EMobilePhoneEnumerateUSimApplications:
case EMobilePhoneSetUSimApplicationStatus:
case EMobilePhoneGetUSimApplicationsInfo:
case EMobilePhoneEnumerateSmartCardApplications:
case EMobilePhoneSetSmartCardApplicationStatus:
case EMobilePhoneGetSmartCardApplicationInfo:
case EMobilePhoneGetUSimAppsSelectionMode:
case EMobilePhoneSetUSimAppsSelectionMode:
case EMobilePhoneGetScFileInfo:
case EMobilePhoneReadScFile:
case EMobilePhoneUpdateScFile:
break;
case EMobilePhoneNotifyUSimAppsSelectionModeChange:
case EMobilePhoneNotifyUSimApplicationsInfoChange:
case EMobilePhoneNotifySmartCardApplicationInfoChange:
ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
break;
default:
User::Leave(KErrNotSupported);
break;
}
return ret;
}
TInt CSimPhoneSmartCardApp::RegisterNotification(const TInt /*aIpc*/)
/**
* The ETel Server calls this function when the first client makes a notification
* request. If supported by the underlying protocol controlling the
* signalling stack, this can be used to start requesting updates for the relevant
* service.
*/
{
return KErrNone;
}
TInt CSimPhoneSmartCardApp::DeregisterNotification(const TInt /*aIpc*/)
/**
* The ETel Server calls this function when the last client that had previously
* made a notification request closes its ETel Server handle. If supported by
* the underlying protocol controlling the signalling stack, this can be used
* to stop requesting updates for the relevant service.
*/
{
return KErrNone;
}
CTelObject* CSimPhoneSmartCardApp::OpenNewObjectByNameL(const TDesC& /*aName*/)
/**
* The API does not support any objects that could be opened from this one.
*/
{
User::Leave(KErrNotSupported);
return NULL;
}
CTelObject* CSimPhoneSmartCardApp::OpenNewObjectL(TDes&)
/**
* The API does not support any objects that could be opened from this one.
*/
{
User::Leave(KErrNotSupported);
return NULL;
}
TInt CSimPhoneSmartCardApp::NumberOfSlotsL(const TInt aIpc)
/**
* Return the number of slots that the ETel Server should allocate for buffering requests
* of the given IPC number.
*
* @param aIpc The IPC number of the request.
*/
{
TInt numberOfSlots = 0;
switch(aIpc)
{
case EMobilePhoneNotifyUSimAppsSelectionModeChange:
case EMobilePhoneNotifyUSimApplicationsInfoChange:
case EMobilePhoneNotifySmartCardApplicationInfoChange:
numberOfSlots = KDefaultNumberOfSlots;
break;
default:
LOGPHONE1("CSimPhoneSmartCardApp: Number of Slots error, unknown IPC");
User::Leave(KErrNotSupported);
break;
}
return numberOfSlots;
}
TInt CSimPhoneSmartCardApp::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
/**
* Cancel an outstanding request.
* @param aIpc The IPC number of the request that is to be cancelled.
* @param aTsyReqHandle The TSY request handle of the request that is to be cancelled.
* @return Standard return value.
*/
{
switch(aIpc)
{
case EMobilePhoneEnumerateSmartCardApplications:
return EnumerateScApplicationsCancel(aTsyReqHandle);
case EMobilePhoneEnumerateUSimApplications:
return EnumerateUSimApplicationsCancel(aTsyReqHandle);
case EMobilePhoneSetUSimApplicationStatus:
return SetUSimApplicationStatusCancel(aTsyReqHandle);
case EMobilePhoneGetUSimApplicationsInfo:
return GetUSimApplicationInfoCancel(aTsyReqHandle);
case EMobilePhoneNotifyUSimApplicationsInfoChange:
return NotifyUSimApplicationsInfoChangeCancel(aTsyReqHandle);
case EMobilePhoneSetSmartCardApplicationStatus:
return SetScApplicationStatusCancel(aTsyReqHandle);
case EMobilePhoneGetSmartCardApplicationInfo:
return GetScApplicationInfoCancel(aTsyReqHandle);
case EMobilePhoneGetCurrentActiveUSimApplication:
return GetCurrentActiveUSimApplicationCancel(aTsyReqHandle);
case EMobilePhoneNotifySmartCardApplicationInfoChange:
return NotifyScApplicationInfoChangeCancel(aTsyReqHandle);
case EMobilePhoneSetUSimAppsSelectionMode:
return SetUSimAppsSelectionModeCancel(aTsyReqHandle);
case EMobilePhoneGetUSimAppsSelectionMode:
return GetUSimAppsSelectionModeCancel(aTsyReqHandle);
case EMobilePhoneNotifyUSimAppsSelectionModeChange:
return NotifyUSIMAppsSelectionModeChangeCancel(aTsyReqHandle);
case EMobilePhoneGetScFileInfo:
return GetScFileInfoCancel(aTsyReqHandle);
case EMobilePhoneReadScFile:
return ReadScFileCancel(aTsyReqHandle);
case EMobilePhoneUpdateScFile:
return UpdateScFileCancel(aTsyReqHandle);
default:
break;
}
return KErrNone;
}
const CTestConfigSection* CSimPhoneSmartCardApp::CfgFile()
/**
* Returns a pointer to the config file section
*
* @return CTestConfigSection a pointer to the configuration file data section
*/
{
LOGPHONE1(">>CSimPhoneSmartCardApp::CfgFile");
return iPhone->CfgFile();
}
void CSimPhoneSmartCardApp::TimerCallBack(TInt /*aId*/)
/**
* Timer callback function. When the timer goes off, it will call back into this
* function for further processing.
*
* @param aId an id identifying which timer callback is being called
*/
{
if(iNotifyScInfo.iNotifyPending || iNotifyUSimInfo.iNotifyPending)
{
TSmartCardAppEvent theEvent=iSmartCardAppEventList->At(iEventPointer);
TInt ret;
RMobilePhone::TSmartCardApplicationEvent occuredEvent;
TBool isUSimAppAffected = EFalse;
if(theEvent.iAction == RMobilePhone::EScApplicationActivate)
{
ret=ActivateSmartCardApp(theEvent.iAID, isUSimAppAffected);
occuredEvent = RMobilePhone::EScApplicationActivated;
}
else
{
ret=TerminateSmartCardApp(theEvent.iAID, isUSimAppAffected);
occuredEvent = RMobilePhone::EScApplicationTerminated;
}
if (ret == KErrNone)
{
iEventPointer++;
//notify any ScApp client if such notify request is pending
if(iNotifyScInfo.iNotifyPending)
{
iNotifyScInfo.iNotifyPending=EFalse;
*(RMobilePhone::TAID*)iNotifyScInfo.iNotifyData1=theEvent.iAID;
*(RMobilePhone::TSmartCardApplicationEvent*)iNotifyScInfo.iNotifyData2=occuredEvent;
iPhone->ReqCompleted(iNotifyScInfo.iNotifyHandle,KErrNone);
}
//notify any USimApp client if such notify request is pending
if(isUSimAppAffected && iNotifyUSimInfo.iNotifyPending)
{
iNotifyUSimInfo.iNotifyPending=EFalse;
if(occuredEvent == RMobilePhone::EScApplicationActivated)
{
*(RMobilePhone::TAID*)iNotifyUSimInfo.iNotifyData1=theEvent.iAID;
}
else
{
*(RMobilePhone::TAID*)iNotifyUSimInfo.iNotifyData1=_L8("");
}
*(TInt*)iNotifyUSimInfo.iNotifyData2=iUSimAppList->Count();
iPhone->ReqCompleted(iNotifyUSimInfo.iNotifyHandle,KErrNone);
}
}
}//end if(iNotifyScInfo.iNotifyPending...
}
TBool CSimPhoneSmartCardApp::FoundScAppTags()
/**
* Returns a value to indicate whether SCApp tags were found in the Config file
*
*/
{
return iFoundScAppTags;
}
void CSimPhoneSmartCardApp::TSmartCardFile::GetFileInfo(RMobilePhone::TScFileInfoV5& aScFileInfo)
/**
* Gets the SmartCard file's File info
*
* @param aScFileInfo The function passes back the file info through this reference
*/
{
aScFileInfo.iFileID = iFileID;
aScFileInfo.iType = iType;
aScFileInfo.iTotalLength = iTotalLength;
aScFileInfo.iRecordLength = iRecordLength;
aScFileInfo.iNumberRecords = iNumberRecords;
}
CSimPhoneSmartCardApp::TCyclicSmartCardFile::TCyclicSmartCardFile()
:iOldestRecord(0)
{}
TInt CSimPhoneSmartCardApp::TCyclicSmartCardFile::ReadFile(
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aReadBuffer)
/**
* Concrete implementation of the ReadFile() method for reading file data from a record based
* cyclic smart card file. Reads precisely one record (iRecordLength bytes).
*
* Note: Records are numbered from 1 to n NOT 0 to n-1
*
* @param aFilePathOffsets Information about which file to read (path) and where in the file to read data from (offsets)
* @param aReadBuffer The requested data is read into this buffer
*/
{
//check that the client has provided a buffer of sufficient size
if(aReadBuffer->MaxSize() < iRecordLength)
{
return KErrOverflow;
}
//check that the client has specified a valid start offset
else if(aFilePathOffsets.iStartOffset < 1 || aFilePathOffsets.iStartOffset > iNumberRecords)
{
LOGPHONE1("ERROR: File start offset information invalid.");
return KErrMMEtelScRecordNotFound;
}
else
{
//Var filepointer initially holds a pointer to the beginning of the specified record
//The record to read is specified as an offset from the oldest record. I.e. Record 1 is the
//newest record.
TInt filePointer = iOldestRecord + (aFilePathOffsets.iStartOffset * iRecordLength);
if(filePointer >= iTotalLength)
{
filePointer = filePointer - iTotalLength;
}
aReadBuffer->SetLength(iRecordLength);
aReadBuffer->FillZ();
TInt index;
for(index = 0; index < iRecordLength; index++)
{
(*aReadBuffer)[index] = iFileData[filePointer];
filePointer++;
}
return KErrNone;
}
}
TInt CSimPhoneSmartCardApp::TCyclicSmartCardFile::UpdateFile(
const RMobilePhone::TScFilePathWithAccessOffsets& /*aFilePathOffsets*/, TDes8* aWriteBuffer)
/**
* Concrete implementation of the UpdateFile() method for updating file data in a record based
* cyclic smart card file. Updates precisely one record (iRecordLength bytes). The record that is
* updated is the oldest record.
*
* Note: Records are numbered from 1 to n NOT 0 to n-1
*
* @param aReadBuffer The data with which the file should be updated.
*/
{
//Check that the client has provided a buffer of sufficient size
if(aWriteBuffer->Size() != iRecordLength)
{
return KErrMMEtelScWrongLength;
}
else
{
TInt filePointer = iOldestRecord ;
TInt index;
for(index = 0; index < iRecordLength; index++)
{
iFileData[filePointer] = (*aWriteBuffer)[index];
filePointer++;
}
UpdateOldestRecordPointer();
return KErrNone;
}
}
void CSimPhoneSmartCardApp::TCyclicSmartCardFile::UpdateOldestRecordPointer()
{
//IF the OldestRecord pointer is set to point to the beginning of the buffer
if(iOldestRecord==0)
{
//Set it to point to the beginning of the last record in the buffer
iOldestRecord = iTotalLength - iRecordLength;
}
//ELSE set it to point to the beginning of previous record (the second oldest record)
else
{
iOldestRecord = iOldestRecord - iRecordLength;
}
}
TInt CSimPhoneSmartCardApp::TLinearSmartCardFile::ReadFile(
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aReadBuffer)
/**
* Concrete implementation of the ReadFile() method for reading file data from a record based
* linear fixed smart card file. Reads precisely one record (iRecordLength bytes).
*
* Note: Records are numbered from 1 to n NOT 0 to n-1
*
* @param aFilePathOffsets Information about which file to read (path) and where in the file to read data from (offsets)
* @param aReadBuffer The requested data is read into this buffer
*/
{
//check that the client has provided a buffer of sufficient size
if(aReadBuffer->MaxSize() < iRecordLength)
{
return KErrOverflow;
}
//check that the client has specified a valid start offset
else if(aFilePathOffsets.iStartOffset < 1 || aFilePathOffsets.iStartOffset > iNumberRecords)
{
LOGPHONE1("ERROR: File start offset information invalid.");
return KErrMMEtelScRecordNotFound;
}
else
{
TInt filePointer = (aFilePathOffsets.iStartOffset - 1) * iRecordLength;
TInt index;
aReadBuffer->SetLength(iRecordLength);
aReadBuffer->FillZ();
for(index = 0; index < iRecordLength; index++)
{
(*aReadBuffer)[index] = iFileData[filePointer];
filePointer++;
}
return KErrNone;
}
}
TInt CSimPhoneSmartCardApp::TLinearSmartCardFile::UpdateFile(
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aWriteBuffer)
/**
* Concrete implementation of the UpdateFile() method for updating data in a record based
* linear fixed smart card file. Updates precisely one record (iRecordLength bytes).
*
* Note: Records are numbered from 1 to n NOT 0 to n-1
*
* @param aFilePathOffsets Information about which file to update (path) and where in the file to write data to (offsets)
* @param aReadBuffer The data with which the file should be updated.
*/
{
//check that the client has provided a buffer of sufficient size
if(aWriteBuffer->Size() != iRecordLength)
{
return KErrMMEtelScWrongLength;
}
//check that the client has specified a valid start offset
else if(aFilePathOffsets.iStartOffset < 1 || aFilePathOffsets.iStartOffset > iNumberRecords)
{
LOGPHONE1("ERROR: File start offset information invalid.");
return KErrMMEtelScRecordNotFound;
}
else
{
TInt filePointer = (aFilePathOffsets.iStartOffset - 1) * iRecordLength;
TInt index;
for(index = 0; index < iRecordLength; index++)
{
iFileData[filePointer] = (*aWriteBuffer)[index];
filePointer++;
}
return KErrNone;
}
}
TInt CSimPhoneSmartCardApp::TTransparentSmartCardFile::ReadFile(
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aReadBuffer)
/**
* Concrete implementation of the ReadFile() method for reading file data from a binary transparent
* smart card file.
*
* @param aFilePathOffsets Information about which file to read (path) and where in the file to read data from (offsets)
* @param aReadBuffer The requested data is read into this buffer
*/
{
const TInt& bytesToRead = aFilePathOffsets.iCount;
TInt filePointer = aFilePathOffsets.iStartOffset;
//check that the client has provided a buffer of sufficient size
if(aReadBuffer->MaxSize() < bytesToRead)
{
return KErrOverflow;
}
//check that the client has specified a valid start offset
else if(aFilePathOffsets.iStartOffset >= (TUint)iTotalLength)
{
LOGPHONE1("ERROR: File start offset information invalid.");
return KErrMMEtelScReferencedDataNotFound;
}
//check the client is not requesting to read too many bytes, resulting in reading
//off the end of the file
else if((bytesToRead + filePointer) > iTotalLength)
{
LOGPHONE1("ERROR: Path offset information results in reading off the end of the file");
return KErrMMEtelScEofReached;
}
else
{
aReadBuffer->SetLength(bytesToRead);
aReadBuffer->FillZ();
TInt index;
for(index = 0; index < bytesToRead; index++)
{
(*aReadBuffer)[index] = iFileData[filePointer];
filePointer++;
}
return KErrNone;
}
}
TInt CSimPhoneSmartCardApp::TTransparentSmartCardFile::UpdateFile(
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aWriteBuffer)
/**
* Concrete implementation of the UpdateFile() method for updating data in a binary transparent
* smart card file.
*
* @param aFilePathOffsets Information about which file to update (path) and where in the file to write data to (offsets)
* @param aReadBuffer The data with which the file should be updated.
*/
{
const TInt& bytesToWrite = aFilePathOffsets.iCount;
TInt filePointer = aFilePathOffsets.iStartOffset;
TInt index;
//check that the client has provided a buffer of sufficient size
if(aWriteBuffer->Size() != bytesToWrite)
{
//The length of the provided buffer does not match the number of bytes that client has requested
//should be updated in the file.
return KErrArgument;
}
//check that the client has specified a valid start offset
else if(aFilePathOffsets.iStartOffset >= (TUint)iTotalLength)
{
LOGPHONE1("ERROR: File start offset information invalid.");
return KErrMMEtelScReferencedDataNotFound;
}
//check the client is not requesting to write too many bytes, resulting in writing
//off the end of the file
else if((bytesToWrite + filePointer) > iTotalLength)
{
LOGPHONE1("ERROR: Path offset information results in reading off the end of the file");
return KErrMMEtelScEofReached;
}
else
{
for(index = 0; index < bytesToWrite; index++)
{
iFileData[filePointer] = (*aWriteBuffer)[index];
filePointer++;
}
return KErrNone;
}
}
RMobilePhone::TAID CSimPhoneSmartCardApp::GetActiveUSim()
/**
* Returns the active aid (internally)
*
*/
{
return iActiveUSimApp;
}
TInt CSimPhoneSmartCardApp::GetCurrentActiveUSimApplication(const TTsyReqHandle aTsyReqHandle, RMobilePhone::TAID* aAID)
/**
* Returns the active aid
*
* @param aReqHandle The TSY request handle for this request.
* @param aAID Returns the AID of the Active USim Application
* @return KErrNone
*/
{
if(iActiveUSimApp.Size() == 0)
{
iPhone->ReqCompleted(aTsyReqHandle, KErrMMEtelScApplicationNotActive);
}
else
{
*aAID=iActiveUSimApp;
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
}
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetCurrentActiveUSimApplicationCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending GetActiveUSimApplication request (unsuccessfully)
*
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::EnumerateUSimApplications(TTsyReqHandle aTsyReqHandle, TInt* aCount, RMobilePhone::TAID* aActiveAID)
/**
* Enumerates the number of USim applications in the UICC and returns the
* AID of the active application.
*
* @param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
* @param aCount Returns the number of USim applications.
* @param aActiveAID Returns the AID of the currently active application.
* @return KErrNone.
*/
{
*aCount=iUSimAppList->Count();
aActiveAID->Copy(iActiveUSimApp);
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::EnumerateUSimApplicationsCancel(TTsyReqHandle aTsyReqHandle)
/**
*Attempts to cancel a pending EnumerateUSimApplications request (unsuccesfully).
*
*@param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetUSimApplicationInfo(TTsyReqHandle aTsyReqHandle, TInt* aUSimAppIndex, TDes8* aInfo)
/**
* Retrieves information for a specified USim application
*
* @param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
* @param aUSimAppIndex Used to specify the index of the application.
* @param aInfo Returns the information of the specified appplication.
* @return KErrNone.
*/
{
if(*aUSimAppIndex>=iUSimAppList->Count())
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNotFound);
return KErrNone;
}
else
{
TPckg<RMobilePhone::TUSimApplicationInfoV2>* infoPckg =
(TPckg<RMobilePhone::TUSimApplicationInfoV2>*)aInfo;
RMobilePhone::TUSimApplicationInfoV2& info = (*infoPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(info);
if(err != KErrNone)
{
iPhone->ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
info.iAID = (*iUSimAppList)[*aUSimAppIndex]->iAID;
info.iLabel = (*iUSimAppList)[*aUSimAppIndex]->iLabel;
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
}
return KErrNone;
}
/**
Attempts to cancel a pending GetUSimApplicationInfo request
(unsuccesfully).
@param aTsyReqHandle A handle belonging to the client that created the
session with this TSY server.
*/
TInt CSimPhoneSmartCardApp::GetUSimApplicationInfoCancel(TTsyReqHandle aTsyReqHandle)
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::SetUSimApplicationStatus(TTsyReqHandle aTsyReqHandle, RMobilePhone::TAID* aAID, RMobilePhone::TUSimAppAction* aUsimAppAction)
/**
* Attempts to set the status of a specific USim application.
*
* @param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
* @param aAID The specific application's ID whose status is to be set.
* @param aUsimAppAction The status to apply to the application identified
* by aAID.
* @return KErrNone on completion of request, unless the aAID given is not
* identifiable, in which case KErrArgument is returned.
*/
{
TInt ret;
RMobilePhone::TAID aAidToAction;
RMobilePhone::TSmartCardApplicationEvent aScEvent;
TBool isUSimAppAffected = EFalse;
//if the request is to activate a USimApp
if(*aUsimAppAction == RMobilePhone::EUSimActivate)
{
//if another USimApp is active.
if(iActiveUSimApp.Size() != 0)
{
//terminate active USimApp
aAidToAction = iActiveUSimApp;
aScEvent = RMobilePhone::EScApplicationTerminated;
isUSimAppAffected = EFalse;
ret = TerminateSmartCardApp(aAidToAction, isUSimAppAffected);
//if No error terminating
if (ret == KErrNone)
{
//notify ScApp client if notify request is pending
if(iNotifyScInfo.iNotifyPending)
{
*(RMobilePhone::TAID*)iNotifyScInfo.iNotifyData1=aAidToAction;
*(RMobilePhone::TSmartCardApplicationEvent*)iNotifyScInfo.iNotifyData2=aScEvent;
iNotifyScInfo.iNotifyPending=EFalse;
iPhone->ReqCompleted(iNotifyScInfo.iNotifyHandle,KErrNone);
}
}
}//end if(iActiveUSimApp.Size() != 0)
//activate the requested application
aAidToAction = *aAID;
aScEvent = RMobilePhone::EScApplicationActivated;
isUSimAppAffected = EFalse;
ret=ActivateSmartCardApp(*aAID, isUSimAppAffected);
//if no error activating
if (ret == KErrNone)
{
//notify any ScApp client if such notify request is pending
if(iNotifyScInfo.iNotifyPending)
{
iNotifyScInfo.iNotifyPending=EFalse;
*(RMobilePhone::TAID*)iNotifyScInfo.iNotifyData1=aAidToAction;
*(RMobilePhone::TSmartCardApplicationEvent*)iNotifyScInfo.iNotifyData2=aScEvent;
iPhone->ReqCompleted(iNotifyScInfo.iNotifyHandle,KErrNone);
}
//notify any USimApp client if such notify request is pending
if(iNotifyUSimInfo.iNotifyPending)
{
iNotifyUSimInfo.iNotifyPending=EFalse;
*(RMobilePhone::TAID*)iNotifyUSimInfo.iNotifyData1=aAidToAction;
*(TInt*)iNotifyUSimInfo.iNotifyData2=iUSimAppList->Count();
iPhone->ReqCompleted(iNotifyUSimInfo.iNotifyHandle,KErrNone);
}
}
//complete requests and return
iPhone->ReqCompleted(aTsyReqHandle,ret);
return KErrNone;
}
else
{
//the request is to terminate a USimApp
aAidToAction = *aAID;
aScEvent = RMobilePhone::EScApplicationTerminated;
//terminate active USimApp
isUSimAppAffected = EFalse;
ret = TerminateSmartCardApp(aAidToAction, isUSimAppAffected);
//if No error terminating
if (ret == KErrNone)
{
//notify ScApp client if such notify request is pending
if(iNotifyScInfo.iNotifyPending)
{
*(RMobilePhone::TAID*)iNotifyScInfo.iNotifyData1=aAidToAction;
*(RMobilePhone::TSmartCardApplicationEvent*)iNotifyScInfo.iNotifyData2=aScEvent;
iNotifyScInfo.iNotifyPending=EFalse;
iPhone->ReqCompleted(iNotifyScInfo.iNotifyHandle,KErrNone);
}
//notify any USimApp client if such notify request is pending
if(iNotifyUSimInfo.iNotifyPending)
{
*(RMobilePhone::TAID*)iNotifyUSimInfo.iNotifyData1=_L8("");
*(TInt*)iNotifyUSimInfo.iNotifyData2=iUSimAppList->Count();
iNotifyUSimInfo.iNotifyPending=EFalse;
iPhone->ReqCompleted(iNotifyUSimInfo.iNotifyHandle,KErrNone);
}
}
//complete requests and return
iPhone->ReqCompleted(aTsyReqHandle,ret);
return KErrNone;
}
}
TInt CSimPhoneSmartCardApp::SetUSimApplicationStatusCancel(TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending SetUSimApplicationStatus request (unsuccesfully).
*
* @param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
* @return KErrNone.
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::NotifyUSimApplicationsInfoChange(const TTsyReqHandle aTsyReqHandle, TInt* aCount, RMobilePhone::TAID* aActiveAID)
/**
* Notifies the client when the specified USim application's information
* changes.
*
* @param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
* @param aCount Returns the total number of USim applications when the
* request completes.
* @param aActiveAID The application's AID whose infromation change will
* be notified to the client.
* @return KErrNone.
*/
{
__ASSERT_ALWAYS(!iNotifyUSimInfo.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
TInt count=iSmartCardAppEventList->Count();
if(iEventPointer<count)
{
if(iTimerStarted)
{
delete iTimer;
iTimer = NULL;
TRAP_IGNORE(iTimer=CSimTimer::NewL(iPhone));
}
TSmartCardAppEvent event=iSmartCardAppEventList->At(iEventPointer);
if (iTimer != NULL)
{
iTimer->Start(event.iDuration,this);
iTimerStarted = ETrue;
}
}
iNotifyUSimInfo.iNotifyPending=ETrue;
iNotifyUSimInfo.iNotifyHandle=aTsyReqHandle;
iNotifyUSimInfo.iNotifyData1=aActiveAID;
iNotifyUSimInfo.iNotifyData2=aCount;
return KErrNone;
}
/**
*Attempts to cancel a pending NotifyUSimApplicationsInfoChange request.
*
*@param aTsyReqHandle A handle belonging to the client that created the
* session with this TSY server.
*@param KErrNone
*/
TInt CSimPhoneSmartCardApp::NotifyUSimApplicationsInfoChangeCancel(TTsyReqHandle aTsyReqHandle)
{
if(iNotifyUSimInfo.iNotifyPending)
{
iNotifyUSimInfo.iNotifyPending=EFalse;
iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
}
return KErrNone;
}
TInt CSimPhoneSmartCardApp::EnumerateScApplications(const TTsyReqHandle aTsyReqHandle, TUint* aCount)
/**
* Enumerates the number of Smart Card applications on the UICC
*
* @param aReqHandle The TSY request handle for this request
* @param aCount Returns the number of Smart Card applications
* @return KErrNone
*/
{
*aCount=iSmartCardAppList->Count();
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::EnumerateScApplicationsCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending EnumerateUSimApplications request (unsuccessfully)
*
* @param aReqHandle The TSY request handle for this request
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetScApplicationInfo(const TTsyReqHandle aTsyReqHandle, TInt* aAppIndex, TDes8* aInfo)
/**
* Retrieves information for a specified Smart Card application
*
* @param aReqHandle The TSY request handle for this request
* @param aAppIndex is used to specify the index of the application
* @param aInfo Returns the information of the specified appplication
* @return KErrNone
*/
{
if(*aAppIndex>=iSmartCardAppList->Count())
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNotFound);
}
else
{
TPckg<RMobilePhone::TSmartCardApplicationInfoV5>* infoPckg =
(TPckg<RMobilePhone::TSmartCardApplicationInfoV5>*)aInfo;
RMobilePhone::TSmartCardApplicationInfoV5& info = (*infoPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(info);
if(err != KErrNone)
{
iPhone->ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
info.iAID=iSmartCardAppList->At(*aAppIndex).iAID;
info.iLabel=iSmartCardAppList->At(*aAppIndex).iLabel;
if (info.ExtensionId() == KEtelExtMultimodeV6)
{
RMobilePhone::TUiccApplicationEapInfoV6& withEapInfo = static_cast<RMobilePhone::TUiccApplicationEapInfoV6&>(info);
withEapInfo.iEapTypeList = iSmartCardAppList->At(*aAppIndex).iEapList;
}
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
}
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetScApplicationInfoCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending GetScApplicationInfo request (unsuccessfully)
*
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::NotifyScApplicationInfoChange(const TTsyReqHandle aTsyReqHandle,
RMobilePhone::TAID* aAID, RMobilePhone::TSmartCardApplicationEvent* aEvent)
/**
* Notifies of any Smart Card application information changes
*
* @param aReqHandle The TSY request handle for this request
* @param aAID Return the AID of the application whose status has changed
* @param aEvent Return the event that took place on application aAID
* @return KErrNone
*/
{
__ASSERT_ALWAYS(!iNotifyScInfo.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
TInt count=iSmartCardAppEventList->Count();
if(iEventPointer<count)
{
if(iTimerStarted)
{
delete iTimer;
iTimer = NULL;
TRAP_IGNORE(iTimer=CSimTimer::NewL(iPhone));
}
TSmartCardAppEvent event=iSmartCardAppEventList->At(iEventPointer);
if (iTimer != NULL)
{
iTimer->Start(event.iDuration,this);
iTimerStarted = ETrue;
}
}
iNotifyScInfo.iNotifyPending=ETrue;
iNotifyScInfo.iNotifyHandle=aTsyReqHandle;
iNotifyScInfo.iNotifyData1=aAID;
iNotifyScInfo.iNotifyData2=aEvent;
return KErrNone;
}
TInt CSimPhoneSmartCardApp::NotifyScApplicationInfoChangeCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending NotifyUSimApplicationsInfoChange request
*
*/
{
if(iNotifyScInfo.iNotifyPending)
{
iNotifyScInfo.iNotifyPending=EFalse;
iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
}
return KErrNone;
}
TInt CSimPhoneSmartCardApp::SetScApplicationStatus(const TTsyReqHandle aTsyReqHandle, RMobilePhone::TAID* aAID, RMobilePhone::TSmartCardApplicationAction* aAction)
/**
* Sets the Application Status for specified smart card application
*
* @param aReqHandle The TSY request handle for this request
* @param aAID The AID of the application whose status should be changed
* @param aAction The action that should take place on the specified application
* @return KErrNone
*/
{
TInt ret;
RMobilePhone::TSmartCardApplicationEvent event;
TBool isUSimAppAffected = EFalse;
if(*aAction==RMobilePhone::EScApplicationActivate)
{
event=RMobilePhone::EScApplicationActivated;
ret=ActivateSmartCardApp(*aAID, isUSimAppAffected);
}
else
{
event=RMobilePhone::EScApplicationTerminated;
ret=TerminateSmartCardApp(*aAID, isUSimAppAffected);
}
if(ret==KErrNone)
{
if(iNotifyScInfo.iNotifyPending)
{
iNotifyScInfo.iNotifyPending=EFalse;
*(RMobilePhone::TAID*)iNotifyScInfo.iNotifyData1=*aAID;
*(RMobilePhone::TSmartCardApplicationEvent*)iNotifyScInfo.iNotifyData2=event;
iPhone->ReqCompleted(iNotifyScInfo.iNotifyHandle,KErrNone);
}
//If the affected ScApp is a USimApp...
//notify any USimApp client if such notify request is pending
if(isUSimAppAffected && iNotifyUSimInfo.iNotifyPending)
{
iNotifyUSimInfo.iNotifyPending=EFalse;
if(event == RMobilePhone::EScApplicationActivated)
{
*(RMobilePhone::TAID*)iNotifyUSimInfo.iNotifyData1=*aAID;
}
else
{
*(RMobilePhone::TAID*)iNotifyUSimInfo.iNotifyData1=_L8("");
}
*(TInt*)iNotifyUSimInfo.iNotifyData2=iUSimAppList->Count();
iPhone->ReqCompleted(iNotifyUSimInfo.iNotifyHandle,KErrNone);
}
}
iPhone->ReqCompleted(aTsyReqHandle,ret);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::SetScApplicationStatusCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending SetScApplicationStatus request (unsuccessfully)
*
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::SetUSimAppsSelectionMode(TTsyReqHandle aTsyReqHandle, RMobilePhone::TUSimSelectionMode* aUSimSelectionMode)
/**
* Sets the Selection mode for USim applications
*
* @param aReqHandle The TSY request handle for this request
* @param aUSimSelectionMode is used to specify the new selection mode for applications
* @return KErrNone
*/
{
iCurrentSelection=*aUSimSelectionMode;
if(iNotifyMode.iNotifyPending)
{
iNotifyMode.iNotifyPending=EFalse;
*(RMobilePhone::TUSimSelectionMode*)iNotifyMode.iNotifyData=iCurrentSelection;
iPhone->ReqCompleted(iNotifyMode.iNotifyHandle,KErrNone);
}
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::SetUSimAppsSelectionModeCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending SetUSimAppsSelectionMode request (unsuccessfully)
*
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetUSimAppsSelectionMode(TTsyReqHandle aTsyReqHandle, RMobilePhone::TUSimSelectionMode* aUSimSelectionMode)
/**
* Gets the Selection mode for USim applications
*
* @param aReqHandle The TSY request handle for this request
* @param aUSimSelectionMode Returns the selection mode for applications
* @return KErrNone
*/
{
*aUSimSelectionMode=iCurrentSelection;
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetUSimAppsSelectionModeCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending GetUSimAppsSelectionMode request (unsuccessfully)
*
*/
{
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::NotifyUSIMAppsSelectionModeChange(TTsyReqHandle aTsyReqHandle, RMobilePhone::TUSimSelectionMode* aUSimSelectionMode)
/**
* Notifies for any Selection mode changes for USim applications
*
* @param aReqHandle The TSY request handle for this request
* @param aUSimSelectionMode Returns the new selection mode for applications
* @return KErrNone
*/
{
__ASSERT_ALWAYS(!iNotifyMode.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
iNotifyMode.iNotifyPending=ETrue;
iNotifyMode.iNotifyHandle=aTsyReqHandle;
iNotifyMode.iNotifyData=aUSimSelectionMode;
return KErrNone;
}
TInt CSimPhoneSmartCardApp::NotifyUSIMAppsSelectionModeChangeCancel(TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending NotifyUSIMAppsSelectionModeChange request
*
*/
{
if(iNotifyMode.iNotifyPending)
{
iNotifyMode.iNotifyPending=EFalse;
iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
}
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetScFileInfo(const TTsyReqHandle aTsyReqHandle,
const RMobilePhone::TScFilePath& aFilePathId, TDes8* aInfo)
/**
* Gets information about the specified smart card file
*
* @param aReqHandle The TSY request handle for this request
* @param aFilePathId Used to specify path of the file for which information should be retrieved
* @param aInfo Used to return the retrieved file information
*/
{
LOGPHONE1("CSimPhoneSmartCardApp::GetScFileInfo called");
RMobilePhone::TScFileInfoV5Pckg *scFileInfoPckg = reinterpret_cast<RMobilePhone::TScFileInfoV5Pckg*>(aInfo);
RMobilePhone::TScFileInfoV5 &scFileInfo = (*scFileInfoPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(scFileInfo);
if(err != KErrNone)
{
iPhone->ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
if(scFileInfo.ExtensionId() == KEtelExtMultimodeV5)
{
TSmartCardFile* scFile = NULL;
TInt ret = FindScFile(aFilePathId, scFile);
if(ret==KErrNone)
{
scFile->GetFileInfo(scFileInfo);
iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
}
else
{
iPhone->ReqCompleted(aTsyReqHandle,ret);
}
}
else
{
iPhone->ReqCompleted(aTsyReqHandle,KErrCorrupt);
}
return KErrNone;
}
TInt CSimPhoneSmartCardApp::GetScFileInfoCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending GetScFileInfo request (unsuccessfully)
*
*/
{
LOGPHONE1("CSimPhoneSmartCardApp::GetScFileInfoCancel called");
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::ReadScFile(const TTsyReqHandle aTsyReqHandle,
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aReadBuffer)
/**
* Reads a specified amount of data from a specified smart card file
*
* @param aReqHandle The TSY request handle for this request
* @param aFilePathOffsets Used to specify which file to read (path) and where in the file to read data from (offsets)
* @param aReadBuffer Used to return the read file data
*/
{
TSmartCardFile* scFile = NULL;
TInt ret = FindScFile((RMobilePhone::TScFilePath)aFilePathOffsets, scFile);
if(ret==KErrNone)
{
ret = scFile->ReadFile(aFilePathOffsets, aReadBuffer);
}
iPhone->ReqCompleted(aTsyReqHandle,ret);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::ReadScFileCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending ReadScFileInfo request (unsuccessfully)
*
*/
{
LOGPHONE1("CSimPhoneSmartCardApp::ReadScFileInfoCancel called");
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::UpdateScFile(const TTsyReqHandle aTsyReqHandle,
const RMobilePhone::TScFilePathWithAccessOffsets& aFilePathOffsets, TDes8* aWriteBuffer)
/**
* Writes a specified amount of data to a specified smart card file
*
* @param aReqHandle The TSY request handle for this request
* @param aFilePathOffsets Used to specify which file to update (path) and where in the file to write data to (offsets)
* @param aReadBuffer Used to return the read file data
*/
{
TSmartCardFile* scFile = NULL;
TInt ret = FindScFile((RMobilePhone::TScFilePath)aFilePathOffsets, scFile);
if(ret==KErrNone)
{
ret = scFile->UpdateFile(aFilePathOffsets, aWriteBuffer);
}
iPhone->ReqCompleted(aTsyReqHandle,ret);
return KErrNone;
}
TInt CSimPhoneSmartCardApp::UpdateScFileCancel(const TTsyReqHandle aTsyReqHandle)
/**
* Attempts to cancel a pending UpdateScFileInfo request (unsuccessfully)
*
*/
{
LOGPHONE1("CSimPhoneSmartCardApp::UpdateScFileInfoCancel called");
iPhone->ReqCompleted(aTsyReqHandle, KErrNone);
return KErrNone;
}
void CSimPhoneSmartCardApp::ParseSmartCardApplicationInfoL()
/**
* Parses all Smart Card Application related tags from the config file
*
*/
{
const CTestConfigItem* item=NULL;
TInt ret=KErrNone;
TInt index;
TPtrC8 activeUSimApp, aid, label, eap;
TInt type;
TSmartCardApplication appInfo;
TRAP_IGNORE(iTimer=CSimTimer::NewL(iPhone));
LOGPHONE1("Starting to Parse MaxActiveSmartCardApp Info");
iMaxActiveSmartCardApps = CfgFile()->ItemValue(KMaxActiveSmartCardApps ,KDefaultMaxActiveSmartCardApps);
LOGPHONE1("Starting to Parse ActiveUSIMApp Info");
activeUSimApp.Set(CfgFile()->ItemValue(KActiveUSIMApp, KEmptyString));
if(activeUSimApp.Length() == 0)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: ACTIVE USIM APP NOT SPECIFIED!");
}
TInt count = CfgFile()->ItemCount(KSmartCardAppInfo);
iSmartCardAppList=new(ELeave) CArrayFixFlat<TSmartCardApplication>(count+1);
LOGPHONE1("Starting to Load and Parse Smart Card Application Info");
for(index=0;index<count;index++)
{
item=CfgFile()->Item(KSmartCardAppInfo,index);
if(!item)
{
break;
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,aid);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD APP INFO TAG");
continue;
}
else
{
appInfo.iAID.Copy(aid);
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,label);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD APP INFO TAG");
continue;
}
else
{
appInfo.iLabel.Copy(label);
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,type);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD APP INFO TAG");
continue;
}
else
{
appInfo.iAppType = (TSmartCardAppType)type;
}
if((appInfo.iAppType == EUSimApp) && (appInfo.iAID == activeUSimApp))
{
//Make this the active USim App
iActiveUSimApp = appInfo.iAID;
appInfo.iAppStatus = EActive;
iNumActiveSmartCardApps++;
}
else
{
appInfo.iAppStatus = EInactive;
}
ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 3, eap);
if (ret != KErrNone)
{
LOGPHONE2("CONFIGURATION FILE PARSING: BAD OR NO (OPTIONAL) EAP LIST @ SMARTCARD APP INFO TAG [%d]", index);
_LIT8(emptyEapList, "");
eap.Set(emptyEapList);
}
// Append empty string if no info is given
appInfo.iEapList.Copy(eap);
iSmartCardAppList->AppendL(appInfo);
iFoundScAppTags = ETrue;
}//end of FOR loop
if(iActiveUSimApp.Length() == 0)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: AID FOR ACTIVE USIM APP NOT FOUND!");
}
count=CfgFile()->ItemCount(KSmartCardAppEvent);
iSmartCardAppEventList=new(ELeave) CArrayFixFlat<TSmartCardAppEvent>(count+1);
TSmartCardAppEvent appEvent;
TInt duration, action;
LOGPHONE1("Starting to Load and Parse Smart Card Application Event Info");
for(index=0;index<count;index++)
{
item=CfgFile()->Item(KSmartCardAppEvent,index);
if(!item)
{
break;
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0, duration);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMART CARD APP EVENT TAG");
continue;
}
else
{
appEvent.iDuration=duration;
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1, aid);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING; BAD SMART CARD APP EVENT TAG");
continue;
}
else
{
appEvent.iAID.Copy(aid);
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2, action);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING; BAD SMART CARD APP EVENT TAG");
continue;
}
else
{
appEvent.iAction = (RMobilePhone::TSmartCardApplicationAction)action;
}
iSmartCardAppEventList->AppendL(appEvent);
}//end FOR loop
}
void CSimPhoneSmartCardApp::ParseSmartCardFileInfoL()
/**
* Parses all Smart Card File related tags from the config file
*
*/
{
const CTestConfigItem* item=NULL;
TInt ret=KErrNone;
TPtrC8 fileId, filePath, fileData;
TInt aidIndex, fileType, fileLength, recordLength, numRecords, index;
TSmartCardFile* file = NULL;
LOGPHONE1("Starting to Parse Smart Card File Info");
TInt count = CfgFile()->ItemCount(KSmartCardFile);
iSmartCardFileList = new(ELeave) CArrayPtrFlat<TSmartCardFile>(count+1);
for(index=0;index<count;index++)
{
item=CfgFile()->Item(KSmartCardFile,index);
if(!item)
{
break;
}
//Get the file's type information
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,fileType);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
continue;
}
else
{
switch ((RMobilePhone::TScFileType)fileType)
{
case RMobilePhone::ELinearFixed:
file = new(ELeave) TLinearSmartCardFile;
break;
case RMobilePhone::ECyclic:
file = new(ELeave) TCyclicSmartCardFile;
break;
case RMobilePhone::ETransparent:
file = new(ELeave) TTransparentSmartCardFile;
break;
default:
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING:");
LOGPHONE1("ENCOUNTERED UNKNOWN SMART CARD FILE TYPE.");
continue;
}
file->iType = (RMobilePhone::TScFileType)fileType;
}
//Get the FID of the file
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,fileId);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
//check that the FID is precisely 4 bytes long
else if(fileId.Length() != KMaxHexFIDLen)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE FID");
delete file;
continue;
}
else
{
TBuf8<KMaxBinFIDLen> fileIdBuffer;
TextToBin(fileId, fileIdBuffer);
file->iFileID = (RMobilePhone::TScFileID)((fileIdBuffer[0] <<8) + (fileIdBuffer[1]));
}
//Get the Index of the AID of the application the file belongs to
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,aidIndex);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
else
{
file->iAIDIndex = aidIndex;
}
//Get the file's path information
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,filePath);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
else
{
file->iPath = filePath;
}
//Get the information about the total length of the file
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,fileLength);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
else
{
file->iTotalLength = fileLength;
}
//Get information about the length of each record in the file
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,5,recordLength);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
else
{
file->iRecordLength = recordLength;
}
//Get information about the number of records in the file
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,6,numRecords);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
else
{
file->iNumberRecords = numRecords;
}
//If the file is Cyclic or Linear record based file...
//Check that record Length * number of records = Total length of file
if((fileType != RMobilePhone::ETransparent) && ((recordLength*numRecords) != fileLength))
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING:...");
LOGPHONE1("...Record Length * Number of Records != File Length");
delete file;
continue;
}
//Get file data
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,7,fileData);
if(ret!=KErrNone)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE TAG");
delete file;
continue;
}
else if((fileData.Length() % 2 ) != 0)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING: BAD SMARTCARD FILE DATA");
continue;
}
else
{
TBuf8<KMaxFileSize> fileDataBuffer;
TextToBin(fileData, fileDataBuffer);
if(fileDataBuffer.Length() != fileLength)
{
LOGPHONE1("ERROR IN CONFIGURATION FILE PARSING:INCONSISTANT DATA FILE LENGTH");
delete file;
continue;
}
file->iFileData = fileDataBuffer;
}
iSmartCardFileList->AppendL(file);
}//end FOR Loop
}
void CSimPhoneSmartCardApp::MapUSimAppsL()
{
iUSimAppList=new(ELeave) RPointerArray<TSmartCardApplication>(iSmartCardAppList->Count() + 1);
TInt index;
TSmartCardApplication* SmartCardApp = NULL;
//iterate through the list of smart card applications
for(index=0; index < iSmartCardAppList->Count(); index++)
{
SmartCardApp = &(iSmartCardAppList->At(index));
//if the smart card application is a USim App
if(SmartCardApp->iAppType == EUSimApp)
{
//add a pointer to it in the list of USim Apps
iUSimAppList->AppendL(SmartCardApp);
}
}//end FOR loop
}
TInt CSimPhoneSmartCardApp::FindScFile(const RMobilePhone::TScFilePath& aFilePathInfo, TSmartCardFile*& aSmartCardFile)
/**
* Helper function
*
* Searches through the SimTSYs internal list of Smart Card files and returns a pointer
* to the requested file. If the file is under an application a check is done to ensure
* the application is active.
*
* @param aFilePathInfo Some information about the file that the client is looking for
* @param aSmartCardFile A pointer to the Smart Card File the client was looking for
*/
{
TInt index;
TInt aidIndex = KNoAID;
//If the user has specified a file that is under an application
if(aFilePathInfo.iAID.Size() != 0)
{
//search the list of Smart Card Applications and get an index for the specifed AID
for(index=0; index < iSmartCardAppList->Count(); index++)
{
if(iSmartCardAppList->At(index).iAID == aFilePathInfo.iAID)
{
aidIndex = index;
break;
}
}
//if the AID is not found
if(aidIndex == KNoAID)
{
return KErrNotFound;
}
else
{
//return an error if the specified application is inactive
if(iSmartCardAppList->At(aidIndex).iAppStatus == EInactive)
{
return KErrMMEtelScApplicationNotActive;
}
}
}//end if(aFilePathInfo.iAID.Size() != 0)
//Find the specified file
TSmartCardFile* scFile=NULL;
for(index = 0; index < iSmartCardFileList->Count(); index++)
{
scFile = iSmartCardFileList->At(index);
if((scFile->iAIDIndex == aidIndex) && (scFile->iPath == aFilePathInfo.iPath))
{
aSmartCardFile = scFile;
return KErrNone;
}
}
return KErrMMEtelScFileNotFound;
}
TInt CSimPhoneSmartCardApp::ActivateSmartCardApp(const RMobilePhone::TAID aAID, TBool& aActivatedUSimApp)
/**
* Performs the logic for Activating a Smart Card application
*
* @param aAID The AID of the application that should be activated
*/
{
TInt index;
TSmartCardApplication* smartCardApp = NULL;
for(index=0; index < iSmartCardAppList->Count(); index++)
{
smartCardApp = &(iSmartCardAppList->At(index));
if(smartCardApp->iAID == aAID)
{
//Check that 1)iMaxActiveSmartCardApps will not be exceeded by activating
//a new smart card application; 2)The application is not already active
if((iNumActiveSmartCardApps<iMaxActiveSmartCardApps) &&
(smartCardApp->iAppStatus != CSimPhoneSmartCardApp::EActive))
{
//if we are activating a USIM and another USIM app is already active,
//fail with KErrAlreadyExists
if((smartCardApp->iAppType == CSimPhoneSmartCardApp::EUSimApp) &&
(iActiveUSimApp.Length() != 0))
{
return KErrAlreadyExists;
}
else
{
smartCardApp->iAppStatus = CSimPhoneSmartCardApp::EActive;
iNumActiveSmartCardApps++;
if(smartCardApp->iAppType == CSimPhoneSmartCardApp::EUSimApp)
{
iActiveUSimApp = smartCardApp->iAID;
aActivatedUSimApp = ETrue;
}
return KErrNone;
}
}
else
{
if(smartCardApp->iAppStatus == CSimPhoneSmartCardApp::EActive)
{
LOGPHONE1("REACTIVATING AN ALREADY ACTIVE APPLICATION");
return KErrNone;
}
else
{
//iMaxActiveSmartCardApps will be exceeded
LOGPHONE1("WARNING: CANNOT PROCESS ACTIVATING APPLICATION");
return KErrMMEtelScMaxApplicationsActive;
}
}
}
}//end for loop
LOGPHONE1("WARNING: AID NOT FOUND. CANNOT PROCESS EVENT");
return KErrNotFound;
}
TInt CSimPhoneSmartCardApp::TerminateSmartCardApp(const RMobilePhone::TAID aAID, TBool& aTerminatedUSimApp)
/**
* Performs the logic for terminating a Smart Card application
*
* @param aAID The AID of the application that should be terminated
*/
{
TInt index;
TSmartCardApplication* smartCardApp = NULL;
for(index=0; index < iSmartCardAppList->Count(); index++)
{
smartCardApp = &(iSmartCardAppList->At(index));
if(smartCardApp->iAID == aAID)
{
if(smartCardApp->iAppStatus == CSimPhoneSmartCardApp::EActive)
{
smartCardApp->iAppStatus = CSimPhoneSmartCardApp::EInactive;
iNumActiveSmartCardApps--;
if(smartCardApp->iAppType == CSimPhoneSmartCardApp::EUSimApp)
{
iActiveUSimApp.Zero();
aTerminatedUSimApp = ETrue;
}
return KErrNone;
}
else
{
LOGPHONE1("ATTEMPTED TO TERMINATE NON-ACTIVE APPLICATION");
return KErrMMEtelScApplicationNotActive;
}
}
}//end for loop
LOGPHONE1("WARNING: AID NOT FOUND. CANNOT PROCESS EVENT");
return KErrNotFound;
}
void CSimPhoneSmartCardApp::TextToBin(const TDesC8& aSrc, TDes8& aDst)
/**
* Helper function
*
* Converts a text descriptor containing Hex information to binary.
*
* @param aSrc The input buffer
* @param aDst The output buffer
*/
{
//LOG_ASSERT((aSrc.Length() % 2) == 0, "Not passed in an even-length string?");
aDst.SetLength(aSrc.Length() / 2);
for (TInt i = 0; i < aSrc.Length(); i += 2)
{
TInt val = 0;
if ((aSrc[i] >= '0') && (aSrc[i] <= '9'))
{
val = ((aSrc[i] - '0') << 4);
}
else if ((aSrc[i] >= 'A') && (aSrc[i] <= 'F'))
{
val = ((aSrc[i] - 'A' + 10) << 4);
}
else
{
__DEBUGGER();
}
if ((aSrc[i+1] >= '0') && (aSrc[i+1] <= '9'))
{
val += (aSrc[i+1] - '0');
}
else if ((aSrc[i+1] >= 'A') && (aSrc[i+1] <= 'F'))
{
val += (aSrc[i+1] - 'A' + 10);
}
else
{
__DEBUGGER();
}
aDst[i/2] = (TUint8) val;
}
}