// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).// All rights reserved.// This component and the accompanying materials are made available// under the terms of "Eclipse Public License v1.0"// which accompanies this distribution, and is available// at the URL "http://www.eclipse.org/legal/epl-v10.html".//// Initial Contributors:// Nokia Corporation - initial contribution.//// Contributors://// Description:// Name : CSatNotifySelectItem.cpp// Part of : Common SIM ATK TSY / commonsimatktsy// SelectItem notification functionality of Sat Tsy// Version : 1.0////INCLUDES#include <satcs.h> // Etel SAT IPC definitions#include "CSatTsy.h" // Tsy class header#include "CSatNotifySelectItem.h" // Tsy class header#include "CSatNotificationsTsy.h" // Class header#include "CBerTlv.h" // Ber Tlv data handling#include "TTlv.h" // TTlv class#include "CSatDataPackage.h" // Parameter packing #include "TfLogger.h" // For TFLOGSTRING#include "TSatUtility.h" // Utilities#include "CSatTsyReqHandleStore.h" // Request handle class#include "cmmmessagemanagerbase.h" // Message manager class for forwarding req.// -----------------------------------------------------------------------------// CSatNotifySelectItem::NewL// Two-phased constructor.// -----------------------------------------------------------------------------// CSatNotifySelectItem* CSatNotifySelectItem::NewL ( CSatNotificationsTsy* aNotificationsTsy ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::NewL"); CSatNotifySelectItem* const satNotifySelectItem = new ( ELeave ) CSatNotifySelectItem( aNotificationsTsy ); CleanupStack::PushL( satNotifySelectItem ); satNotifySelectItem->ConstructL(); CleanupStack::Pop( satNotifySelectItem ); TFLOGSTRING("CSAT: CSatNotifySelectItem::NewL, end of method"); return satNotifySelectItem; }// -----------------------------------------------------------------------------// CSatNotifySelectItem::~CSatNotifySelectItem// Destructor// -----------------------------------------------------------------------------// CSatNotifySelectItem::~CSatNotifySelectItem ( // None ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::~CSatNotifySelectItem"); }// -----------------------------------------------------------------------------// CSatNotifySelectItem::CSatNotifySelectItem// Default C++ constructor// -----------------------------------------------------------------------------// CSatNotifySelectItem::CSatNotifySelectItem ( CSatNotificationsTsy* aNotificationsTsy ) : iNotificationsTsy ( aNotificationsTsy ), iItemsIconIdListRemoved ( EFalse ) { // None }// -----------------------------------------------------------------------------// CSatNotifySelectItem::ConstructL// Symbian 2nd phase constructor// -----------------------------------------------------------------------------// void CSatNotifySelectItem::ConstructL ( // None ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::ConstructL"); // Initiliaze Item Next Indicator flag iItemNextIndicatorRemoved = EFalse; }// -----------------------------------------------------------------------------// CSatNotifySelectItem::Notify// This request allows a client to be notified of a SELECT ITEM proactive // command// -----------------------------------------------------------------------------//TInt CSatNotifySelectItem::Notify ( const TTsyReqHandle aTsyReqHandle, const TDataPackage& aPackage ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::Notify"); // Save data pointer to client side for completion iSelectItemV2Pckg = reinterpret_cast<RSat::TSelectItemV2Pckg*>( aPackage.Des1n() ); // Save the request handle iNotificationsTsy->iSatTsy->SaveReqHandle( aTsyReqHandle, CSatTsy::ESatNotifySelectItemPCmdReqType ); // Check if requested notification is already pending iNotificationsTsy->NotifySatReadyForNotification( KSelectItem ); return KErrNone; }// -----------------------------------------------------------------------------// CSatNotifySelectItem::CancelNotification// This method cancels an outstanding asynchronous // NotifyDisplayText request.// -----------------------------------------------------------------------------//TInt CSatNotifySelectItem::CancelNotification ( const TTsyReqHandle aTsyReqHandle ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::CancelNotification"); // Reset the request handle TTsyReqHandle reqHandle = iNotificationsTsy->iSatReqHandleStore-> ResetTsyReqHandle( CSatTsy::ESatNotifySelectItemPCmdReqType ); // Reset the data pointer iSelectItemV2Pckg = NULL; // Complete the request with KErrCancel iNotificationsTsy->iSatTsy->ReqCompleted( aTsyReqHandle, KErrCancel ); return KErrNone; }// -----------------------------------------------------------------------------// CSatNotifySelectItem::CompleteNotifyL// Complete Sim Session End notification to the client// -----------------------------------------------------------------------------// TInt CSatNotifySelectItem::CompleteNotifyL ( CSatDataPackage* aDataPackage, TInt aErrorCode ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL"); TInt ret( KErrNone ); // Unpack parameters TPtrC8* data; aDataPackage->UnPackData( &data ); TBuf<1> additionalInfo; // Reset req handle. Returns the deleted req handle TTsyReqHandle reqHandle = iNotificationsTsy->iSatReqHandleStore-> ResetTsyReqHandle( CSatTsy::ESatNotifySelectItemPCmdReqType ); // Get ber tlv CBerTlv berTlv; berTlv.SetData( *data ); // Get command details tlv CTlv commandDetails; berTlv.TlvByTagValue( &commandDetails, KTlvCommandDetailsTag ); // Store command details tlv iNotificationsTsy->iTerminalRespData.iCommandDetails.Copy( commandDetails.Data() ); // Get command qualifier TUint8 cmdQualifier( commandDetails.GetShortInfo( ETLV_CommandQualifier ) ); TUint8 pCmdNumber( commandDetails.GetShortInfo( ETLV_CommandNumber ) ); // In case the request was ongoing, continue.. if ( CSatTsy::ESatReqHandleUnknown != reqHandle ) { // Complete right away if error has occured, otherwise continue.. if ( KErrNone == aErrorCode ) { // Fill the select item structure RSat::TSelectItemV2& selectItemV2 = ( *iSelectItemV2Pckg )(); selectItemV2.Reset(); // Store Transaction id place of command number // This is done because we keep interface same as in Calimero. // Client returns back same value in response package. selectItemV2.SetPCmdNumber( pCmdNumber ); TPtrC8 sourceString; // Used in unicode conversions // Alpha id string (optional) selectItemV2.iAlphaId.iAlphaId.Zero(); CTlv alphaIdentifier; TInt returnValue( berTlv.TlvByTagValue( &alphaIdentifier, KTlvAlphaIdentifierTag ) ); // If alpha id string exist if ( KErrNone == returnValue ) { TUint16 alphaIdLength( alphaIdentifier.GetLength() ); if ( alphaIdLength ) { // Get the alpha id sourceString.Set( alphaIdentifier.GetData( ETLV_AlphaIdentifier ) ); // Convert and set the alpha id TSatUtility::SetAlphaId( sourceString, selectItemV2.iAlphaId.iAlphaId ); } // Check alpha tag (id) status if ( alphaIdLength ) { // Alpha tag present if ( selectItemV2.iAlphaId.iAlphaId.Length() ) { selectItemV2.iAlphaId.iStatus = RSat::EAlphaIdProvided; } else { TFLOGSTRING("CSAT: CSatNotifySelectItem::\ CompleteNotifyL, Alpha ID is NULL"); selectItemV2.iAlphaId.iStatus = RSat::EAlphaIdNull; } } } // Alpha id not present else { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL\ Alpha ID not present"); selectItemV2.iAlphaId.iStatus = RSat::EAlphaIdNotPresent; } // Help information if ( KHelpAvailabilityMask & cmdQualifier ) { // Help information available selectItemV2.iHelp = RSat::EHelpAvailable; } else { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL,\ No Help available"); // No help selectItemV2.iHelp = RSat::ENoHelpAvailable; } // Presentation as a choice of navigation options if ( KSelectItemChoiceOfNavigation == ( KSelectItemPresentationTypeMask & cmdQualifier ) ) { selectItemV2.iPresentationType = RSat::ENavigationOptions; } // Presentation as a choice of data values else if ( KSelectItemChoiceOfData == ( KSelectItemPresentationTypeMask & cmdQualifier ) ) { selectItemV2.iPresentationType = RSat::EDataValues; } else { selectItemV2.iPresentationType = RSat::ENotSpecified; } // Selection preference if ( KSelectItemSelectUsingSoftKeyMask & cmdQualifier ) { // Preference = soft key selectItemV2.iPreference = RSat::ESoftKeyPreferred; } else { // Preference not set selectItemV2.iPreference = RSat::ESelectionPreferenceNotSet; } // Default item id ( optional ) CTlv defaultItem; returnValue = berTlv.TlvByTagValue( &defaultItem, KTlvItemIdentifierTag ); if ( KErrNone == returnValue ) { selectItemV2.iDefaultItemId = defaultItem.GetShortInfo( ETLV_IdentifierOfItemChosen ); } // Icon qualifier list ( optional ) // Each item of a list of items has an icon identifier coded on one // byte. The length of the Items icon identifier list shall be the // number of items of the list of items (X-1 shall be the number of // items in the list). The order of each item icon identifier, // shall reflect the order of the items in the list of items. // Each icon identifier addresses a record // in EFIMG as defined in TS 11.11 CTlv itemsIconIdentifierList; TInt retValue( berTlv.TlvByTagValue( &itemsIconIdentifierList, KTlvItemIconIdentifierListTag ) ); selectItemV2.iIconListQualifier = RSat::EIconQualifierNotSet; TPtrC8 iconIdList; if ( KErrNone == retValue ) { TUint8 iconListQualifier( itemsIconIdentifierList.GetShortInfo( ETLV_IconListQualifier ) ); // Set iconIdList pointer iconIdList.Set( itemsIconIdentifierList.GetData( ETLV_IconIdentifierList )); // The icon list qualifier indicates to the ME how // the icons are to be used if( iconListQualifier ) { // icon is not self-explanatory, i.e. if displayed, // it shall be displayed together with the item text selectItemV2.iIconListQualifier = RSat::ENotSelfExplanatory; } else { // icon is self-explanatory, i.e. if displayed, // it replaces the item text selectItemV2.iIconListQualifier = RSat::ESelfExplanatory; } } else if ( KErrNotFound == retValue ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL,\ No Icon ID"); selectItemV2.iIconListQualifier = RSat::ENoIconId; } else { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL, \ Return value not valid."); } ret = HandleItemsL( pCmdNumber, &berTlv, ret, iconIdList, &selectItemV2 ); // Iconid TSatUtility::FillIconStructure( berTlv, selectItemV2.iIconId ); } // End of if ( KErrNone == aErrorCode ) else { ret = aErrorCode; } iNotificationsTsy->iSatTsy->ReqCompleted( reqHandle, ret ); } // End of if ( CSatTsy::ESatReqHandleUnknown != reqHandle ) else { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL,\ Request not ongoing"); // Request not on, returning response immediately additionalInfo.Zero(); additionalInfo.Append( KNoCause ); CreateTerminalRespL( pCmdNumber, RSat::KMeUnableToProcessCmd, additionalInfo ); } return ret; }// -----------------------------------------------------------------------------// CSatNotifySelectItem::TerminalResponseL// Called by ETel server, passes terminal response to DOS// -----------------------------------------------------------------------------//TInt CSatNotifySelectItem::TerminalResponseL ( TDes8* aRsp ) { TFLOGSTRING("CSAT:: CSatNotifySelectItem::TerminalResponseL"); TInt ret( KErrNone ); TBuf<1> additionalInfo; RSat::TSelectItemRspV1Pckg* aRspPckg = reinterpret_cast<RSat::TSelectItemRspV1Pckg*> ( aRsp ); RSat::TSelectItemRspV1& rspV1 = ( *aRspPckg ) (); // Get Proactive command number TUint8 pCmdNumber( rspV1.PCmdNumber() ); // Check that general result values are valid if ( ( RSat::KSuccess != rspV1.iGeneralResult ) && ( RSat::KSuccessRequestedIconNotDisplayed != rspV1.iGeneralResult ) && ( RSat::KPSessionTerminatedByUser != rspV1.iGeneralResult ) && ( RSat::KBackwardModeRequestedByUser != rspV1.iGeneralResult ) && ( RSat::KNoResponseFromUser != rspV1.iGeneralResult ) && ( RSat::KHelpRequestedByUser != rspV1.iGeneralResult ) && ( RSat::KMeUnableToProcessCmd != rspV1.iGeneralResult ) && ( RSat::KCmdBeyondMeCapabilities != rspV1.iGeneralResult ) ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL,\ Invalid General Result"); ret = KErrCorrupt; } // If there is ME (Mobile Entity) error or there there should be // item identifier or // general result is success, additional info is needed if ( ( RSat::KMeProblem == rspV1.iInfoType ) || ( RSat::KItemIdentifier == rspV1.iInfoType ) || ( RSat::KSuccess == rspV1.iGeneralResult ) ) { // Check the length of additional info if ( rspV1.iAdditionalInfo.Length() != 0 ) { TFLOGSTRING2("CSAT: CSatNotifySelectItem::TerminalResponseL, \ Additional info: %S", &rspV1.iAdditionalInfo); additionalInfo.Zero(); additionalInfo.Append( rspV1.iAdditionalInfo[0] ); TFLOGSTRING2("CSAT: CSatNotifySelectItem::TerminalResponseL, \ Additional info: %S", &additionalInfo); } else { TFLOGSTRING("CSAT: CSatNotifySelectItem::CompleteNotifyL,\ Invalid Additional Info"); ret = KErrCorrupt; } } if ( RSat::KSuccess == rspV1.iGeneralResult ) { if (iItemNextIndicatorRemoved) { TFLOGSTRING("CSatNotifySelectItem::TerminalResponseL, Partial Comprehension, \ iItemNextIndicatorRemoved"); rspV1.iGeneralResult = RSat::KPartialComprehension; } if (iItemsIconIdListRemoved) { TFLOGSTRING("CSatNotifySelectItem::TerminalResponseL, Partial Comprehension, \ iItemsIconIdListRemoved"); rspV1.iGeneralResult = RSat::KPartialComprehension; } } iItemNextIndicatorRemoved = EFalse; iItemsIconIdListRemoved = EFalse; CreateTerminalRespL( pCmdNumber, static_cast<TUint8>( rspV1.iGeneralResult ), additionalInfo ); return ret; }// -----------------------------------------------------------------------------// CSatNotifySelectItem::CreateTerminalRespL// Constructs SelectItem specific part of terminal response and calls // DOS to send the actual message.// -----------------------------------------------------------------------------//TInt CSatNotifySelectItem::CreateTerminalRespL ( TUint8 aPCmdNumber, TUint8 aGeneralResult, TDesC16& aAdditionalInfo ) { TFLOGSTRING2("CSAT: CSatNotifySelectItem::CreateTerminalRespL, \ Additional info: %S", &aAdditionalInfo); TTlv tlvSpecificData; // Create General Result TLV here tlvSpecificData.AddTag( KTlvResultTag ); // General result tlvSpecificData.AddByte( aGeneralResult ); if ( !( iNotificationsTsy->CommandPerformedSuccessfully( aGeneralResult ) ) ) { switch ( aGeneralResult ) { case RSat::KHelpRequestedByUser: { // Add selected Item Id tag tlvSpecificData.AddTag( KTlvItemIdentifierTag ); tlvSpecificData.AddByte( ( TUint8 ) aAdditionalInfo[0] ); break; } case RSat::KPSessionTerminatedByUser: case RSat::KBackwardModeRequestedByUser: case RSat::KNoResponseFromUser: { break; } default: { if (aAdditionalInfo.Length() > 0) { tlvSpecificData.AddByte( ( TUint8 ) aAdditionalInfo[0] ); } break; } } } else { // Add selected Item Id tag tlvSpecificData.AddTag( KTlvItemIdentifierTag ); tlvSpecificData.AddByte( ( TUint8 ) aAdditionalInfo[0] ); } // Prepare data iNotificationsTsy->iTerminalRespData.iPCmdNumber = aPCmdNumber; TPtrC8 data = tlvSpecificData.GetDataWithoutTopLevelTag(); // Pack data CSatDataPackage dataPackage; dataPackage.PackData( &iNotificationsTsy->iTerminalRespData, &data ); // Forward request to the DOS return iNotificationsTsy->iSatTsy->MessageManager()->HandleRequestL( ESatTerminalRsp, &dataPackage ); }// -----------------------------------------------------------------------------// CSatNotifySelectItem::HandleItemsL// Handle menu items// -----------------------------------------------------------------------------//TInt CSatNotifySelectItem::HandleItemsL ( TUint8 aPCmdNumber, CBerTlv* aBerTlv, TInt aRet, TPtrC8 aIconIdList, RSat::TSelectItemV2* aSelectItemV2 ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::HandleItemsL"); TInt ret( aRet ); CTlv item; // Get all items TInt returnValue = aBerTlv->TlvByTagValueMulti( &item, KTlvItemTag ); TPtrC8 itemData = item.Data(); TUint8 numberOfItemData( 0 ); TInt ind( 0 ); TUint16 tlvLength( 0 ); TInt currentTlv( 0 ); TInt i( 0 ); // Set numberOfItemData for ( i = 0; i < itemData.Length(); i += ( TInt ) tlvLength ) { // First determine if the length of the TLV is // coded with 1 or 2 bytes. if ( KTwoByteLengthCoding == itemData[ind+1] ) { // Length is coded with 2 bytes -> real length is in second // byte first byte is 81 and it is "tag" for 2 byte length // coding. tlvLength = ( TUint16 ) ( itemData[ind + 2] + KTlvHeaderLength + 1 ); } else { // TLV header bytes (2) must be added to total length tlvLength = ( TUint16 ) ( itemData[ind + 1] + KTlvHeaderLength ); } currentTlv = itemData[ind]&KTagValueMask; if ( KTlvItemTag == currentTlv ) { numberOfItemData++; } ind += tlvLength; } // See if itemnextindicator is included ( optional ) CTlv nextIndicator; returnValue = aBerTlv->TlvByTagValue( &nextIndicator, KTlvItemsNextActionIndicatorTag ); TPtrC8 itemNextIndicator; if ( KErrNone == returnValue ) { TPtrC8 itemNextIndicatorTemp; itemNextIndicatorTemp.Set( nextIndicator.GetData( ETLV_ItemsNextActionIndicator ) ); // In case the number of items in this list doesn't match the nr of // items in the menu, Items Next Action Indicator list is ignored by ME if( itemNextIndicatorTemp.Length() != numberOfItemData ) { iItemNextIndicatorRemoved = ETrue; } else { itemNextIndicator.Set( itemNextIndicatorTemp ); } } if ( ( aIconIdList.Length() > 0 ) && ( aIconIdList.Length() != numberOfItemData ) ) { // In case the number of items in this list doesn't match the nr of // items in the menu, Items Icon Identifier list is ignored by ME iItemsIconIdListRemoved = ETrue; aIconIdList.Set( KNullDesC8 ); } // Filling up the menu items RSat::TItem newItem; // Set string length and pos TUint8 stringLength( 0 ); TUint8 pos( 2 ); // LOOP Through ALL MENU ITEMS AND TAKE THE DATA for ( i = 0; ( i < numberOfItemData ) && ( KErrNone == ret ); i++ ) { // Check if two byte length coding is used if ( KTwoByteLengthCoding == itemData[pos - 1] ) { // Set new offset pos++; } // Fill the newitem newItem.iItemId = itemData[pos]; stringLength = itemData[pos - 1]; // Copying the string from 8-bit to 16-bit if ( RSat::KMenuItemMaxSize < stringLength ) { // String too long ret = KErrCorrupt; } newItem.iItemString.Zero(); // ArabicCoding, GreekCoding and TurkishCoding have different // coding method. There is a tag for each type of alphabet // (resp. 80, 81 or 82) before the text, and there are base // pointers used for expanding 1 byte to 2 bytes as required // in UCS2 // Ref: 3gpp 11.11, Annex B // Check if string present if ( 0 < ( stringLength - 1 ) ) { TBuf8<RSat::KTextStringMaxSize> itemText; itemText = itemData.Mid( pos + 1, stringLength - 1 ); if ( ( KUCS2ArabicCoding == itemText[0] ) || ( KUCS2GreekCoding == itemText[0] ) || ( KUCS2TurkishCoding == itemText[0] ) ) { TSatUtility::ConvertAlphaFieldsToUnicode( itemText, newItem.iItemString ); } else { // 8-bit format TSatUtility::Convert7BitToUnicode16( itemText, newItem.iItemString ); } } if ( ( NULL != aIconIdList.Size() ) && ( i < aIconIdList.Length() ) ) { if ( ( NULL != itemNextIndicator.Size() ) && ( i < itemNextIndicator.Length() ) ) { // ADD ITEM WITH ITEM NEXT INDICATOR AND ICON IDENTIFIER if ( KErrNoMemory == aSelectItemV2->AddItem( newItem, itemNextIndicator[i], aIconIdList[i] ) ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::HandleItemsL,\ Icon data length exceeded, AddItem1"); // Too many or long menu items ret = KErrCorrupt; } } // ADD ITEM WITH ICON else if ( KErrNoMemory == aSelectItemV2->AddItemIcon( newItem, aIconIdList[i] ) ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::HandleItemsL,\ Icon data length exceeded, AddItemIcon"); // Too many or long menu items ret = KErrCorrupt; } } else { if ( ( NULL != itemNextIndicator.Size() ) && ( i < itemNextIndicator.Length() ) ) { // ADD ITEM WITH ITEM NEXT INDICATOR if ( KErrNoMemory == aSelectItemV2->AddItem( newItem, itemNextIndicator[i] ) ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::HandleItemsL,\ Icon data length exceeded, AddItem2"); // Too many or long menu items ret = KErrCorrupt; } } //ADD ITEM else { TInt retAdd = aSelectItemV2->AddItem( newItem ); if ( KErrNoMemory == retAdd ) { TFLOGSTRING("CSAT: CSatNotifySelectItem::HandleItemsL,\ AddItem failed -> KErrNoMemory"); // Too many or long menu items // If there is not enough space left in the buffer used // by the menu KErrNoMemory is returned. TBuf<1> additionalInfo; additionalInfo.Zero(); additionalInfo.Append( KNoCause ); // Send terminal response CreateTerminalRespL( aPCmdNumber, RSat::KCmdDataNotUnderstood, additionalInfo ); ret = KErrCorrupt; } } } // Calculating the new position pos = TUint8( pos + itemData[pos - 1] + 2 ); } return ret; }// End of File