// --------------------------------------------------------------------------- // CMmConferenceCallGsmWcdmaExt::AddCallL // Addition of a new call to an existing conference call. If // call object is not found by the name given as input parameter KErrArgument // will be returned. // (other items were commented in a header). // --------------------------------------------------------------------------- // TInt CMmConferenceCallGsmWcdmaExt::AddCallL( const TName* aCallName, RMobileConferenceCall::TMobileConferenceStatus aStatus, CMmCallList* aCallList ) { TInt ret = KErrArgument; // Get the call object that should be added to the conference call CMmCallTsy* mmCall = aCallList->GetMmCallByName( aCallName ); if ( mmCall ) { // Fetch the active call extension CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>( mmCall->ActiveCallExtension() ); // Get the mobile call capabilities RMobileCall::TMobileCallCapsV1 mobileCallCaps; mmCallGsmWcdmaExt->GetMobileCallCapsV1(mobileCallCaps); // Only calls whose call control capabilities include KCapsJoin can be added to a conference call. if( !( RMobileCall::KCapsJoin & mobileCallCaps.iCallControlCaps )) { // Do not add the call to the conference since the call doesn't have KCapsJoin capability. if(KMaxCallsInConference <= iMmConferenceCallTsy->NumberOfCallsInConference()) return KErrMMEtelMaxReached; return ret; } RMobileCall::TMobileCallStatus callStatus = mmCall->MobileCallStatus(); //check that this call is not in hold or connected state and //conference call is not idle (=no reason to try this) if ( ( ( callStatus == RMobileCall::EStatusHold ) || ( callStatus == RMobileCall::EStatusConnected ) ) && ( RMobileConferenceCall::EConferenceIdle != aStatus ) ) { // send request to DOS // only packed parameter for DOS call: Id of the call to be added CCallDataPackage callDataPackage; callDataPackage.SetCallIdAndMode( mmCall->CallId(), RMobilePhone::EServiceUnspecified ); // service type not needed CMmCallTsy* mmExistingCall = NULL; TInt existingCallId; __DEBUG_ONLY(TBool callFound = EFalse;) TInt numOfObjects = aCallList->GetNumberOfObjects(); for ( TInt i = 0; i < numOfObjects; i++ ) { mmExistingCall = aCallList->GetMmCallByIndex(i); if ( mmExistingCall->IsPartOfConference() ) { __DEBUG_ONLY(callFound = ETrue;) existingCallId = mmExistingCall->CallId(); break; }
// ----------------------------------------------------------------------------- // CMmConferenceCallMessHandler::CallControlInd // Breaks a CALL_CONTROL_IND ISI-message. Completes failed // CreateConference, AddCall or Swap API request if there is a cause sub // block in this response. In case that this message contains Split operation // sub block, inform ConferenceCallTsy that GoOneToOne handling has started // ----------------------------------------------------------------------------- // void CMmConferenceCallMessHandler::CallControlInd( const TIsiReceiveC& aIsiMsg ) { TFLOGSTRING("TSY: CMmConferenceCallMessHandler::CallControlInd"); OstTrace0( TRACE_NORMAL, CMMCONFERENCECALLMESSHANDLER_CALLCONTROLIND_TD, "CMmConferenceCallMessHandler::CallControlInd" ); TUint sbStartOffSet( 0 ); // Try to find CALL_MODEM_SB_CAUSE subblock. If found something has gone wrong if( KErrNone == aIsiMsg.FindSubBlockOffsetById( ISI_HEADER_SIZE + SIZE_CALL_MODEM_CONTROL_IND, CALL_MODEM_SB_CAUSE, EIsiSubBlockTypeId8Len8, sbStartOffSet ) ) { // CALL_MODEM_SB_CAUSE sub block found, something has gone wrong. // Get cause type TUint8 causeType( aIsiMsg.Get8bit( sbStartOffSet + CALL_MODEM_SB_CAUSE_OFFSET_CAUSETYPE ) ); // Get cause value TUint8 causeValue( aIsiMsg.Get8bit( sbStartOffSet + CALL_MODEM_SB_CAUSE_OFFSET_CAUSE ) ); // Get Symbian OS error value TInt result( CMmStaticUtility::CSCauseToEpocError( PN_MODEM_CALL, causeType, causeValue ) ); // If last operation was build, CreateConference or AddCall was asked if ( CALL_MODEM_OP_CONFERENCE_BUILD == iLastOperation ) { // Has CreateConference been requested last. if ( iIsCreateConference ) { // Complete with error iMessageRouter->Complete( EMobileConferenceCallCreateConference, result); // Reset flag iIsCreateConference = EFalse; } else { // Must be response to AddCall request iMessageRouter->Complete( EMobileConferenceCallAddCall, result ); } iLastOperation = 0; } // if last operation was hold or retrieve else if ( CALL_MODEM_OP_HOLD == iLastOperation || CALL_MODEM_OP_RETRIEVE == iLastOperation ) { // Complete swap with error iMessageRouter->Complete( EMobileConferenceCallSwap, result ); } // No else } // Successful operation handling for operations // Initiated bypassing the ETel (ghost operetion). else if ( !iIsCreateConference && 0 == iLastOperation ) { TUint8 callOperation( 0 ); // Get call Id (three bits (1-3) contain unique call ID) TInt uniqueCallId( static_cast<TInt>( aIsiMsg.Get8bit( ISI_HEADER_SIZE + CALL_MODEM_CONTROL_IND_OFFSET_CALLID ) & KMaskBits1to3 ) ); // Get call operation sub block if ( KErrNone == aIsiMsg.FindSubBlockOffsetById( ISI_HEADER_SIZE + CALL_MODEM_CONTROL_IND_OFFSET_OPERATION, CALL_MODEM_SB_OPERATION, EIsiSubBlockTypeId8Len8, sbStartOffSet ) ) { TInt symbianConferenceEvent( -1 ); // Get call operation callOperation = aIsiMsg.Get8bit( sbStartOffSet + CALL_MODEM_SB_OPERATION_OFFSET_OPERATION ); TFLOGSTRING2("TSY: CMmConferenceCallMessHandler::CallControlInd - Call operation: %d", callOperation); OstTraceExt1( TRACE_NORMAL, DUP1_CMMCONFERENCECALLMESSHANDLER_CALLCONTROLIND_TD, "CMmConferenceCallMessHandler::CallControlInd;callOperation=%hhu", callOperation ); // Purpose of this case is to prepare handling of externally // controlled conference call switch ( callOperation ) { case CALL_MODEM_OP_CONFERENCE_BUILD: { symbianConferenceEvent = RMobileConferenceCall::EConferenceBuilt; break; } case CALL_MODEM_OP_HOLD: case CALL_MODEM_OP_SWAP: { symbianConferenceEvent = RMobileConferenceCall::EConferenceSwapped; break; } case CALL_MODEM_OP_CONFERENCE_SPLIT: { symbianConferenceEvent = RMobileConferenceCall::EConferenceSplit; break; } default: { // Nothing to do break; } } // Update the information to Conference call if ( 0 <= symbianConferenceEvent ) { // Create call package CCallDataPackage callData; // Pack the data for sending to the manager callData.SetCallIdAndMode( uniqueCallId, RMobilePhone::EVoiceService ); // Pack conference event callData.PackData( &symbianConferenceEvent ); // Pass call information to the Symbian OS layer // complete mobile call info change iMessageRouter->Complete( EMobileConferenceCallNotifyConferenceEvent, &callData, KErrNone ); } // No else } // No else } // No else iIsCreateConference = EFalse; iLastOperation = 0; }