diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/multimodetsy/Multimode/mPHBKCOM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/multimodetsy/Multimode/mPHBKCOM.CPP Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,708 @@ +// Copyright (c) 1997-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: +// Multimode TSY Phone book Implementation file. +// This file contains the implementation of the CATPhoneBookCommands, CATPhoneBookInit, +// CATPhoneBookWrite and CATPhoneBookDelete classes. +// +// + +/** + @file +*/ + +#include "Mphbkcom.h" +#include "mSLOGGER.H" +#include "mPHBOOK.H" +#include "NOTIFY.H" +#include "ATIO.H" +#include "Matstd.h" + +// AT commands + +_LIT8(KPhoneBookReadAll,"AT+CPBR="); // Modified from "AT+CPBR=1,n; 1 is not always the starting index +_LIT8(KPhoneBookReadResponse,"+CPBR:*"); + +_LIT8(KPhoneBookWriteWithIndex,"AT+CPBW=%d,\"%S\",%d,\"%S\""); +_LIT8(KPhoneBookWriteWithIndexPrependedPlus,"AT+CPBW=%d,\"+%S\",%d,\"%S\""); +_LIT8(KPhoneBookDelete,"AT+CPBW=%d"); +_LIT8(KPhoneBookAlternativeDelete,"AT+CPBW=%d,\"\",,\"\""); + + +const TInt KPhoneBookTimeForExtraRxData=100; + +// Time-outs + +const TInt KPhoneBookReadTimeout=30; //< Time-out used when reading the phone books (in seconds). For sizeable phonebooks, this can be large. + //< The Siemens S25 is the slowest phone observed. The Nokia 8210 can take 14s to read an empty 200 entry phonebook. + +// +// CATPhoneBookCommands definitions +// + +CATPhoneBookCommands::CATPhoneBookCommands(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals) + : CATCommands(aIo,aTelObject,aInit,aPhoneGlobals), iState(EATPhoneBookCommandIdle) + {} + +CATPhoneBookCommands::~CATPhoneBookCommands() +/** + * Destructor. + */ + { + iIo->RemoveExpectStrings(this); + } + +void CATPhoneBookCommands::EventSignal(TEventSource aEventSource) +/** + * This function contains the State machine for the phonebook commands whose classes + * inherit from the CATPhoneBookCommands class. + * + * Note: The cases EATPhoneBookCommandWaitForReadComplete & EATPhoneBookCommandWait- + * ForAlternativeReadComplete are overriden by similar cases in CATPhoneBookInit:: + * EventSignal and CATPhoneBookRead::EventSignal. + */ + { + if (aEventSource==ETimeOutCompletion && iState!=EATPhoneBookCommandExtendedRead) + { + LOGTEXT(_L8("Timeout Error during phone book command")); + RemoveStdExpectStrings(); + Complete(KErrTimedOut,aEventSource); + return; + } + + TInt ret=KErrNone; + switch (iState) + { + case EATPhoneBookStorageSelectWaitForWriteComplete: + __ASSERT_ALWAYS(aEventSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected)); + AddStdExpectStrings(); + iIo->SetTimeOut(this); + iState=EATPhoneBookStorageSelectWaitForReadComplete; + return; + + case EATPhoneBookStorageSelectWaitForReadComplete: + __ASSERT_ALWAYS(aEventSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected)); + { + ret=ValidateExpectString(); + RemoveStdExpectStrings(); + if (ret!=KErrNone) + { + Complete(ret,aEventSource); + return; + } + CMobilePhonebookStore* phoneBook=REINTERPRET_CAST(CMobilePhonebookStore*,iTelObject); + iPhoneGlobals->iPhoneStatus.iLastAccessedPhoneBook=phoneBook->StorageType(); + } + StartThisCommand(); + return; + + case EATPhoneBookCommandWaitForWriteComplete: + __ASSERT_ALWAYS(aEventSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected)); + iIo->SetTimeOut(this); + AddStdExpectStrings(); + iState=EATPhoneBookCommandWaitForReadComplete; + return; + + case EATPhoneBookCommandWaitForReadComplete: + case EATPhoneBookCommandWaitForAlternativeReadComplete: + __ASSERT_ALWAYS(aEventSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected)); + ret=ValidateExpectString(); + RemoveStdExpectStrings(); + if (ret!=KErrNone) + { + Complete(ret,aEventSource); + return; + } + iIo->SetTimeOut(this,KPhoneBookTimeForExtraRxData); + iState=EATPhoneBookCommandExtendedRead; + return; + + case EATPhoneBookCommandWaitForAlternativeWriteComplete: + __ASSERT_ALWAYS(aEventSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected)); + iIo->SetTimeOut(this,KPhoneBookReadTimeout*KOneSecondPause); + AddStdExpectStrings(); + iState=EATPhoneBookCommandWaitForAlternativeReadComplete; + return; + + case EATPhoneBookCommandExtendedRead: + __ASSERT_ALWAYS(aEventSource==ETimeOutCompletion,Panic(EATCommand_IllegalCompletionWaitExpected)); + Complete(ret,aEventSource); + return; + + case EATPhoneBookCommandIdle: + default: + return; + } + } + +void CATPhoneBookCommands::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus) +/** + * This function is called if an error occurs. It cancels the relevant timer and + * completes the request before setting the state to Idle. + */ + { + if (iState!=EATPhoneBookCommandIdle) + { + iIo->WriteAndTimerCancel(this); + iTelObject->ReqCompleted(iReqHandle,aStatus); + iState=EATPhoneBookCommandIdle; + } + } + +void CATPhoneBookCommands::StartStorageSelect() +/** + * This function finds out which phone book memory to set and then transmits the + * set command ("AT+CPBS=xx") to the relevant phone book. + */ + { + LOGTEXT(_L8("Starting AT+CPBS= Command")); + + CMobilePhonebookStore* phoneBook=REINTERPRET_CAST(CMobilePhonebookStore*,iTelObject); + if (iPhoneGlobals->iPhoneStatus.iLastAccessedPhoneBook==phoneBook->StorageType()) + { + StartThisCommand(); + } + else + { + TBuf8 buf; + TStorageType storageType(phoneBook->StorageType()); + buf.Format(KPhoneBookStorageSet,&storageType); + WriteExpectingResults(buf,3); + __ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL, Panic(EGeneral)); + iState=EATPhoneBookStorageSelectWaitForWriteComplete; + } + } + +void CATPhoneBookCommands::Stop(TTsyReqHandle aTsyReqHandle) +/** + * This function is used to prematurely stop the state machine. This would usually + * occur following a client cancel request. + */ + { + __ASSERT_ALWAYS(aTsyReqHandle == iReqHandle,Panic(EIllegalTsyReqHandle)); + LOGTEXT(_L8("Cancelling phone book command")); + + switch (iState) + { + case EATPhoneBookStorageSelectWaitForWriteComplete: + case EATPhoneBookCommandWaitForWriteComplete: + case EATPhoneBookCommandWaitForAlternativeWriteComplete: + Complete(KErrCancel,EWriteCompletion); + return; + + case EATPhoneBookStorageSelectWaitForReadComplete: + case EATPhoneBookCommandWaitForReadComplete: + case EATPhoneBookCommandWaitForAlternativeReadComplete: + Complete(KErrCancel,EReadCompletion); + return; + + case EATPhoneBookCommandExtendedRead: + Complete(KErrCancel,ETimeOutCompletion); + return; + + case EATPhoneBookCommandIdle: + default: + return; + } + } + +void CATPhoneBookCommands::Complete(TInt aError,TEventSource aSource) +/** + * This function completes a client request. Sets the state machine to Idle. + */ + { + iIo->WriteAndTimerCancel(this); + iIo->RemoveExpectStrings(this); + if (aSource==EWriteCompletion) + iIo->Read(); + iState=EATPhoneBookCommandIdle; + CATCommands::Complete(aError,aSource); + iTelObject->ReqCompleted(iReqHandle,aError); + } + +// +// CATPhoneBookRead definitions +// + +CATPhoneBookRead::CATPhoneBookRead(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,CATPhoneBookInfo *aInfo) + : CATPhoneBookCommands(aIo,aTelObject,aInit,aPhoneGlobals), + iInfo(aInfo) +/** + * C++ constructor + */ + {} + +CATPhoneBookRead::~CATPhoneBookRead() +/** + * Destructor. + */ + { + delete iPbBuffer; + } + +CATPhoneBookRead* CATPhoneBookRead::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,CATPhoneBookInfo *aInfo) +/** + * Standard 2 phase constructor. + * This method creats an instance of the CATPhoneBookRead class. + */ + { + CATPhoneBookRead* r=new(ELeave) CATPhoneBookRead(aIo,aTelObject,aInit,aPhoneGlobals,aInfo); + CleanupStack::PushL(r); + r->ConstructL(); + CleanupStack::Pop(); + return r; + } + +void CATPhoneBookRead::ConstructL() +/** + * Standard 2nd phase constructor. + * Creates phonebook buffer object used to populate client buffer + */ + { + CATCommands::ConstructL(); + iPbBuffer = new(ELeave) CPhoneBookBuffer(); + } + +void CATPhoneBookRead::Start(TTsyReqHandle aTsyReqHandle,TAny* aParams) +/** + * Start function. Its calls the StartStorageSelect() function to select + * the phone book memory. + */ + { + iReqHandle=aTsyReqHandle; + iRead = static_cast(aParams); + StartStorageSelect(); + } + +void CATPhoneBookRead::StartThisCommand() +/** + * This function starts the "AT+CPBR=minimum index, maximum index" command, i.e, + * Read one or a number of entries in the selected phone book. It constructs the command + * using the starting index and the number of entries that are to be read. It + * then sets the state machine going. + */ + { + LOGTEXT(_L8("Starting AT+CPBR=minIndex,maxIndex Command (Read one or more entries)")); + + // Construct the AT+CPBR=a,z command. The starting index is not necessarily 1 + TBuf8 buf(KPhoneBookReadAll); + buf.AppendNum(iRead->iIndex); // starting location in the phonebook from which to read + + if (iRead->iNumSlots>1) + { + // If more than one entry to be read also put finishing index + buf.Append(KCommaChar); + buf.AppendNum(iRead->iIndex + iRead->iNumSlots -1); // last location from which to read + } + + iNumReadEntries=0; + WriteExpectingResults(buf,3); + __ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL, Panic(EGeneral)); + iCPBRResponse=iIo->AddExpectString(this,KPhoneBookReadResponse); + iState=EATPhoneBookCommandWaitForAlternativeWriteComplete; + } + +void CATPhoneBookRead::ParseResponseL() +/** + * This function parses a line of response to the "AT+CBPR=minimum index, maximum index" + * command and converts the phonebook data into the TLV format. Note that the minimum + * index of the phone book memory need not necessarily + * start at 1 (e.g the phonebook could use range [100 to 150]. + */ + { + ParseBufferLC(EFalse, ':'); + + TDblQueIter iter(iRxResults); + CATParamListEntry* entry=iter++; //Assume discarded CPBR string + if (entry==NULL) + User::Leave(KErrGeneral); + TInt ret(KErrNone); + TBuf16 buffer; + + // new entry so append the new entry tag first + if(iPbBuffer->AddNewEntryTag() == KErrNone) + { + // convert index into TLV format and append it to the supplied buffer + entry=iter++; + if(!entry) + User::Leave(KErrGeneral); + TInt index=CATParamListEntry::EntryValL(entry); + + if (iInfo->Completed()) + { + LOGTEXT(_L8("CATPhoneBookRead::ParseResponseL Mapping phone index to client index")); + iInfo->MapPhoneIndexToClientIndex(index); + } + + ret = iPbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBAdnIndex, static_cast(index)); + + if(ret == KErrNone) // only continue if the previous field successfully appended + { + // convert number into TLV format and append it to the supplied buffer + entry=iter++; + if (!entry) + User::Leave(KErrGeneral); + buffer.Copy(entry->iResultPtr); +// If the number has a leading "+" then remove it. Note: in this case, we assume that the TON will be international. + if((buffer.Length()>0)&&(buffer[0]=='+')) + buffer.Delete(0,1); + + TPtrC16 numberPtr(buffer); + ret=iPbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber, numberPtr); + + if(ret == KErrNone) // only continue if the previous field successfully appended + { + // convert type into TLV format and append it to the supplied buffer + entry=iter++; + TInt type=CATParamListEntry::EntryValL(entry); + ret=iPbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi, static_cast(type)); + + if(ret == KErrNone) // only continue if the previous field successfully appended + { + // convert text into TLV format and append it to the supplied buffer + entry=iter++; + if (!entry) + User::Leave(KErrGeneral); + buffer.Copy(entry->iResultPtr); + TPtrC16 textPtr(buffer); + ret=iPbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText, textPtr); + if(ret==KErrNone) + iNumReadEntries++; + } + } + } + } // end if AddNewEntryTag + + // one of the fields could not be appended so remove previous fields from the buffer + if(ret != KErrNone) + { + (void)iPbBuffer->RemovePartialEntry(); + } + CleanupStack::PopAndDestroy(); // parsed buffer + } + +void CATPhoneBookRead::EventSignal(TEventSource aEventSource) +/** + * State machine. Replaces CATPhoneBookCommands implementation to use second command + * state. + */ + { + if ((aEventSource!=ETimeOutCompletion) && (iState==EATPhoneBookCommandWaitForAlternativeReadComplete)) + { + __ASSERT_ALWAYS(aEventSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected)); + // may be a entry, OK, or ERROR + if (iIo->FoundChatString()==iCPBRResponse) + { + TRAPD(ret,ParseResponseL()); + if (ret!=KErrNone) + { + Complete(ret,EReadCompletion); + return; + } + // wait for another one + iIo->SetTimeOut(this,KPhoneBookReadTimeout*KOneSecondPause); + } + else + { + TInt ret(ValidateExpectString()); + RemoveStdExpectStrings(); + if((ret==KErrNone)&&(iNumReadEntries==0)) + { +// No entries read, so buffer will be empty and KErrNotFound must be returned. + ret=KErrNotFound; + } + Complete(ret,EReadCompletion); + } + } + else + CATPhoneBookCommands::EventSignal(aEventSource); + } + + +void CATPhoneBookRead::CompleteWithIOError(TEventSource,TInt aError) +/** + * This function is called if an error occurs. It cancels the relevant timer and + * completes the request. + */ + { + if (iState!=EATPhoneBookCommandIdle) + { + iIo->WriteAndTimerCancel(this); + iCPBRResponse=0; + iState=EATPhoneBookCommandIdle; + iTelObject->ReqCompleted(iReqHandle,aError); + } + } + + +// +// CATPhoneBookWrite definitions +// + +CATPhoneBookWrite* CATPhoneBookWrite::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals) +/** + * Standard 2 phase constructor. + * This method creats an instance of the CATPhoneBookWrite class. + */ + { + CATPhoneBookWrite* r=new(ELeave) CATPhoneBookWrite(aIo,aTelObject,aInit,aPhoneGlobals); + CleanupStack::PushL(r); + r->ConstructL(); + CleanupStack::Pop(); + return r; + } + +CATPhoneBookWrite::CATPhoneBookWrite(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals) + : CATPhoneBookCommands(aIo,aTelObject,aInit,aPhoneGlobals) +/** + * C++ constructor + */ + {} + +void CATPhoneBookWrite::ConstructL() +/** + * Standard 2nd phase constructor. + * Creates phonebook buffer object used to extract data from client buffer + */ + { + CATCommands::ConstructL(); + iPbBuffer = new(ELeave) CPhoneBookBuffer(); + } + +CATPhoneBookWrite::~CATPhoneBookWrite() +/** + * Destructor. + */ + { + delete iPbBuffer; + } + +void CATPhoneBookWrite::Start(TTsyReqHandle aTsyReqHandle,TAny* aParams) +/** + * Start function. Its calls the StartStorageSelect() function to select + * the phone book memory. + */ + { + iReqHandle=aTsyReqHandle; + iIndex = *(static_cast(aParams)); // aParams will contain an index + StartStorageSelect(); + } + +void CATPhoneBookWrite::StartThisCommand() +/** + * This function starts the Write command. It decodes the phonebook data supplied by the + * client from the TLV format into the AT+CPBW= format, builds the command and + * starts the state machine to write the entry to the phone. It can only write + * one entry at a time. + */ + { + LOGTEXT(_L8("Starting AT+CPBW= Command")); + + TBuf8 atbuf; // used for 8-bit AT command characters + TBuf8 name; + TBuf8 number; + + TBuf16 des16Buf; // used for 16-bit name field + TPtrC16 des16Ptr(des16Buf); + + TUint8 tonNpi(0); + + TUint8 aTagValue(0); + CPhoneBookBuffer::TPhBkTagType aDataType; + + TInt ret=KErrNone; + iPbBuffer->StartRead(); + while ((ret=iPbBuffer->GetTagAndType(aTagValue, aDataType))==KErrNone) + { + if (aTagValue==RMobilePhoneBookStore::ETagPBTonNpi) + { + (void)iPbBuffer->GetValue(tonNpi); + } + else if (aTagValue==RMobilePhoneBookStore::ETagPBText) + { + (void)iPbBuffer->GetValue(des16Ptr); + + if (des16Ptr.Length() > KGenericBufferSize) + { + Complete(KErrOverflow, EWriteCompletion); + return; + } + + name.Copy(des16Ptr); + } + else if (aTagValue==RMobilePhoneBookStore::ETagPBNumber) + { + (void)iPbBuffer->GetValue(des16Ptr); + + if (des16Ptr.Length() > KGenericBufferSize) + { + Complete(KErrOverflow, EWriteCompletion); + return; + } + + number.Copy(des16Ptr); + } + else + { + // An unsupported field type - just skip this value + iPbBuffer->SkipValue(aDataType); + } + } + + if(ret==KErrNotFound) // This is to ensure the TLV conversion worked + { +// If the ton is international, but the number doesn't start with a '+' then prepend one. + if((tonNpi==145)&&(number.Length()>0)&&(number[0]!='+')) + atbuf.Format(KPhoneBookWriteWithIndexPrependedPlus,iIndex,&number,tonNpi,&name); + else + atbuf.Format(KPhoneBookWriteWithIndex,iIndex,&number,tonNpi,&name); + } + + WriteExpectingResults(atbuf,3); + __ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL, Panic(EGeneral)); + iState=EATPhoneBookCommandWaitForWriteComplete; + } + + +TUint CATPhoneBookWrite::NumberTypefromMMToGSM(TUint aTypeOfNumberMM) +/** Maping from MM Number Type To GSM Number Type + * This method maps the MM way of representing a type of telefon number + * to the GSM standard. + */ + { + switch (aTypeOfNumberMM) + { + case 0: // EUnknownNumber (MM) + return 129; // Nationality unknown (GSM) + case 1: // EInternationalNumber (MM) + return 145; // International Number (GSM) + case 2: // ENationalNumber (MM) + return 161; // National Number (GSM) + default: + return 129; // Nationality unknown (GSM) + } + } + + +void CATPhoneBookWrite::ParseResponseL() + { + } + + +// +// CATPhoneBookDelete definitions +// +CATPhoneBookDelete* CATPhoneBookDelete::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals) +/** + * Standard 2 phase constructor. + * This method creats an instance of the CATPhoneBookDelete class. + */ + { + CATPhoneBookDelete* r=new(ELeave) CATPhoneBookDelete(aIo,aTelObject,aInit,aPhoneGlobals); + CleanupStack::PushL(r); + r->ConstructL(); + CleanupStack::Pop(); + return r; + } + +CATPhoneBookDelete::CATPhoneBookDelete(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals) + : CATPhoneBookCommands(aIo,aTelObject,aInit,aPhoneGlobals) +/** + * C++ constructor + */ + {} + +CATPhoneBookDelete::~CATPhoneBookDelete() + {} + +void CATPhoneBookDelete::Start(TTsyReqHandle aTsyReqHandle,TAny* aParams) +/** + * Start function. Its calls the StartStorageSelect() function to select + * the phone book memory. + */ + { + iReqHandle=aTsyReqHandle; + iIndex=*(TInt*)aParams; + + StartStorageSelect(); + } + +void CATPhoneBookDelete::StartThisCommand() +/** + * Start of the Delete command. This function constructs and then sends the Delete + * command (the Delete command is the same as the write command with just the index to + * delete specified e.g "AT+CPBW=2" command will delete the entry in index location 2). + */ + { + LOGTEXT(_L8("Starting AT+CPBW= Command")); + + TBuf8 buf; + + buf.Format(KPhoneBookDelete,iIndex); + WriteExpectingResults(buf,3); + __ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL, Panic(EGeneral)); + iState=EATPhoneBookCommandWaitForWriteComplete; + } + +void CATPhoneBookDelete::StartAlternativeDelete() +/** + * Alternative Delete command. The same principles as the normal delete apply. + */ + { + LOGTEXT(_L8("Starting alternative AT+CPBW= Command")); + + TBuf8 buf; + + buf.Format(KPhoneBookAlternativeDelete,iIndex); + WriteExpectingResults(buf,3); + __ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL, Panic(EGeneral)); + iState=EATPhoneBookCommandWaitForAlternativeWriteComplete; + } + + +void CATPhoneBookDelete::EventSignal(TEventSource aEventSource) +/** + * State machine for the Delete command. + */ + { + if (iState==EATPhoneBookCommandWaitForReadComplete && + aEventSource!=ETimeOutCompletion) + { + __ASSERT_ALWAYS(aEventSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected)); + TInt ret(ValidateExpectString()); + RemoveStdExpectStrings(); + if (ret==KErrGeneral) + { + StartAlternativeDelete(); + return; + } + if (ret!=KErrNone) + { + Complete(ret,aEventSource); + return; + } + iIo->SetTimeOut(this,KTimeForExtraRxData); + iState=EATPhoneBookCommandExtendedRead; + } + else + CATPhoneBookCommands::EventSignal(aEventSource); + } + +void CATPhoneBookDelete::ParseResponseL() +/** + * + */ + { + } + +