os/mm/devsound/sounddevbt/src/A2dpBlueTooth/server/A2dpBTHeadsetAudioIfServer.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include <s32mem.h>
    17 #include "A2dpBTHeadsetAudioIfServer.h"
    18 #include "A2dpBTHeadsetAudioIfServerStart.h"
    19 #include "A2dpBTheadsetAudioIf.h"
    20 #include "MMFBtRoutingSoundDevice.h"	// for TRange
    21 
    22 
    23 CA2dpBTHeadsetAudioIfServer* CA2dpBTHeadsetAudioIfServer::NewL()
    24 	{
    25 	CA2dpBTHeadsetAudioIfServer* self = new(ELeave) CA2dpBTHeadsetAudioIfServer();
    26 	CleanupStack::PushL(self);
    27 	self->ConstructL();
    28 	CleanupStack::Pop();
    29 	return self;
    30 	}
    31 	
    32 CA2dpBTHeadsetAudioIfServer::~CA2dpBTHeadsetAudioIfServer()
    33 	{
    34 	delete iBTAudioInterface;
    35 	}
    36 	
    37 CMmfIpcSession* CA2dpBTHeadsetAudioIfServer::NewSessionL(const TVersion &aVersion) const
    38 	{
    39 	TVersion version(	KBTAudioServerMajorVersionNumber,
    40 						KBTAudioServerMinorVersionNumber,
    41 						KBTAudioServerBuildVersionNumber);
    42 
    43 	if(!User::QueryVersionSupported(version, aVersion))
    44 		{
    45 		User::Leave(KErrNotSupported);
    46 		}
    47 	
    48 	CA2dpBTHeadsetAudioIfSession* session = CA2dpBTHeadsetAudioIfSession::NewL(iBTAudioInterface);
    49 	return session;
    50 	}
    51 
    52 CA2dpBTHeadsetAudioIfServer::CA2dpBTHeadsetAudioIfServer() :
    53 							 CMmfIpcServer(EPriorityStandard)
    54 	{
    55 	}
    56 	
    57 void CA2dpBTHeadsetAudioIfServer::ConstructL()
    58 	{
    59 	// Create the interface to the BT headset
    60 	iBTAudioInterface = CA2dpBTHeadsetAudioInterface::NewL();
    61 	
    62 	// Call base class to Start server
    63 	TName name(RThread().Name());
    64 	StartL(name);
    65 	}
    66 
    67 
    68 /*
    69  Session implementation.
    70  */
    71 CA2dpBTHeadsetAudioIfSession* CA2dpBTHeadsetAudioIfSession::NewL( CA2dpBTHeadsetAudioInterface* 
    72 																	aBTAudioInterface)
    73 	{
    74 	CA2dpBTHeadsetAudioIfSession* self = new(ELeave) CA2dpBTHeadsetAudioIfSession(aBTAudioInterface);
    75 	CleanupStack::PushL(self);
    76 	self->ConstructL();
    77 	CleanupStack::Pop(self);
    78 	return self;
    79 	}
    80 	
    81 CA2dpBTHeadsetAudioIfSession::CA2dpBTHeadsetAudioIfSession(CA2dpBTHeadsetAudioInterface* aBTAudioInterface) :
    82 							iBTAudioInterface(aBTAudioInterface)
    83 	{
    84 	}
    85 
    86 void CA2dpBTHeadsetAudioIfSession::ConstructL()
    87 	{
    88 	// Create the AO event handlers
    89 	iInitHandler = CA2dpBTHeadsetIfEventHandler::NewL();
    90 	iOpenDeviceHandler = CA2dpBTHeadsetIfEventHandler::NewL();
    91 	iCloseDeviceHandler = CA2dpBTHeadsetIfEventHandler::NewL();
    92 	iPlayDataHandler = CA2dpBTHeadsetIfEventHandler::NewL();
    93 	iNotifyErrorHandler = CA2dpBTHeadsetIfEventHandler::NewL();
    94 	}
    95 
    96 CA2dpBTHeadsetAudioIfSession::~CA2dpBTHeadsetAudioIfSession()
    97 	{
    98 	delete iInitHandler;
    99 	delete iOpenDeviceHandler;
   100 	delete iCloseDeviceHandler;
   101 	delete iPlayDataHandler;
   102 	delete iNotifyErrorHandler;
   103 	}
   104 	
   105 void CA2dpBTHeadsetAudioIfSession::ServiceL(const RMessage2& aMessage)
   106 	{
   107 	// Service the message
   108 	TBool complete = EFalse;
   109 	TInt err = KErrNone;
   110 	switch(aMessage.Function())
   111 		{
   112 	case EBTAudioServerInitialize:
   113 		complete = DoInitializeL(aMessage);
   114 		break;
   115 	case EBTAudioServerCancelInitialize:
   116 		complete = DoCancelInitializeL(aMessage);
   117 		break;
   118 	case EBTAudioServerCopyFourCCArrayData:
   119 		complete = DoCopyFourCCArrayDataL(aMessage);
   120 		break;
   121 	case EBTAudioServerCopyChannelsArrayData:
   122 		complete = DoCopyChannelsArrayDataL(aMessage);
   123 		break;
   124 	case EBTAudioServerGetSupportedDataTypes:
   125 		err = DoGetSupportedDataTypesL(aMessage);
   126 		aMessage.Complete(err);
   127 		break;
   128 	case EBTAudioServerGetSupportedSampleRates:
   129 		err = DoGetSupportedSampleRatesL(aMessage);
   130 		aMessage.Complete(err);
   131 		break;
   132 	case EBTAudioServerGetSupportedSampleRatesDiscrete:
   133 		complete = DoGetSupportedSampleRatesDiscreteL(aMessage);
   134 		break;
   135 	case EBTAudioServerGetSupportedSampleRatesRange:
   136 		complete = DoGetSupportedSampleRatesRangeL(aMessage);
   137 		break;
   138 	case EBTAudioServerGetSupportedChannels:
   139 		err = DoGetSupportedChannelsL(aMessage);
   140 		aMessage.Complete(err);
   141 		break;
   142 	case EBTAudioServerSetDataType:
   143 		err = DoSetDataTypeL(aMessage);
   144 		aMessage.Complete(err);
   145 		break;
   146 	case EBTAudioServerSetSampleRate:
   147 		err = DoSetSampleRateL(aMessage);
   148 		aMessage.Complete(err);
   149 		break;
   150 	case EBTAudioServerSetChannels:
   151 		err = DoSetChannelsL(aMessage);
   152 		aMessage.Complete(err);
   153 		break;
   154 	case EBTAudioServerOpenDevice:
   155 		complete = DoOpenDeviceL(aMessage);
   156 		break;
   157 	case EBTAudioServerCancelOpenDevice:
   158 		complete = DoCancelOpenDevice(aMessage);
   159 		break;
   160 	case EBTAudioServerCloseDevice:
   161 		complete = DoCloseDeviceL(aMessage);
   162 		break;
   163 	case EBTAudioServerVolume:
   164 		complete = DoVolumeL(aMessage);
   165 		break;
   166 	case EBTAudioServerSetVolume:
   167 		err = DoSetVolumeL(aMessage);
   168 		aMessage.Complete(err);
   169 		break;
   170 	case EBTAudioServerPlayData:
   171 		complete = DoPlayDataL(aMessage);
   172 		break;
   173 	case EBTAudioServerCancelPlayData:
   174 		complete = DoCancelPlayDataL(aMessage);
   175 		break;
   176 	case EBTAudioServerFlushBuffer:
   177 		complete = DoFlushBufferL(aMessage);
   178 		break;
   179 	case EBTAudioServerBytesPlayed:
   180 		complete = DoBytesPlayedL(aMessage);
   181 		break;
   182 	case EBTAudioServerResetBytesPlayed:
   183 		complete = DoResetBytesPlayedL(aMessage);
   184 		break;
   185 	case EBTAudioServerPauseBuffer:
   186 		complete = DoPauseBufferL(aMessage);
   187 		break;
   188 	case EBTAudioServerResumePlaying:
   189 		complete = DoResumePlayingL(aMessage);
   190 		break;
   191 	case EBTAudioServerNotifyError:
   192 		complete = DoNotifyErrorL(aMessage);
   193 		break;
   194 	case EBTAudioServerCancelNotifyError:
   195 		complete = DoCancelNotifyErrorL(aMessage);
   196 		break;
   197 	default:
   198 		User::Leave(KErrNotSupported);
   199 		break;
   200 		}
   201 
   202 	if (complete)
   203 		{
   204 		aMessage.Complete(KErrNone);
   205 		}
   206 	}
   207 
   208 TBool CA2dpBTHeadsetAudioIfSession::DoInitializeL(const RMmfIpcMessage& aMessage)
   209 	{
   210 	// Get the address from the message
   211 	TPckgBuf<TBTDevAddr> btAddrPckg;
   212 	aMessage.ReadL(0, btAddrPckg);
   213 	TBTDevAddr& devAddr = btAddrPckg();
   214 	iInitHandler->StartL(aMessage);
   215 	iBTAudioInterface->Initialize(devAddr, iInitHandler->iStatus);
   216 		
   217 	return EFalse;
   218 	}
   219 
   220 TBool CA2dpBTHeadsetAudioIfSession::DoCancelInitializeL(const RMmfIpcMessage& /*aMessage*/)
   221 	{
   222 	iBTAudioInterface->CancelInitialize();
   223 	iInitHandler->Stop();
   224 	return ETrue;
   225 	}
   226 
   227 TBool CA2dpBTHeadsetAudioIfSession::DoCopyFourCCArrayDataL(const RMmfIpcMessage& aMessage)
   228 	{
   229 	const TInt KBufExpandSize8 = 8;//two TInts
   230 	CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
   231 	CleanupStack::PushL(dataCopyBuffer);
   232 	RBufWriteStream stream;
   233 	stream.Open(*dataCopyBuffer);
   234 	CleanupClosePushL(stream);
   235 	for (TInt i = 0; i < iFourCCArray.Count(); i++)
   236 		{
   237 		stream.WriteInt32L(iFourCCArray[i].FourCC());
   238 		}
   239 	aMessage.WriteL(0, dataCopyBuffer->Ptr(0));
   240 	stream.Close();
   241 	CleanupStack::PopAndDestroy(2);//dataCopyBuffer, stream
   242 	return ETrue;
   243 	}
   244 
   245 TBool CA2dpBTHeadsetAudioIfSession::DoCopyUintArrayDataL(const RMmfIpcMessage& aMessage, RArray<TUint> aArray)
   246 	{
   247 	const TInt KBufExpandSize8 = 8;//two TInts
   248 	CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
   249 	CleanupStack::PushL(dataCopyBuffer);
   250 	RBufWriteStream stream;
   251 	stream.Open(*dataCopyBuffer);
   252 	CleanupClosePushL(stream);
   253 	for (TInt i = 0; i < aArray.Count(); i++)
   254 		{
   255 		stream.WriteInt32L(aArray[i]);
   256 		}
   257 	aMessage.WriteL(0, dataCopyBuffer->Ptr(0));
   258 	stream.Close();
   259 	CleanupStack::PopAndDestroy(2);//dataCopyBuffer, stream	
   260 	return ETrue;
   261 	}
   262 
   263 TInt CA2dpBTHeadsetAudioIfSession::DoGetSupportedDataTypesL(const RMmfIpcMessage& aMessage)
   264 	{
   265 	iFourCCArray.Reset();
   266 
   267 	TInt err = iBTAudioInterface->GetSupportedDataTypes(iFourCCArray);
   268 
   269 	TPckgBuf<TInt> pckg;
   270 	pckg() = iFourCCArray.Count();
   271 	aMessage.WriteL(TInt(0),pckg);	
   272 	
   273 	return err;
   274 	}
   275 
   276 TInt CA2dpBTHeadsetAudioIfSession::DoGetSupportedSampleRatesL(const RMmfIpcMessage& aMessage)
   277 	{
   278 	iDiscreteArray.Reset();
   279 	iRangeArray.Reset();
   280 	
   281 	TInt err = iBTAudioInterface->GetSupportedSampleRates(iDiscreteArray, iRangeArray);
   282 	
   283 	TPckgBuf<TRatesArrayElements> pckg;
   284 	pckg().iDiscrete = iDiscreteArray.Count();
   285 	pckg().iRange = iRangeArray.Count();
   286 	
   287 	aMessage.WriteL(0, pckg);
   288 	
   289 	return err;
   290 	}
   291 
   292 TBool CA2dpBTHeadsetAudioIfSession::DoGetSupportedSampleRatesDiscreteL(const RMmfIpcMessage& aMessage)
   293 	{
   294 	return DoCopyUintArrayDataL(aMessage, iDiscreteArray);
   295 	}
   296 
   297 TBool CA2dpBTHeadsetAudioIfSession::DoGetSupportedSampleRatesRangeL(const RMmfIpcMessage& aMessage)
   298 	{
   299 	const TInt KBufExpandSize8 = 8;//two TInts
   300 	CBufFlat* dataCopyBuffer = CBufFlat::NewL(KBufExpandSize8);
   301 	CleanupStack::PushL(dataCopyBuffer);
   302 	RBufWriteStream stream;
   303 	stream.Open(*dataCopyBuffer);
   304 	CleanupClosePushL(stream);
   305 	for (TInt i = 0; i < iRangeArray.Count(); i++)
   306 		{
   307 		stream.WriteInt32L(iRangeArray[i].iLow);
   308 		stream.WriteInt32L(iRangeArray[i].iHigh);
   309 		}
   310 	aMessage.WriteL(0, dataCopyBuffer->Ptr(0));
   311 	stream.Close();
   312 	CleanupStack::PopAndDestroy(2);//dataCopyBuffer, stream
   313 	return ETrue;
   314 	}
   315 
   316 TInt CA2dpBTHeadsetAudioIfSession::DoGetSupportedChannelsL(const RMmfIpcMessage& aMessage)
   317 	{
   318 	// Array of uints
   319 	iStereoSupportArray.Reset();
   320 	TMMFStereoSupport stereoSupport;
   321 
   322 	TInt err = iBTAudioInterface->GetSupportedChannels(iStereoSupportArray, stereoSupport);
   323 	
   324 	TPckgBuf<TChannelsSupport> pckg;
   325 	pckg().iElementCount = iStereoSupportArray.Count();
   326 	pckg().iSupport = stereoSupport;
   327 	
   328 	aMessage.WriteL(0, pckg);
   329 	
   330 	return err;
   331 	}
   332 
   333 TBool CA2dpBTHeadsetAudioIfSession::DoCopyChannelsArrayDataL(const RMmfIpcMessage& aMessage)
   334 	{
   335 	return DoCopyUintArrayDataL(aMessage, iStereoSupportArray);
   336 	}
   337 
   338 TInt CA2dpBTHeadsetAudioIfSession::DoSetDataTypeL(const RMmfIpcMessage& aMessage)
   339 	{
   340 	TPckgBuf<TFourCC> dataTypePckg;
   341 	aMessage.ReadL(0, dataTypePckg);
   342 	TFourCC dataType = dataTypePckg();
   343 	return iBTAudioInterface->SetDataType(dataType);
   344 	}
   345 
   346 TInt CA2dpBTHeadsetAudioIfSession::DoSetSampleRateL(const RMmfIpcMessage& aMessage)
   347 	{
   348 	TPckgBuf<TUint> ratePckg;
   349 	aMessage.ReadL(0, ratePckg);
   350 	TUint rate = ratePckg();
   351 	return iBTAudioInterface->SetSampleRate(rate);
   352 	}
   353 
   354 TInt CA2dpBTHeadsetAudioIfSession::DoSetChannelsL(const RMmfIpcMessage& aMessage)
   355 	{
   356 	TPckgBuf<TChannelsSupport> pckgBuf;
   357 	aMessage.ReadL(0, pckgBuf);
   358 	TChannelsSupport support = pckgBuf();
   359 	return iBTAudioInterface->SetChannels(support.iElementCount, support.iSupport);
   360 	}
   361 
   362 TBool CA2dpBTHeadsetAudioIfSession::DoOpenDeviceL(const RMmfIpcMessage& aMessage)
   363 	{
   364 	iOpenDeviceHandler->StartL(aMessage);
   365 	iBTAudioInterface->OpenDevice(iOpenDeviceHandler->iStatus);
   366 	return EFalse;
   367 	}
   368 
   369 TBool CA2dpBTHeadsetAudioIfSession::DoCancelOpenDevice(const RMmfIpcMessage& /*aMessage*/)
   370 	{
   371 	iBTAudioInterface->CancelOpenDevice();
   372 	return ETrue;
   373 	}
   374 	
   375 TBool CA2dpBTHeadsetAudioIfSession::DoCloseDeviceL(const RMmfIpcMessage& aMessage)
   376 	{
   377 	iCloseDeviceHandler->StartL(aMessage);
   378 	iBTAudioInterface->CloseDevice(iCloseDeviceHandler->iStatus);
   379 	return EFalse;
   380 	}
   381 
   382 TBool CA2dpBTHeadsetAudioIfSession::DoVolumeL(const RMmfIpcMessage& aMessage)
   383 	{	
   384 	TUint volume = iBTAudioInterface->Volume();
   385 	TPckgBuf<TUint> pckg(volume);
   386 	aMessage.WriteL(0, pckg);
   387 	return ETrue;
   388 	}
   389 
   390 TInt CA2dpBTHeadsetAudioIfSession::DoSetVolumeL(const RMmfIpcMessage& aMessage)
   391 	{
   392 	TPckgBuf<TUint> pckg;
   393 	aMessage.ReadL(0, pckg);
   394 	TUint volume = pckg();
   395 	return iBTAudioInterface->SetVolume(volume);
   396 	}
   397 
   398 TBool CA2dpBTHeadsetAudioIfSession::DoPlayDataL(const RMmfIpcMessage& aMessage)
   399 	{
   400 	// Client's in the same process so access the buffer directly
   401 	const TPtr8* ptr = static_cast<const TPtr8*>(aMessage.Ptr0());
   402 	iPlayDataHandler->StartL(aMessage);
   403 	iBTAudioInterface->PlayData(*ptr, iPlayDataHandler->iStatus);
   404 	return EFalse;
   405 	}
   406 
   407 TBool CA2dpBTHeadsetAudioIfSession::DoCancelPlayDataL(const RMmfIpcMessage& /*aMessage*/)
   408 	{
   409 	iBTAudioInterface->CancelPlayData();
   410 	iPlayDataHandler->Stop();
   411 	return ETrue;
   412 	}
   413 
   414 TBool CA2dpBTHeadsetAudioIfSession::DoFlushBufferL(const RMmfIpcMessage& /*aMessage*/)
   415 	{
   416 	iBTAudioInterface->FlushBuffer();
   417 	return ETrue;
   418 	}
   419 
   420 TBool CA2dpBTHeadsetAudioIfSession::DoBytesPlayedL(const RMmfIpcMessage& aMessage)
   421 	{
   422 	TUint bytesPlayed = iBTAudioInterface->BytesPlayed();
   423 	TPckgBuf<TUint> pckg(bytesPlayed);
   424 	aMessage.WriteL(0, pckg);
   425 	return ETrue;
   426 	}
   427 
   428 TBool CA2dpBTHeadsetAudioIfSession::DoResetBytesPlayedL(const RMmfIpcMessage& /*aMessage*/)
   429 	{
   430 	iBTAudioInterface->ResetBytesPlayed();
   431 	return ETrue;
   432 	}
   433 
   434 TBool CA2dpBTHeadsetAudioIfSession::DoPauseBufferL(const RMmfIpcMessage& /*aMessage*/)
   435 	{
   436 	iBTAudioInterface->PauseBuffer();
   437 	return ETrue;
   438 	}
   439 
   440 TBool CA2dpBTHeadsetAudioIfSession::DoResumePlayingL(const RMmfIpcMessage& /*aMessage*/)
   441 	{
   442 	iBTAudioInterface->ResumePlaying();
   443 	return ETrue;
   444 	}
   445 
   446 TBool CA2dpBTHeadsetAudioIfSession::DoNotifyErrorL(const RMmfIpcMessage& aMessage)
   447 	{
   448 	iNotifyErrorHandler->StartL(aMessage);
   449 	iBTAudioInterface->NotifyError(iNotifyErrorHandler->iStatus);
   450 	return EFalse;
   451 	}
   452 
   453 TBool CA2dpBTHeadsetAudioIfSession::DoCancelNotifyErrorL(const RMmfIpcMessage& /*aMessage*/)
   454 	{
   455 	iBTAudioInterface->CancelNotifyError();
   456 	iNotifyErrorHandler->Stop();
   457 	return ETrue;
   458 	}
   459 
   460 /**
   461  * Implementation of Active Object to handle asynch requests to the Bluetooth interface.
   462  */
   463 CA2dpBTHeadsetIfEventHandler* CA2dpBTHeadsetIfEventHandler::NewL()
   464 	{
   465 	CA2dpBTHeadsetIfEventHandler* self = new(ELeave) CA2dpBTHeadsetIfEventHandler();
   466 	CleanupStack::PushL(self);
   467 	self->ConstructL();
   468 	CleanupStack::Pop(self);
   469 	return self;
   470 	}
   471 	
   472 CA2dpBTHeadsetIfEventHandler::~CA2dpBTHeadsetIfEventHandler()
   473 	{
   474 	Cancel();
   475 	delete iMessage;
   476 	}
   477 
   478 void CA2dpBTHeadsetIfEventHandler::RunL()
   479 	{
   480 	TInt err = iStatus.Int();
   481 	// Complete the message
   482 	iMessage->Complete(err);
   483 	delete iMessage;
   484 	iMessage = NULL;
   485 	}
   486 
   487 void CA2dpBTHeadsetIfEventHandler::DoCancel()
   488 	{
   489 	if (iMessage)
   490 		{
   491 		iMessage->Complete(KErrCancel);		
   492 		}
   493 	}
   494 	
   495 CA2dpBTHeadsetIfEventHandler::CA2dpBTHeadsetIfEventHandler() : CActive(EPriorityStandard)
   496 	{
   497 	CActiveScheduler::Add(this);
   498 	}
   499 
   500 void CA2dpBTHeadsetIfEventHandler::ConstructL()
   501 	{
   502 	}
   503 
   504 void CA2dpBTHeadsetIfEventHandler::StartL(const RMmfIpcMessage& aMessage)
   505 	{
   506 	// take a copy of the message to complete later
   507 	delete iMessage;	// ensure we only have one message!
   508 	iMessage = NULL;
   509 	iMessage = new(ELeave) RMmfIpcMessage(aMessage);
   510 
   511 	if (!IsActive())
   512 		{
   513 		SetActive();
   514 		}
   515 	}
   516 	
   517 void CA2dpBTHeadsetIfEventHandler::Stop()
   518 	{
   519 	Cancel();
   520 	}