bsptemplate/asspandvariant/template_variant/specific/soundsc_tx.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsptemplate/asspandvariant/template_variant/specific/soundsc_tx.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,553 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// template\template_variant\specific\soundsc_tx.cpp
+// Implementation of the Template playback shared chunk sound physical device driver (PDD).
+// This file is part of the Template Base port
+// 
+//
+
+/**
+ @file
+*/
+
+#include "soundsc_plat.h"
+
+// TO DO: (mandatory)
+// Declare a name for this driver. The format of this name should be
+// "SoundSc.xxxx" where xxxx is the variant name.
+_LIT(KSoundScPddName,"SoundSc.Template");
+
+// Definitions for the kernel thread created for this sound driver.
+_LIT(KSoundScDriverThreadName,"SoundDriverThread");
+const TInt KSoundScDriverThreadPriority=26;				// One less than DFC thread 0
+
+/**
+Define a function at ordinal 0 which returns a new instance of a DPhysicalDevice-derived factory class.
+*/
+DECLARE_STANDARD_PDD()
+	{
+	return new DTemplateSoundScPddFactory;
+	}
+
+/**
+Constructor for the shared chunk sound PDD factory class.
+*/
+DTemplateSoundScPddFactory::DTemplateSoundScPddFactory()
+	{	
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScPddFactory::DTemplateSoundScPddFactory"));
+
+//	iDfcQ=NULL;
+	
+	// Support units KSoundScTxUnit0 & KSoundScRxUnit0.
+    iUnitsMask=(1<<KSoundScRxUnit0)|(1<<KSoundScTxUnit0);
+
+    // Set version number for this device.
+	iVersion=RSoundSc::VersionRequired();
+	}
+
+/**
+Destructor for the shared chunk sound PDD factory class.
+*/
+DTemplateSoundScPddFactory::~DTemplateSoundScPddFactory()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScPddFactory::~DTemplateSoundScPddFactory"));
+	
+	// Destroy the kernel thread.
+	if (iDfcQ)
+		iDfcQ->Destroy();
+	}
+	
+/**
+Second stage constructor for the shared chunk sound PDD factory class.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScPddFactory::Install()
+	{
+	TInt r=KErrNone;
+	if (iDfcQ==NULL)
+		{
+		// Create a new sound driver DFC queue (and associated kernel thread). 
+		r=Kern::DynamicDfcQCreate(iDfcQ,KSoundScDriverThreadPriority,KSoundScDriverThreadName);
+		}
+	
+	if (r==KErrNone)
+		{
+		r=SetName(&KSoundScPddName); 				// Set the name of the driver object
+		}
+	
+	__KTRACE_SND(Kern::Printf("<DTemplateSoundScPddFactory::Install - %d",r));
+	return(r);
+	}
+	
+/**
+Returns the PDD's capabilities. This is not used by the Symbian OS device driver framework
+or by the LDD.
+@param aDes A descriptor to write capabilities information into
+*/
+void DTemplateSoundScPddFactory::GetCaps(TDes8& /*aDes*/) const
+	{}
+
+/**
+Called by the kernel's device driver framework to check if this PDD is suitable for use
+with a logical channel.
+This is called in the context of the client thread which requested the creation of a logical
+channel - through a call to RBusLogicalChannel::DoCreate().
+The thread is in a critical section.
+@param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate().
+@param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate() - not used.
+@param aVer The version number of the logical channel which will use this physical channel. 
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScPddFactory::Validate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
+	{
+	// Check that the version specified is compatible.
+	if (!Kern::QueryVersionSupported(RSoundSc::VersionRequired(),aVer))
+		return(KErrNotSupported);
+	
+	// Check the unit number is compatible
+	if (aUnit!=KSoundScTxUnit0 && aUnit!=KSoundScRxUnit0)
+		return(KErrNotSupported);
+		
+	return(KErrNone);
+	}
+
+/**
+Called by the kernel's device driver framework to create a physical channel object.
+This is called in the context of the client thread which requested the creation of a logical
+channel - through a call to RBusLogicalChannel::DoCreate().
+The thread is in a critical section.
+@param aChannel Set by this function to point to the created physical channel object.
+@param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate().
+@param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate().
+@param aVer The version number of the logical channel which will use this physical channel. 
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScPddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScPddFactory::Create"));
+
+	// Create the appropriate PDD channel object.
+	TInt r=KErrNoMemory;
+	if (aUnit==KSoundScRxUnit0)
+		{
+		// Create a record PDD channel object
+		DTemplateSoundScRxPdd* pD=new DTemplateSoundScRxPdd;
+		aChannel=pD;
+		if (pD)
+			{
+			pD->iPhysicalDevice=this;
+			r=pD->DoCreate();
+			}
+		}
+		
+	else
+		{
+		// Create a playback PDD channel object
+		DTemplateSoundScTxPdd* pD=new DTemplateSoundScTxPdd;
+		aChannel=pD;
+		if (pD)
+			{
+			pD->iPhysicalDevice=this;
+			r=pD->DoCreate();
+			}
+		}
+	return(r);
+	}
+
+
+/**
+Constructor for the Template playback shared chunk sound driver physical device driver (PDD).
+*/
+DTemplateSoundScTxPdd::DTemplateSoundScTxPdd()
+	{		
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::DTemplateSoundScTxPdd"));
+	
+//	iDmaChan=NULL;
+//	iPendingPlay=0;
+//	iFlag=0;
+	}
+	
+/**
+Destructor for the Template playback shared chunk sound driver physical device driver (PDD).
+*/
+DTemplateSoundScTxPdd::~DTemplateSoundScTxPdd()
+	{
+	// Delete the DMA request objects
+	for (TInt i=0; i<KTemplateMaxTxDmaRequests; i++)
+		{
+		if (iDmaRequest[i])
+			delete iDmaRequest[i];
+		}
+	
+	// Close the DMA channel.
+	if (iDmaChannel)
+		iDmaChannel->Close();
+	}
+	
+/**
+Second stage constructor for the Template playback shared chunk sound driver physical device driver (PDD).
+Note that this constructor is called before the second stage constructor for the LDD so it is not
+possible to call methods on the LDD here.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/	
+TInt DTemplateSoundScTxPdd::DoCreate()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::DoCreate"));
+		
+	SetCaps();								// Setup the capabilities of this device.
+	
+	// Setup a DMA channel for playback
+	// TO DO: (mandatory)
+	// Setup the DMA channel information for this play device.
+	TDmaChannel::SCreateInfo info;
+//	info.iCookie=???
+	info.iDfcQ=DfcQ(KSoundScTxUnit0);
+//	info.iDfcPriority=???
+	info.iDesCount=KTemplateMaxTxDmaRequests;
+	// coverity[uninit_use_in_call]
+	// The values info.iCookie and info.iDfcPriority are to be initialized when implemented
+	TInt r=TDmaChannel::Open(info,iDmaChannel);
+	
+	// Create the DMA request objects for use with the DMA channel.
+	if (r==KErrNone)
+		{
+		for (TInt i=0; i<KTemplateMaxTxDmaRequests; i++)
+			{
+			iDmaRequest[i] = new DTemplateSoundScTxDmaRequest(*iDmaChannel,this);
+			if (iDmaRequest[i] == NULL)
+				{
+				r=KErrNoMemory;
+				break;
+				}
+			}
+		}
+	
+	__KTRACE_SND(Kern::Printf("<DTemplateSoundScTxPdd::DoCreate - %d",r));
+	return(r);
+	}
+	
+/**
+Return the DFC queue to be used by this playback device.
+@return The DFC queue to use.
+*/	
+TDfcQue* DTemplateSoundScTxPdd::DfcQ(TInt /*aUnit*/)
+	{
+	return(iPhysicalDevice->iDfcQ);
+	}
+		
+/** 
+Called from the LDD to return the shared chunk create information to be used by this play device.
+@param aChunkCreateInfo A chunk create info. object to be to be filled with the settings
+						required for this device.
+*/		
+void DTemplateSoundScTxPdd::GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo)
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::GetChunkCreateInfo"));
+
+	// TO DO: (mandatory)
+	// Setup the shared chunk create information in aChunkCreateInfo for this play device.
+	aChunkCreateInfo.iType=TChunkCreateInfo::ESharedKernelMultiple;
+//	aChunkCreateInfo.iMapAttr=???
+	aChunkCreateInfo.iOwnsMemory=ETrue; 				// Using RAM pages.
+	aChunkCreateInfo.iDestroyedDfc=NULL; 				// No chunk destroy DFC.
+	}
+
+/**
+Called from the LDD to return the capabilities of this device.
+@param aCapsBuf A packaged TSoundFormatsSupportedV02 object to be filled with the play
+				capabilities of this device. This descriptor is in kernel memory and can be accessed directly.
+@see TSoundFormatsSupportedV02.
+*/
+void DTemplateSoundScTxPdd::Caps(TDes8& aCapsBuf) const
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::Caps"));
+	
+	// Copy iCaps back.
+	TPtrC8 ptr((const TUint8*)&iCaps,sizeof(iCaps));
+	aCapsBuf.FillZ(aCapsBuf.MaxLength());
+	aCapsBuf=ptr.Left(Min(ptr.Length(),aCapsBuf.MaxLength()));		
+	}
+
+/**
+Called from the LDD to return the maximum transfer length in bytes that this device can support in a single data transfer.
+@return The maximum transfer length in bytes.
+*/
+TInt DTemplateSoundScTxPdd::MaxTransferLen() const
+	{
+	return(KTemplateMaxTxDmaTransferLen);
+	}
+
+/**
+Called from the LDD to configure or reconfigure the device using the the configuration supplied.
+@param aConfigBuf A packaged TCurrentSoundFormatV02 object which contains the new configuration settings.
+				  This descriptor is in kernel memory and can be accessed directly.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+@see TCurrentSoundFormatV02.
+*/	
+TInt DTemplateSoundScTxPdd::SetConfig(const TDesC8& aConfigBuf)
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::SetConfig"));
+	
+	// Read the new configuration from the LDD.
+	TCurrentSoundFormatV02 config;
+	TPtr8 ptr((TUint8*)&config,sizeof(config));
+	Kern::InfoCopy(ptr,aConfigBuf);
+	
+	// TO DO: (mandatory)
+	// Apply the specified audio configuration to the audio device.
+	TInt r=KErrNone;
+	
+	__KTRACE_SND(Kern::Printf("<DTemplateSoundScTxPdd::SetConfig - %d",r));
+	return(r);
+	}
+	
+/**
+Called from the LDD to set the play volume.
+@param aVolume The play volume to be set - a value in the range 0 to 255. The value 255 equates
+	to the maximum volume and each value below this equates to a 0.5dB step below it.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::SetVolume(TInt aVolume)
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::SetVolume"));
+    
+    // TO DO: (mandatory)
+	// Set the specified play volume on the audio device.
+	TInt r=KErrNone;
+    
+	return(r);
+	}
+		
+/**
+Called from the LDD to prepare the audio device for playback.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::StartTransfer()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::StartTransfer"));
+	
+	// TO DO: (mandatory)
+	// Prepare the audio device for playback.
+	TInt r=KErrNone;
+    
+    __KTRACE_SND(Kern::Printf("<DTemplateSoundScTxPdd::StartTransfer - %d",r));
+    return(r);
+	}
+
+/**
+Called from the LDD to initiate the playback of a portion of data to the audio device.
+When the transfer is complete, the PDD signals this event using the LDD function PlayCallback().
+@param aTransferID A value assigned by the LDD to allow it to uniquely identify a particular transfer fragment.
+@param aLinAddr The linear address within the shared chunk of the start of the data to be played.
+@param aPhysAddr The physical address within the shared chunk of the start of the data to be played.
+@param aNumBytes The number of bytes to be played. 
+@return KErrNone if the transfer has been initiated successfully;
+  		KErrNotReady if the device is unable to accept the transfer for the moment;
+		otherwise one of the other system-wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr /*aPhysAddr*/,TInt aNumBytes)
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::TransferData(ID:%xH,Addr:%xH,Len:%d)",aLinAddr,aNumBytes));
+		
+	TInt r=KErrNone;
+	
+	// Check that we can accept the request
+	if (iPendingPlay>=KTemplateMaxTxDmaRequests)
+		r=KErrNotReady;
+	else
+		{
+		// Start a DMA transfer.
+		iDmaRequest[iFlag]->iTransferID=aTransferID;
+		iDmaRequest[iFlag]->iTransferSize=aNumBytes;
+		// TO DO: (mandatory)
+		// Supply the DMA destination information.
+		TUint32 dest=0; // ???
+		r=iDmaRequest[iFlag]->Fragment(aLinAddr,dest,aNumBytes,KDmaMemSrc|KDmaIncSrc,0);
+		if (r==KErrNone)
+			{
+			iDmaRequest[iFlag]->Queue();
+			iPendingPlay++;
+			if ((++iFlag)>=KTemplateMaxTxDmaRequests)
+				iFlag=0;
+			
+			// TO DO: (mandatory)
+			// Start the audio device transfering data.
+			}
+		}
+											
+	__KTRACE_SND(Kern::Printf("<DTemplateSoundScTxPdd::TransferData - %d",r));	
+	return(r);
+	}
+
+/**
+Called from the LDD to terminate the playback of a data to the device and to release any resources necessary for playback.
+This is called soon after the last pending play request from the client has been completed. Once this function had been
+called, the LDD will not issue any further TransferData() commands without first issueing a StartTransfer() command. 
+*/
+void DTemplateSoundScTxPdd::StopTransfer()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::StopTransfer"));
+
+    // Stop the DMA channel.
+    iDmaChannel->CancelAll();
+	iFlag=0;
+    iPendingPlay=0;
+    
+    // TO DO: (mandatory)
+	// Stop the audio device transfering data.
+	}
+
+/**
+Called from the LDD to halt the playback of data to the sound device but not to release any resources necessary for
+playback.
+If possible, any active transfer should be suspended in such a way that it can be resumed later - starting from next
+sample following the one last played.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::PauseTransfer()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::PauseTransfer"));
+	
+	// TO DO: (mandatory)
+	// Halt playback on the audio device.
+	TInt r=KErrNone;
+    
+	return(r);
+	}
+	
+/**
+Called from the LDD to resume the playback of data to the sound device following a request to halt playback.
+If possible, any transfer which was active when the device was halted should be resumed - starting from next sample
+following the one last played. Once complete, it should be reported using PlayCallback()
+as normal. 
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::ResumeTransfer()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::ResumeTransfer"));
+	
+	// TO DO: (mandatory)
+	// Resume playback on the audio device.
+	TInt r=KErrNone;
+			
+	return(r);
+	}
+
+/**
+Called from the LDD to power up the sound device when the channel is first opened and if ever the phone is brought out
+of standby mode.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::PowerUp()
+	{
+	// TO DO: (mandatory)
+	// Power up the audio device.
+	
+	return(KErrNone);
+	}
+
+/**
+Called from the LDD to power down the sound device when the channel is closed and just before the phone powers down when
+being turned off or going into standby.
+*/
+void DTemplateSoundScTxPdd::PowerDown()
+	{
+	// TO DO: (mandatory)
+	// Power down the audio device.
+	}
+	
+/**
+Called from the LDD to handle a custom configuration request.
+@param aFunction A number identifying the request.
+@param aParam A 32-bit value passed to the driver. Its meaning depends on the request.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateSoundScTxPdd::CustomConfig(TInt /*aFunction*/,TAny* /*aParam*/)
+	{
+	return(KErrNotSupported);
+	}	
+
+/**
+Called from the LDD to find out how many microseconds of data have been played.  This is called
+in the context of the DFC thread.
+@param aTimeTransferred	A reference to a variable into which to place the number of microseconds of audio.
+@param aStatus			The current status of this channel
+@return KErrNone if time is valid or KErrNotSupported.
+*/
+TInt DTemplateSoundScTxPdd::TimeTransferred(TInt64& aTimeTransferred, TInt aStatus)
+	{
+	return(KErrNotSupported);
+	}
+
+/**
+Called each time a playback DMA transfer completes - from the DMA callback function in the sound thread's DFC context.
+@param aTransferID The transfer ID of the DMA transfer.
+@param aTransferResult The result of the DMA transfer.
+@param aBytesTransferred The number of bytes transferred.
+*/	
+void DTemplateSoundScTxPdd::PlayCallback(TUint aTransferID,TInt aTransferResult,TInt aBytesTransferred)
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::PlayCallback"));
+	
+	iPendingPlay--;
+		
+	Ldd()->PlayCallback(aTransferID,aTransferResult,aBytesTransferred);
+	}
+
+/**
+Initialise the data member DTemplateSoundScTxPdd::iCaps with the play capabilities of this audio playback device.
+*/	
+void DTemplateSoundScTxPdd::SetCaps()
+	{
+	__KTRACE_SND(Kern::Printf(">DTemplateSoundScTxPdd::SetCaps"));
+	
+	// The data transfer direction for this unit is play.
+	iCaps.iDirection=ESoundDirPlayback;
+	
+	// TO DO: (mandatory)
+	// Setup the rest of the capabilities structure DTemplateSoundScTxPdd::iCaps with the capabilities of this
+	// audio playback device.
+	}	
+
+/**
+Constructor for a shared chunk sound driver playback DMA request.
+*/
+DTemplateSoundScTxDmaRequest::DTemplateSoundScTxDmaRequest(TDmaChannel& aChannel,DTemplateSoundScTxPdd* aPdd,TInt aMaxTransferSize)
+	: DDmaRequest(aChannel,DTemplateSoundScTxDmaRequest::DmaService,this,aMaxTransferSize),
+	  iPdd(aPdd)
+	{}
+	
+/**
+DMA tx service routine. Called in the sound thread's DFC context by the s/w DMA controller.
+@param aResult Status of DMA transfer.
+@param aArg Argument passed to DMA controller.
+*/	
+void DTemplateSoundScTxDmaRequest::DmaService(TResult aResult, TAny* aArg)
+	{
+	__KTRACE_SND(Kern::Printf(">SndTxDmaService - %d",aResult));
+	DTemplateSoundScTxDmaRequest& req=*(DTemplateSoundScTxDmaRequest*)aArg;
+	
+	TInt res=KErrNone;
+	TInt bytesTransferred=req.iTransferSize;
+	if (aResult!=DDmaRequest::EOk)
+		{
+		res=KErrCorrupt;
+		bytesTransferred=0;
+		}
+		
+	// Inform the LDD of the result of the transfer.
+	req.iPdd->PlayCallback(req.iTransferID,res,bytesTransferred);	
+	return;
+	}
+