--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/multimedia/t_sound_api.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1372 @@
+// 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:
+// e32test\multimedia\t_sound_api.cpp
+//
+//
+
+/**
+ @file Shared chunk sound driver API test code.
+*/
+
+#include <e32test.h>
+#include <f32file.h>
+#include "t_soundutils.h"
+
+#define CHECK(aValue) {Test(aValue);}
+#define CHECK_NOERROR(aValue) { TInt v=(aValue); if(v) { Test.Printf(_L("Error value = %d\n"),v); Test(EFalse,__LINE__); }}
+#define CHECK_EQUAL(aValue1,aValue2) { TInt v1=(aValue1); TInt v2=(aValue2); if(v1!=v2) { Test.Printf(_L("Error value = %d\n"),v1); Test(EFalse,__LINE__); }}
+
+_LIT(KSndLddFileName,"ESOUNDSC.LDD");
+_LIT(KSndPddFileName,"SOUNDSC.PDD");
+
+RTest Test(_L("T_SOUND_API"));
+RSoundSc TxSoundDevice;
+RSoundSc RxSoundDevice;
+
+TSoundFormatsSupportedV02Buf RecordCapsBuf;
+TSoundFormatsSupportedV02Buf PlayCapsBuf;
+TCurrentSoundFormatV02Buf PlayFormatBuf;
+TCurrentSoundFormatV02Buf RecordFormatBuf;
+
+LOCAL_C TInt Load()
+ {
+ TInt r;
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-219
+ @SYMTestCaseDesc Installing the PDD
+ @SYMTestPriority Critical
+ @SYMTestActions 1) Attempt to install the PDD (using User::LoadPhysicalDevice()).
+ 2) Without un-installing it, attempt to install it a second time.
+ @SYMTestExpectedResults 1) KErrNone - PDD loads successfully.
+ 2) Should fail with KErrAlreadyExists.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Start(_L("Load sound PDD"));
+ r=User::LoadPhysicalDevice(KSndPddFileName);
+ if (r==KErrNotFound)
+ {
+ Test.End();
+ return(r);
+ }
+ CHECK(r==KErrNone || r==KErrAlreadyExists);
+ r=User::LoadPhysicalDevice(KSndPddFileName);
+ CHECK(r==KErrAlreadyExists);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-220
+ @SYMTestCaseDesc Installing the LDD
+ @SYMTestPriority Critical
+ @SYMTestActions 1) Attempt to install the LDD (using User::LoadLogicalDevice()).
+ 2) Without un-installing it, attempt to install it a second time.
+ @SYMTestExpectedResults 1) KErrNone - LDD loads successfully.
+ 2) Should fail with KErrAlreadyExists.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Load sound LDD"));
+ r=User::LoadLogicalDevice(KSndLddFileName);
+ CHECK(r==KErrNone || r==KErrAlreadyExists);
+ r=User::LoadPhysicalDevice(KSndPddFileName);
+ CHECK(r==KErrAlreadyExists);
+
+ Test.End();
+ return(KErrNone);
+ }
+
+LOCAL_C void TestSetAudioFormat()
+ {
+ TInt r;
+ Test.Printf(_L("Testing setting the audio format\r\n"));
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-227
+ @SYMTestCaseDesc Setting the audio configuration - channel configuration.
+ @SYMTestPriority Critical
+ @SYMTestActions Read the audio capabilities of the playback channel. For each of the possible 6 channel
+ configurations, issue a request on the playback channel to set this audio configuration.
+ @SYMTestExpectedResults Either KErrNone if the playback channel supports the channel configuration, or
+ KErrNotSupported if the playback channel does not support the channel configuration.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Try to set every possible audio channel configuration"));
+ TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
+ TInt i;
+ for (i=0 ; i < 6 ; i++)
+ {
+ PlayFormatBuf().iChannels = (i+1);
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ if (PlayCapsBuf().iChannels & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ }
+ else
+ {
+ CHECK(r==KErrNotSupported); // Caps reports it is not supported
+ }
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-228
+ @SYMTestCaseDesc Setting the audio configuration - sample rate.
+ @SYMTestPriority Critical
+ @SYMTestActions Read the audio capabilities of the playback channel. For each of the possible 14 sample
+ rates, issue a request on the playback channel to set this audio configuration.
+ @SYMTestExpectedResults Either KErrNone if the playback channel supports the sample rate, or
+ KErrNotSupported if the playback channel does not support the sample rate.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Try to set every possible sample rate"));
+ TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
+ for (i=0 ; i <= (TInt)ESoundRate48000Hz ; i++)
+ {
+ PlayFormatBuf().iRate = (TSoundRate)i;
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ if (PlayCapsBuf().iRates & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ }
+ else
+ {
+ CHECK(r==KErrNotSupported); // Caps reports it is not supported
+ }
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-229
+ @SYMTestCaseDesc Setting the audio configuration - audio encoding.
+ @SYMTestPriority Critical
+ @SYMTestActions Read the audio capabilities of the playback channel. For each of the possible 3 audio
+ encodings, issue a request on the playback channel to set this audio configuration.
+ @SYMTestExpectedResults Either KErrNone if the playback channel supports the audio encoding, or
+ KErrNotSupported if the playback channel does not support the audio encoding.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Try to set every possible encoding"));
+ TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
+ for (i=0 ; i <= (TInt)ESoundEncoding24BitPCM ; i++)
+ {
+ PlayFormatBuf().iEncoding = (TSoundEncoding)i;
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ if (PlayCapsBuf().iEncodings & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ }
+ else
+ {
+ CHECK(r==KErrNotSupported); // Caps reports it is not supported
+ }
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-230
+ @SYMTestCaseDesc Setting the audio configuration - audio data format.
+ @SYMTestPriority Critical
+ @SYMTestActions Read the audio capabilities of the playback channel. For each of the possible 2 audio data
+ formats, issue a request on the playback channel to set this audio configuration.
+ @SYMTestExpectedResults Either KErrNone if the playback channel supports the audio data format, or
+ KErrNotSupported if the playback channel does not support the audio data format.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Try to set every possible data format"));
+ TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
+ for (i=0 ; i <= (TInt)ESoundDataFormatNonInterleaved ; i++)
+ {
+ PlayFormatBuf().iDataFormat = (TSoundDataFormat)i;
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ if (PlayCapsBuf().iDataFormats & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ }
+ else
+ {
+ CHECK(r==KErrNotSupported); // Caps reports it is not supported
+ }
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-231
+ @SYMTestCaseDesc Setting the audio configuration - altering the configuration while transferring data.
+ @SYMTestPriority Critical
+ @SYMTestActions 1) Read the audio capabilities of the playback channel and apply a playback audio
+ configuration that is supported by channel. Set the play buffer configuration and
+ then start playing data from one of the buffers. While still playing, attempt to alter
+ the audio configuration of the playback channel.
+ 2) Read the audio capabilities of the record channel and apply an audio record
+ configuration that is supported by channel. Set the record buffer configuration and
+ then start recording data into one of the buffers. While still recording, attempt
+ to alter the audio configuration of the record channel.
+ @SYMTestExpectedResults 1) Altering the audio configuration should fail with KErrInUse.
+ 2) Altering the audio configuration should fail with KErrInUse.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Try to alter the audio format while playing"));
+
+ // Set the audio configuration of the playback channel ready to start playing
+ TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
+ if (PlayCapsBuf().iEncodings&KSoundEncoding16BitPCM)
+ PlayFormatBuf().iEncoding = ESoundEncoding16BitPCM;
+
+ PlayFormatBuf().iChannels = 2;
+
+ // find first supported rate and set the the audio configuration to use it
+ TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
+ for (i=0 ; i <= (TInt)ESoundRate48000Hz ; i++)
+ {
+ PlayFormatBuf().iRate = (TSoundRate)i;
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ if (PlayCapsBuf().iRates & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ break;
+ }
+ }
+
+ PrintConfig(PlayFormatBuf(),Test);
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ CHECK_NOERROR(r);
+
+ // Set the play buffer configuration.
+ RChunk chunk;
+ TInt bufSize=BytesPerSecond(PlayFormatBuf()); // Large enough to hold 1 second of data.
+ bufSize=ValidBufferSize(bufSize,PlayCapsBuf().iRequestMinSize,PlayFormatBuf()); // Keep the buffer length valid for driver.
+ TTestSharedChunkBufConfig bufferConfig;
+ bufferConfig.iNumBuffers=3;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iFlags=0;
+ TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
+ r=TxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ TxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+ CHECK(bufferConfig.iBufferSizeInBytes==bufSize);
+
+ // Start playing
+ r=MakeSineTable(PlayFormatBuf());
+ CHECK_NOERROR(r);
+ r=SetToneFrequency(660,PlayFormatBuf());
+ CHECK_NOERROR(r);
+ TPtr8 ptr(chunk.Base()+bufferConfig.iBufferOffsetList[0],bufSize);
+ WriteTone(ptr,PlayFormatBuf());
+ TRequestStatus stat;
+ TxSoundDevice.PlayData(stat,bufferConfig.iBufferOffsetList[0],bufSize,KSndFlagLastSample);
+
+ // Check that altering the audio format while playing - fails
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ CHECK(r==KErrInUse);
+
+ User::WaitForRequest(stat);
+ CHECK_EQUAL(stat.Int(),KErrNone);
+
+ Test.Next(_L("Try to alter the audio format while recording"));
+
+ // Set the audio configuration of the record channel ready to start recording
+ RxSoundDevice.AudioFormat(RecordFormatBuf); // Read back the current setting which must be valid.
+ if (RecordCapsBuf().iEncodings&KSoundEncoding16BitPCM)
+ RecordFormatBuf().iEncoding = ESoundEncoding16BitPCM;
+ RecordFormatBuf().iChannels = 2;
+
+ // find first supported rate and set the the audio configuration to use it
+ for (i=0 ; i <= (TInt)ESoundRate48000Hz ; i++)
+ {
+ RecordFormatBuf().iRate = (TSoundRate)i;
+ r=TxSoundDevice.SetAudioFormat(RecordFormatBuf);
+ if (RecordCapsBuf().iRates & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ break;
+ }
+ }
+
+ // Use the same shared chunk for recording
+ r=RxSoundDevice.SetBufferChunkOpen(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+
+ // Start recording
+ TInt length;
+ RxSoundDevice.RecordData(stat,length);
+
+ // Check that altering the audio format while recording - fails
+ r=RxSoundDevice.SetAudioFormat(RecordFormatBuf);
+ CHECK(r==KErrInUse);
+
+ User::WaitForRequest(stat);
+ TInt retOffset=stat.Int();
+ CHECK(retOffset>=0);
+ CHECK(length>0);
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK_NOERROR(r);
+
+ RxSoundDevice.CancelRecordData(); // Stop the driver from recording.
+ chunk.Close();
+ }
+
+LOCAL_C void TestSetBufferConfig(TInt aBufferConfigFlags)
+ {
+
+ Test.Printf(_L("Testing setting the buffer configuration\r\n"));
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-232
+ @SYMTestCaseDesc Setting the buffer configuration - varying the number of buffers.
+ @SYMTestPriority Critical
+ @SYMTestActions Issue a request on the playback channel to create a shared chunk (i.e. using
+ SetBufferChunkCreate()) with a buffer configuration containing a single buffer. Attempt
+ to open the same shared chunk on the record channel (i.e. using SetBufferChunkOpen()).
+ Then close the chunk.
+ Repeat this same sequence using buffer configurations containing 2 - 8 buffers.
+ @SYMTestExpectedResults In every case the attempt to create and open the shared chunk should return KErrNone.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test creating/opening a chunk, varying the number of buffers "));
+ TInt r;
+ RChunk chunk;
+ TTestSharedChunkBufConfig bufferConfig;
+ bufferConfig.iBufferSizeInBytes=0x7FE0; // 32K - 32 bytes
+ if (PlayCapsBuf().iRequestMinSize)
+ bufferConfig.iBufferSizeInBytes&=~(PlayCapsBuf().iRequestMinSize-1); // Assumes iRequestMinSize is same for play and record
+ TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
+
+ TInt i;
+ for (i=1 ; i<=8 ; i++)
+ {
+ bufferConfig.iFlags=aBufferConfigFlags;
+ bufferConfig.iNumBuffers=i;
+
+ // Create the shared chunk on the play channel
+ r=TxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ TxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+
+ // Open the same shared chunk on the record channel
+ r=RxSoundDevice.SetBufferChunkOpen(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+
+ chunk.Close();
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-233
+ @SYMTestCaseDesc Setting the buffer configuration - varying the size of the buffers.
+ @SYMTestPriority Critical
+ @SYMTestActions Issue a request on the playback channel to create a shared chunk (i.e. using
+ SetBufferChunkCreate()) with a buffer configuration containing multiple buffers
+ each of size 32K bytes. Attempt to open the same shared chunk on the record channel
+ (i.e. using SetBufferChunkOpen()). Then close the chunk. Repeat this same sequence
+ using buffer configurations containing buffers of size 16K, 8K and 4K bytes.
+ @SYMTestExpectedResults In every case the attempt to create and open the shared chunk should return KErrNone.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test creating/opening a chunk, varying the size of the buffers "));
+ bufferConfig.iNumBuffers=4;
+
+ for (i=1 ; i<=8 ; i*=2)
+ {
+ bufferConfig.iFlags=aBufferConfigFlags;
+ bufferConfig.iBufferSizeInBytes=(0x8000/i);
+
+ // Create the shared chunk on the play channel
+ r=TxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ TxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+
+ // Open the same shared chunk on the record channel
+ r=RxSoundDevice.SetBufferChunkOpen(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+
+ chunk.Close();
+ }
+
+ // Try creating a shared chunk for the record channel specifying an illegal buffer size.
+ if (RecordCapsBuf().iRequestMinSize)
+ {
+ Test.Next(_L("Test creating a chunk, with an illegal buffer size"));
+ bufferConfig.iNumBuffers=1;
+ bufferConfig.iBufferSizeInBytes=0x1001; // 4K + 1byte
+ bufferConfig.iFlags=aBufferConfigFlags;
+ r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK(r==KErrArgument);
+ chunk.Close();
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-234
+ @SYMTestCaseDesc Setting the buffer configuration - specifying the buffer offsets.
+ @SYMTestPriority Critical
+ @SYMTestActions Issue a request on the record channel to create a shared chunk (i.e.
+ using SetBufferChunkCreate()) with an buffer configuration containing multiple buffers
+ where the offset of each buffer is specified by the client. Perform this test repeatedly
+ with buffer offsets specified as follows:-
+ 1) Valid buffer offsets
+ 2) Offsets resulting on overlapping buffers
+ 3) Offsets which aren't aligned with the request alignment restrictions for the device (if it has any).
+ @SYMTestExpectedResults 1) Setting the buffer configuration should return KErrNone.
+ 2) Setting the buffer configuration should fail with KErrArgument.
+ 3) Setting the buffer configuration should fail with KErrArgument.
+ @SYMREQ PREQ1073.4 */
+/*
+ // ***** Setting the buffer configuration - specifying the buffer offsets is not supported. *****
+
+ Test.Next(_L("Test creating a chunk, specifying the buffer offsets"));
+ TInt bufSize=0x2000;
+ bufferConfig.iNumBuffers=8;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iBufferOffsetList[0]=0;
+ bufferConfig.iBufferOffsetList[1]=bufSize;
+ bufferConfig.iBufferOffsetList[2]=bufSize*4;
+ bufferConfig.iBufferOffsetList[3]=bufSize*6;
+ bufferConfig.iBufferOffsetList[4]=bufSize*7;
+ bufferConfig.iBufferOffsetList[5]=bufSize*9;
+ bufferConfig.iBufferOffsetList[6]=bufSize*10;
+ bufferConfig.iBufferOffsetList[7]=bufSize*12;
+ bufferConfig.iFlags=(aBufferConfigFlags|KScFlagBufOffsetListInUse);
+ bufferConfigBuf.SetLength(sizeof(bufferConfig)); // Otherwise set shorter by previous GetBufferConfig().
+ r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ RxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+ chunk.Close();
+
+ Test.Next(_L("Test creating a chunk, with invalid buffer offsets specified"));
+
+ // Firstly with 2nd buffer overlapping the 1st
+ bufSize=0x2000;
+ bufferConfig.iNumBuffers=3;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iBufferOffsetList[0]=0;
+ bufferConfig.iBufferOffsetList[1]=bufSize/2;
+ bufferConfig.iBufferOffsetList[2]=bufSize*2;
+ bufferConfig.iFlags=(aBufferConfigFlags|KScFlagBufOffsetListInUse);
+ r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK(r==KErrArgument);
+ chunk.Close();
+
+ // Now with offset of 3rd buffer not on a page boundary
+ if (RecordCapsBuf().iRequestAlignment)
+ {
+ bufSize=0x2000;
+ bufferConfig.iNumBuffers=3;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iBufferOffsetList[0]=0;
+ bufferConfig.iBufferOffsetList[1]=bufSize;
+ bufferConfig.iBufferOffsetList[2]=(bufSize*2)+1;
+ bufferConfig.iFlags=(aBufferConfigFlags|KScFlagBufOffsetListInUse);
+ r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK(r==KErrArgument);
+ chunk.Close();
+ }
+*/
+ }
+
+LOCAL_C void TestPlay()
+ {
+
+ Test.Printf(_L("Testing play operation\r\n"));
+
+ // Close and re-open the playback channel to reset the driver.
+ TxSoundDevice.Close();
+ TInt r = TxSoundDevice.Open(KSoundScTxUnit0);
+ CHECK_NOERROR(r);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-235
+ @SYMTestCaseDesc Play operation - playing without having set the buffer configuration.
+ @SYMTestPriority Critical
+ @SYMTestActions Issue a request on the playback channel to play some audio data before having set-up
+ the buffer configuration.
+ @SYMTestExpectedResults The play request should fail with KErrNotReady.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test playing without setting buffer config"));
+ TRequestStatus stat[2];
+ TxSoundDevice.PlayData(stat[0],0,0x2000); // 8K
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrNotReady);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-236
+ @SYMTestCaseDesc Play operation - playing without having set the audio configuration.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the buffer configuration on the playback channel and then issue a request to
+ play audio data before having set-up the audio configuration
+ @SYMTestExpectedResults The play request should complete with KErrNone - with the driver using its default
+ audio configuration for the transfer.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test playing without setting audio config"));
+
+ // Read back the default play configuration
+ TxSoundDevice.AudioFormat(PlayFormatBuf);
+ TCurrentSoundFormatV02 playFormat=PlayFormatBuf();
+ PrintConfig(playFormat,Test);
+
+ // Set the play buffer configuration.
+ RChunk chunk;
+ TInt bufSize=BytesPerSecond(PlayFormatBuf()); // Large enough to hold 1 second of data.
+ bufSize=ValidBufferSize(bufSize,PlayCapsBuf().iRequestMinSize,PlayFormatBuf()); // Keep the buffer length valid for driver.
+ TTestSharedChunkBufConfig bufferConfig;
+ bufferConfig.iNumBuffers=1;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iFlags=0;
+ TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
+ r=TxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ TxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+ CHECK(bufferConfig.iBufferSizeInBytes==bufSize);
+
+ // Start playing
+ r=MakeSineTable(PlayFormatBuf());
+ CHECK_NOERROR(r);
+ r=SetToneFrequency(660,PlayFormatBuf());
+ CHECK_NOERROR(r);
+ TPtr8 ptr(chunk.Base()+bufferConfig.iBufferOffsetList[0],bufSize);
+ WriteTone(ptr,PlayFormatBuf());
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],bufSize,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_NOERROR(stat[0].Int());
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-239
+ @SYMTestCaseDesc Play operation - with invalid arguments.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the playback channel to commence playing audio data using a buffer configuration
+ containing multiple buffers. Now issue a series of transfer requests to play data where the
+ requests contain invalid request arguments as follows:-
+ 1) A request with a buffer offset before the start of the first buffer.
+ 2) A request with a buffer offset between buffers.
+ 3) A request with a length too large for a buffer.
+ 4) A request with a buffer offset that doesn't comply with the offset restrictions of
+ the driver (i.e. TSoundFormatsSupportedV02:: iRequestAlignment).
+ 5) A request with a length that doesn't comply with the length restrictions of
+ the driver (i.e. TSoundFormatsSupportedV02::iRequestMinSize).
+ @SYMTestExpectedResults 1) The play request should fail with KErrArgument.
+ 2) The play request should fail with KErrArgument.
+ 3) The play request should fail with KErrArgument.
+ 4) The play request should fail with KErrArgument.
+ 5) The play request should fail with KErrArgument
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test playing with invalid arguments"));
+
+ // With a buffer offset before the start of the buffer.
+ TxSoundDevice.PlayData(stat[0],(bufferConfig.iBufferOffsetList[0]-0x100),bufSize,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrArgument);
+
+ // With a buffer offset beyond the end of the buffer
+ TxSoundDevice.PlayData(stat[0],(bufferConfig.iBufferOffsetList[0]+bufSize+0x100),bufSize,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrArgument);
+
+ // With a length too large for the buffer
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],(bufSize+0x100),KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrArgument);
+
+ // With a length that doesn't comply with the length restrictions of the driver
+ if (PlayCapsBuf().iRequestMinSize)
+ {
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],(bufSize-1),KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrArgument);
+ }
+
+ // With an offset that doesn't comply with the offset restrictions of the driver
+ if (PlayCapsBuf().iRequestAlignment)
+ {
+ TInt ln=bufSize/2;
+ if (PlayCapsBuf().iRequestMinSize)
+ ln&=~(PlayCapsBuf().iRequestMinSize-1); // Keep the buffer length valid for the driver.
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0]+1,ln,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrArgument);
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-242
+ @SYMTestCaseDesc Play operation - play underflow detection.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the audio configuration on the playback channel and then setup the buffer
+ configuration. Issue a single request to play audio data from one of the buffers
+ (without supplying the KSndFlagLastSample flag) and wait for the request to complete.
+ @SYMTestExpectedResults The driver should successfully play the audio data supplied but the request should
+ return the error value: KErrUnderflow.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test play underflow detection"));
+
+ // Now set the audio configuration to a known state.
+ if (PlayCapsBuf().iEncodings&KSoundEncoding16BitPCM)
+ PlayFormatBuf().iEncoding = ESoundEncoding16BitPCM;
+ if (PlayCapsBuf().iRates&KSoundRate16000Hz)
+ PlayFormatBuf().iRate = ESoundRate16000Hz;
+ if (PlayCapsBuf().iChannels&KSoundStereoChannel)
+ PlayFormatBuf().iChannels = 2;
+ PrintConfig(PlayFormatBuf(),Test);
+ r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
+ CHECK_NOERROR(r);
+
+ // Reset the play buffer configuration to correspond to the audio configuration.
+ bufSize=BytesPerSecond(PlayFormatBuf()); // Large enough to hold 1 second of data (64K)
+ bufSize=ValidBufferSize(bufSize,PlayCapsBuf().iRequestMinSize,PlayFormatBuf()); // Keep the buffer length valid for driver.
+ bufferConfig.iNumBuffers=1;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iFlags=0;
+ r=TxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ TxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+ CHECK(bufferConfig.iBufferSizeInBytes==bufSize);
+
+ // Start playing
+ r=MakeSineTable(PlayFormatBuf());
+ CHECK_NOERROR(r);
+ r=SetToneFrequency(660,PlayFormatBuf());
+ CHECK_NOERROR(r);
+ ptr.Set(chunk.Base()+bufferConfig.iBufferOffsetList[0],bufSize,bufSize);
+ WriteTone(ptr,PlayFormatBuf());
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],bufSize);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrUnderflow);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-243
+ @SYMTestCaseDesc Play operation - playing multiple transfers from a single buffer.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the audio configuration on the playback channel and setup the buffer configuration
+ so the shared chunk contains just a single large buffer. Issue a pair of requests to play
+ audio data from the buffer (marking the last with the KSndFlagLastSample flag) and wait
+ for the requests to complete.
+ @SYMTestExpectedResults The driver should successfully play the audio data supplied and both requests should
+ complete with KErrNone.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test playing multiple transfers from a single buffer"));
+
+ // Start playing
+ TInt len=bufSize/2;
+ if (PlayCapsBuf().iRequestMinSize)
+ len&=~(PlayCapsBuf().iRequestMinSize-1); // Keep the buffer length valid for the driver.
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],len);
+ TxSoundDevice.PlayData(stat[1],(bufferConfig.iBufferOffsetList[0]+len),len,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_NOERROR(stat[0].Int());
+ User::WaitForRequest(stat[1]);
+ CHECK_NOERROR(stat[1].Int());
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-244
+ @SYMTestCaseDesc Play operation - tracking the count of bytes transferred.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the playback channel for playing audio data.
+ 1) Reset the channel's count of bytes transferred and read back the count.
+ 2) Issue a play request of known length and wait for it to complete. Now read the
+ count of bytes transferred.
+ 3) Reset the channel's count of bytes transferred and read back the count.
+ @SYMTestExpectedResults 1) The count of bytes transferred should equal zero.
+ 2) The count of bytes transferred should equal the length of the play request.
+ 3) The count of bytes transferred should equal zero.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test tracking the number of bytes played"));
+ TxSoundDevice.ResetBytesTransferred();
+ TInt bytesPlayed=TxSoundDevice.BytesTransferred();
+ CHECK(bytesPlayed==0);
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],len,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_NOERROR(stat[0].Int());
+ bytesPlayed=TxSoundDevice.BytesTransferred();
+ CHECK(bytesPlayed==len);
+ TxSoundDevice.ResetBytesTransferred();
+ bytesPlayed=TxSoundDevice.BytesTransferred();
+ CHECK(bytesPlayed==0);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-246
+ @SYMTestCaseDesc Play operation - testing the driver's handling of PDD play errors.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the playback channel for playing audio data. Using the CustomConfig() test mode
+ supported by the driver, induce the following errors returned from the driver PDD back
+ to the LDD:-
+ 1) Induce a KErrTimedOut error at the start of the transfer and then issue a play request.
+ 2) Induce a KErrTimedOut error once transfer has commenced and then issue a play request.
+ Once this completes, issue a further play request.
+ @SYMTestExpectedResults 1) The play request should fail immediately with KErrTimedOut (with no audible output being
+ heard).
+ 2) The driver should output a short section of audible data before the first play request
+ fails with KErrTimedOut. However, the driver should recover from this and the second
+ play request should complete with KErrNone.
+ @SYMREQ PREQ1073.4 */
+
+#ifdef _DEBUG
+ Test.Next(_L("Test the driver's handling of PDD play errors"));
+
+ // First induce an error at the start of the transfer
+ // Use an LDD test mode which induces KErrTimedOut at the start of the transfer.
+ r=TxSoundDevice.CustomConfig(KSndCustom_ForceStartTransferError);
+ CHECK_NOERROR(r);
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],bufSize,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrTimedOut);
+
+ // Now induce an error once transfer has commenced
+ // Use an LDD test mode which induces KErrTimedOut once transfer has commenced.
+ r=TxSoundDevice.CustomConfig(KSndCustom_ForceTransferDataError);
+ CHECK_NOERROR(r);
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],bufSize,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_EQUAL(stat[0].Int(),KErrTimedOut);
+
+ // Check that the driver recovers
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],bufSize,KSndFlagLastSample);
+ User::WaitForRequest(stat[0]);
+ CHECK_NOERROR(stat[0].Int());
+#endif
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-247
+ @SYMTestCaseDesc Play operation - closing the channel cancels any play requests.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the playback channel for playing audio data. Issue a play request and
+ while this is outstanding, close the playback channel.
+ @SYMTestExpectedResults The outstanding request should complete with KErrCancel.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test that closing the channel cancels a play request"));
+ TxSoundDevice.PlayData(stat[0],bufferConfig.iBufferOffsetList[0],len,KSndFlagLastSample);
+ CHECK(stat[0]==KRequestPending);
+ TxSoundDevice.Close();
+ User::WaitForRequest(stat[0]);
+ CHECK(stat[0]==KErrCancel);
+
+ Test.Next(_L("Re-open the channel"));
+ r = TxSoundDevice.Open(KSoundScTxUnit0);
+ CHECK_NOERROR(r);
+
+ chunk.Close();
+ }
+
+LOCAL_C void TestRecord()
+ {
+
+ Test.Printf(_L("Testing record operation\r\n"));
+
+ // Close and re-open the record channel to reset the driver.
+ RxSoundDevice.Close();
+ TInt r = RxSoundDevice.Open(KSoundScRxUnit0);
+ CHECK_NOERROR(r);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-251
+ @SYMTestCaseDesc Record operation - recording without having set the buffer configuration.
+ @SYMTestPriority Critical
+ @SYMTestActions Issue a request on the record channel to record some audio data before
+ having set-up the buffer configuration.
+ @SYMTestExpectedResults The record request should fail with KErrNotReady.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test recording without setting buffer config"));
+
+ TRequestStatus stat;
+ TInt length;
+ RxSoundDevice.RecordData(stat,length);
+ User::WaitForRequest(stat);
+ TInt retOffset=stat.Int();
+ CHECK_EQUAL(retOffset,KErrNotReady);
+
+ // Test releasing a buffer without setting buffer config
+ r=RxSoundDevice.ReleaseBuffer(0);
+ CHECK(r==KErrNotReady);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-252
+ @SYMTestCaseDesc Record operation - recording without having set the audio configuration.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the buffer configuration on the record channel.
+ 1) Issue a request to record a buffer of audio data before having set-up the audio
+ configuration.
+ 2) Release the buffer.
+ @SYMTestExpectedResults 1) The record request should complete with KErrNone - with the driver using its
+ default audio configuration for the transfer.
+ 2) The request to release the buffer should return KErrNone
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test recording without setting audio config"));
+
+ // Read back the default record configuration
+ RxSoundDevice.AudioFormat(RecordFormatBuf);
+ TCurrentSoundFormatV02 recordFormat=RecordFormatBuf();
+ PrintConfig(recordFormat,Test);
+
+ // Set the record buffer configuration.
+ RChunk chunk;
+ TInt bufSize=BytesPerSecond(RecordFormatBuf()); // Large enough to hold 1 second of data.
+ bufSize=ValidBufferSize(bufSize,RecordCapsBuf().iRequestMinSize,RecordFormatBuf()); // Keep the buffer length valid for driver.
+ TTestSharedChunkBufConfig bufferConfig;
+ bufferConfig.iNumBuffers=3;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iFlags=0;
+ TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
+ r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ RxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+ CHECK(bufferConfig.iBufferSizeInBytes==bufSize);
+
+ // Start recording
+ RxSoundDevice.SetVolume(KSoundMaxVolume);
+ RxSoundDevice.RecordData(stat,length); // Start recording here
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset>=0);
+ CHECK(length==bufSize);
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK_NOERROR(r);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-255
+ @SYMTestCaseDesc Record operation - invalid attempts to release a record buffer.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the record channel to record audio data. Issue a request to record a buffer of audio data
+ and then release the buffer.
+ 1) Request to release the same buffer just released (without having re-claimed it with a
+ further record request).
+ 2) Release a further buffer - specifying an illegal buffer offset for the buffer.
+ 3) Stop the driver from recording (using CancelRecordData()). Now release a buffer while
+ recording is disabled.
+ @SYMTestExpectedResults 1) The request to release the buffer should fail with KErrNotFound.
+ 2) The request to release the buffer should fail with KErrNotFound.
+ 3) The request to release the buffer should fail with KErrNotFound.
+ @SYMREQ PREQ1073.4 */
+
+ // Test releasing a buffer twice
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK(r==KErrNotFound);
+
+ // Test releasing an invalid buffer offset
+ r=RxSoundDevice.ReleaseBuffer(0);
+ CHECK(r==KErrNotFound);
+
+ // Third test case for PBASE-T_SOUND_API-255 is performed later in this function.
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-256
+ @SYMTestCaseDesc Record operation - record overflow detection.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the audio configuration on the record channel and then setup the buffer configuration
+ so the shared chunk contains three record buffers.
+ 1) Issue a request to record a buffer of audio data (to start the driver recording).
+ 2) When the request completes, release the buffer immediately.
+ 3) Wait just over 2 buffer periods (i.e. the time it takes for the driver to fill 2 record
+ buffers) and then issue a further record request.
+ 4) To test that the driver recovers from the overflow situation, immediately issue a further
+ record request.
+ @SYMTestExpectedResults 1) The record request should complete with KErrNone.
+ 2) The request to release the buffer should return KErrNone.
+ 3) The record request should fail with KErrOverflow.
+ 4) The record request should complete with KErrNone.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test for record overflow"));
+
+ // Now set the audio configuration to a known state.
+ RxSoundDevice.CancelRecordData(); // Stop the driver from recording.
+
+ RxSoundDevice.AudioFormat(RecordFormatBuf); // Read back the current setting which must be valid.
+ if (RecordCapsBuf().iEncodings&KSoundEncoding16BitPCM)
+ RecordFormatBuf().iEncoding = ESoundEncoding16BitPCM;
+ if (RecordCapsBuf().iChannels&KSoundStereoChannel)
+ RecordFormatBuf().iChannels = 2;
+
+ // find first supported rate and set the the audio configuration to use it
+ for (TInt i=0 ; i <= (TInt)ESoundRate48000Hz ; i++)
+ {
+ RecordFormatBuf().iRate = (TSoundRate)i;
+ r = RxSoundDevice.SetAudioFormat(RecordFormatBuf);
+ if (RecordCapsBuf().iRates & (1<<i))
+ {
+ CHECK_NOERROR(r); // Caps reports it is supported
+ break;
+ }
+ }
+
+ PrintConfig(RecordFormatBuf(),Test);
+
+ // Reset the record buffer configuration to correspond to the audio configuration.
+ bufSize=BytesPerSecond(RecordFormatBuf())/2; // Large enough to hold 0.5 seconds of data (64K)
+ bufSize=ValidBufferSize(bufSize,RecordCapsBuf().iRequestMinSize,RecordFormatBuf()); // Keep the buffer length valid for driver.
+ bufferConfig.iNumBuffers=3;
+ bufferConfig.iBufferSizeInBytes=bufSize;
+ bufferConfig.iFlags=0;
+ r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
+ CHECK_NOERROR(r);
+ RxSoundDevice.GetBufferConfig(bufferConfigBuf);
+ PrintBufferConf(bufferConfig,Test);
+ CHECK(bufferConfig.iBufferSizeInBytes==bufSize);
+
+ // Test releasing a buffer before we have started recording
+ r=RxSoundDevice.ReleaseBuffer(bufferConfig.iBufferOffsetList[0]);
+ CHECK(r==KErrNotFound);
+
+ RxSoundDevice.RecordData(stat,length); // Start recording here
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset>=0);
+ CHECK(length==bufSize);
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK_NOERROR(r);
+
+ User::After(1100000); // Wait 2 buffer periods (1.1 seconds) for data overflow.
+
+ RxSoundDevice.RecordData(stat,length);
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset==KErrOverflow);
+
+ Test.Next(_L("Test that the driver recovers from overflow"));
+
+ RxSoundDevice.RecordData(stat,length);
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset>=0);
+ CHECK(length==bufSize);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-257
+ @SYMTestCaseDesc Record operation - when client is too slow releasing buffers.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the audio configuration on the record channel and then setup the buffer configuration
+ so the shared chunk contains three record buffers. Issue a request to record a buffer of
+ audio data (to start the driver recording). When this request completes, issue a further
+ record request without releasing the first buffer.
+ @SYMTestExpectedResults The second record request should fail with KErrInUse.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test when client is too slow releasing buffers"));
+
+ RxSoundDevice.RecordData(stat,length);
+ User::WaitForRequest(stat);
+ TInt retOffset1=stat.Int();
+ CHECK(retOffset1==KErrInUse);
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK_NOERROR(r);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-258
+ @SYMTestCaseDesc Record operation - tracking the count of bytes transferred.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the record channel for recording audio data.
+ 1) Reset the channel's count of bytes transferred and read back the count.
+ 2) Issue a record request (to start the driver recording) and wait for it to complete. Immediately read the count of bytes transferred.
+ 3) Reset the channel's count of bytes transferred and read back the count
+ @SYMTestExpectedResults 1) The count of bytes transferred should equal zero.
+ 2) The count of bytes transferred should equal the size of a record buffer.
+ 3) The count of bytes transferred should equal zero.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test tracking the number of bytes recorded"));
+ RxSoundDevice.CancelRecordData(); // Stop the driver from recording.
+ RxSoundDevice.ResetBytesTransferred();
+ TInt bytesRecorded=RxSoundDevice.BytesTransferred();
+ CHECK(bytesRecorded==0);
+ RxSoundDevice.RecordData(stat,length); // Re-start recording here
+ User::WaitForRequest(stat);
+
+ // Quickly check the number of bytes recorded
+ bytesRecorded=RxSoundDevice.BytesTransferred();
+ CHECK(bytesRecorded==bufSize);
+
+ // Now check the request was successful and release the buffer
+ retOffset=stat.Int();
+ CHECK(retOffset>=0);
+ CHECK(length==bufSize);
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK_NOERROR(r);
+
+ RxSoundDevice.ResetBytesTransferred();
+ bytesRecorded=RxSoundDevice.BytesTransferred();
+ CHECK(bytesRecorded==0);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-260
+ @SYMTestCaseDesc Record operation - testing the driver's handling of PDD record errors.
+ @SYMTestPriority Critical
+ @SYMTestActions Setup the record channel for recording. Using the CustomConfig() test mode supported by the driver, induce
+ the following errors returned from the driver PDD back to the LDD:-
+ 1) Induce a KErrTimedOut error at the start of the transfer. Then, issue a record request to
+ start the driver recording. Once this completes, stop the channel from recording.
+ 2) Induce a KErrTimedOut error once transfer has commenced. Then, issue a record request to
+ re-start the driver recording. Once this completes, issue a further record request.
+ @SYMTestExpectedResults 1) The record request should fail immediately with KErrTimedOut.
+ 2) The first record request should soon fail with KErrTimedOut. However, the driver should
+ recover from this and the subsequent record request should complete with KErrNone.
+ @SYMREQ PREQ1073.4 */
+
+#ifdef _DEBUG
+ Test.Next(_L("Test the driver's handling of PDD record errors"));
+
+ Test.Printf(_L("Induce an error at the start of the transfer.\r\n"));
+ // Use an LDD test mode which induces KErrTimedOut at the start of the transfer.
+ RxSoundDevice.CancelRecordData(); // Stop the driver from recording.
+ r=RxSoundDevice.CustomConfig(KSndCustom_ForceStartTransferError);
+ CHECK_NOERROR(r);
+ RxSoundDevice.RecordData(stat,length); // Re-start recording here
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset==KErrTimedOut);
+ RxSoundDevice.CancelRecordData(); // Stop the driver from recording.
+
+ Test.Printf(_L("Induce an error once transfer has commenced.\r\n"));
+ // Use an LDD test mode which induces KErrTimedOut once transfer has commenced.
+ r=RxSoundDevice.CustomConfig(KSndCustom_ForceTransferDataError);
+ CHECK_NOERROR(r);
+ RxSoundDevice.RecordData(stat,length); // Re-start recording here
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset==KErrTimedOut);
+
+ Test.Printf(_L("Check that the driver recovers.\r\n"));
+ RxSoundDevice.RecordData(stat,length);
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ CHECK(retOffset>=0);
+ CHECK(length==bufSize);
+ r=RxSoundDevice.ReleaseBuffer(retOffset);
+ CHECK_NOERROR(r);
+
+/* Test disabled
+ Test.Printf(_L("Induce LDD to be slow servicing transfer completes from PDD.\r\n"));
+ r=RxSoundDevice.CustomConfig(KSndCustom_ForceTransferTimeout);
+ CHECK_NOERROR(r);
+ RxSoundDevice.RecordData(stat,length);
+ User::WaitForRequest(stat);
+ retOffset=stat.Int();
+ Test.Printf(_L("Driver returned %d.\r\n"),retOffset); */
+#endif
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-261
+ @SYMTestCaseDesc Record operation - closing the channel cancels any record requests.
+ @SYMTestPriority Critical
+ @SYMTestActions Start the record channel for recording audio data. Issue a record request and while this is
+ outstanding, close the record channel
+ @SYMTestExpectedResults The outstanding request should complete with KErrCancel.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test that closing the channel cancels a play request"));
+ RxSoundDevice.RecordData(stat,length);
+ CHECK(stat==KRequestPending);
+ RxSoundDevice.Close();
+ User::WaitForRequest(stat);
+ CHECK(stat==KErrCancel);
+
+ Test.Next(_L("Re-open the channel"));
+ r = RxSoundDevice.Open(KSoundScRxUnit0);
+ CHECK_NOERROR(r);
+
+ chunk.Close();
+ }
+
+#ifdef _DEBUG
+LOCAL_C void TestChangeOfHwConfigNotifier()
+ {
+
+ Test.Printf(_L("Testing the change of h/w config notifier\r\n"));
+
+ // If support for the notifier is not supported on this platform, use a debug custom config command to force
+ // support for the notifier.
+ TInt r;
+ if (!PlayCapsBuf().iHwConfigNotificationSupport)
+ {
+ r=TxSoundDevice.CustomConfig(KSndCustom_ForceHwConfigNotifSupported);
+ CHECK_NOERROR(r);
+ }
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-264
+ @SYMTestCaseDesc Change of h/w config. notifier - receiving notification.
+ @SYMTestPriority Critical
+ @SYMTestActions 1) Register for notification of a change in the hardware configuration of the device on
+ either the record or playback channel. Using the CustomConfig() test mode supported by the
+ driver, trigger the notifier - signalling that the headset is not present.
+ 2) Re-register for notification of a change in the hardware configuration on the same channel.
+ Again using the CustomConfig() test mode, trigger the notifier - this time signalling that the
+ headset is present.
+ @SYMTestExpectedResults 1) The outstanding request for notification should complete with KErrNone and the status of
+ the bolean aHeadsetPresent should be false.
+ 2) The outstanding request for notification should complete with KErrNone and the status of
+ the bolean aHeadsetPresent should be true.
+ @SYMREQ PREQ1073.4 */
+
+ // Register for notification of a change in the hardware configuration of the device.
+ TRequestStatus stat;
+ TBool headsetPresent=ETrue;
+ TxSoundDevice.NotifyChangeOfHwConfig(stat,headsetPresent);
+ CHECK(stat==KRequestPending);
+
+ Test.Next(_L("Trigger the notifier"));
+ // Use another debug custom config command to trigger the notifier.
+ r=TxSoundDevice.CustomConfig(KSndCustom_CompleteChangeOfHwConfig,(TAny*)0x00); // Signal headset not present.
+ CHECK_NOERROR(r);
+ User::WaitForRequest(stat);
+ CHECK_NOERROR(stat.Int());
+ CHECK(!headsetPresent);
+
+ Test.Next(_L("Trigger the notifier again"));
+ TxSoundDevice.NotifyChangeOfHwConfig(stat,headsetPresent);
+ CHECK(stat==KRequestPending);
+ r=TxSoundDevice.CustomConfig(KSndCustom_CompleteChangeOfHwConfig,(TAny*)0x01); // Signal headset is present.
+ CHECK_NOERROR(r);
+ User::WaitForRequest(stat);
+ CHECK_NOERROR(stat.Int());
+ CHECK(headsetPresent);
+
+ Test.Next(_L("Test cancelling the notifier"));
+ TxSoundDevice.NotifyChangeOfHwConfig(stat,headsetPresent);
+ CHECK(stat==KRequestPending);
+ TxSoundDevice.CancelNotifyChangeOfHwConfig();
+ User::WaitForRequest(stat);
+ CHECK(stat==KErrCancel);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-265
+ @SYMTestCaseDesc Change of h/w config. notifier - receiving notification.
+ @SYMTestPriority Critical
+ @SYMTestActions 1) Register for notification of a change in the hardware configuration of the device on
+ either the record or playback channel. Using the CustomConfig() test mode supported by the
+ driver, trigger the notifier - signalling that the headset is not present.
+ 2) Re-register for notification of a change in the hardware configuration on the same channel.
+ Again using the CustomConfig() test mode, trigger the notifier - this time signalling that the
+ headset is present.
+ @SYMTestExpectedResults 1) The outstanding request for notification should complete with KErrNone and the status of
+ the bolean aHeadsetPresent should be false.
+ 2) The outstanding request for notification should complete with KErrNone and the status of
+ the bolean aHeadsetPresent should be true.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Test that closing the channel cancels the notifier"));
+ TxSoundDevice.NotifyChangeOfHwConfig(stat,headsetPresent);
+ CHECK(stat==KRequestPending);
+ TxSoundDevice.Close();
+ User::WaitForRequest(stat);
+ CHECK(stat==KErrCancel);
+
+ Test.Next(_L("Re-open the channel"));
+ r = TxSoundDevice.Open(KSoundScTxUnit0);
+ CHECK_NOERROR(r);
+ }
+#endif
+
+LOCAL_C void TestUnloadDrivers()
+ {
+ /** @SYMTestCaseID PBASE-T_SOUND_API-221
+ @SYMTestCaseDesc Un-installing the LDD
+ @SYMTestPriority Critical
+ @SYMTestActions Attempt to un-install the LDD (using User::FreeLogicalDevice()).
+ @SYMTestExpectedResults KErrNone - LDD unloads successfully
+ @SYMREQ PREQ1073.4 */
+
+ TInt r=User::FreeLogicalDevice(KDevSoundScName);
+ Test.Printf(_L("Unloading %S.LDD - %d\r\n"),&KDevSoundScName,r);
+ CHECK_NOERROR(r);
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-222
+ @SYMTestCaseDesc Un-installing the PDD
+ @SYMTestPriority Critical
+ @SYMTestActions Attempt to un-install the PDD (using User::FreePhysicalDevice()).
+ @SYMTestExpectedResults KErrNone - PDD unloads successfully
+ @SYMREQ PREQ1073.4 */
+
+ TName pddName(KDevSoundScName);
+ _LIT(KPddWildcardExtension,".*");
+ pddName.Append(KPddWildcardExtension);
+ TFindPhysicalDevice findPD(pddName);
+ TFullName findResult;
+ r=findPD.Next(findResult);
+ while (r==KErrNone)
+ {
+ r=User::FreePhysicalDevice(findResult);
+ Test.Printf(_L("Unloading %S.PDD - %d\r\n"),&findResult,r);
+ CHECK_NOERROR(r);
+ findPD.Find(pddName); // Reset the find handle now that we have deleted something from the container.
+ r=findPD.Next(findResult);
+ }
+ }
+
+/**
+Invoke the helper executable, tell it what unit to open RSoundSc for.
+
+@param aUnit Parameter to supply to RSoundSc ie. KSoundScTxUnit0, KSoundScRxUnit0
+@param aExpectedError The expected return code from RSoundSc::Open
+ */
+static void RunHelper(TInt aUnit, TInt aExpectedError)
+ {
+ TInt r;
+
+ RProcess ph;
+ r = ph.Create(KHelperExe, KNullDesC);
+ CHECK_NOERROR(r);
+ r = ph.SetParameter(KSlot, aUnit);
+ CHECK_NOERROR(r);
+
+ TRequestStatus rsh;
+ ph.Logon(rsh);
+ Test(rsh == KRequestPending);
+ ph.Resume();
+ User::WaitForRequest(rsh);
+
+ // process has died so check the panic category and reason match the expected values
+ CHECK_EQUAL(ph.ExitType(), EExitPanic);
+ Test(ph.ExitCategory()==KSoundAPICaps,__LINE__,(const TText*)__FILE__);
+ CHECK_EQUAL(ph.ExitReason(), aExpectedError);
+
+ ph.Close();
+ }
+
+/**
+Delete the copy of the helper exe which was created with altered capabilities
+*/
+static TInt DeleteHelper()
+ {
+ RFs fs;
+ TInt r = fs.Connect();
+ CHECK_NOERROR(r);
+ TFileName fileName(KSysBin);
+ fileName.Append(KPathDelimiter);
+ fileName+=KHelperExe;
+ //delete modified version of helper exe
+ r = fs.Delete(fileName);
+ fs.Close();
+ return r;
+ }
+
+/**
+Use setcap.exe to create a copy of the helper executable, t_sound_api_helper.exe
+called t_sound_api_helper_caps.exe with the supplied capabilities.
+
+@param aCaps A bitmask of capabilities to assign to helper exe.
+*/
+static void SetHelperCaps(TUint32 aCaps)
+ {
+ TInt r;
+ _LIT(KCommandLineArgsFormat, "%S %08x %S\\%S");
+ TBuf<128> cmdLine;
+ cmdLine.Format(KCommandLineArgsFormat, &KHelperExeBase, aCaps, &KSysBin, &KHelperExe);
+
+ RProcess p;
+ r = p.Create(_L("setcap.exe"), cmdLine);
+ CHECK_NOERROR(r);
+
+ TRequestStatus rs;
+ p.Logon(rs);
+ CHECK_EQUAL(rs.Int(),KRequestPending);
+ p.Resume();
+ User::WaitForRequest(rs);
+
+ p.Close();
+ }
+
+/**
+Test that ECapabilityMultimediaDD is required
+in order to open RSoundSc for playback and that
+ECapabilityUserEnvironment is needed, in addition,
+to open for record.
+*/
+static void TestCapabilityChecks()
+ {
+ //convert capabilities into bitmask understood by setcap.exe
+ const TUint32 KUserEnvironment = 1<<ECapabilityUserEnvironment;
+ const TUint32 KMultimediaDD= 1<<ECapabilityMultimediaDD;
+
+ //try to delete helper just in case it has been left hanging about from a previous run which failed
+ DeleteHelper();
+ SetHelperCaps(NULL);
+ RunHelper(KSoundScTxUnit0,KErrPermissionDenied);
+ RunHelper(KSoundScRxUnit0,KErrPermissionDenied);
+
+ CHECK_NOERROR(DeleteHelper());
+ SetHelperCaps(KMultimediaDD);
+ RunHelper(KSoundScTxUnit0,KErrNone);
+ RunHelper(KSoundScRxUnit0,KErrPermissionDenied);
+
+ CHECK_NOERROR(DeleteHelper());
+ SetHelperCaps(KUserEnvironment);
+ RunHelper(KSoundScTxUnit0,KErrPermissionDenied);
+ RunHelper(KSoundScRxUnit0,KErrPermissionDenied);
+
+ CHECK_NOERROR(DeleteHelper());
+ SetHelperCaps(KUserEnvironment|KMultimediaDD);
+ RunHelper(KSoundScTxUnit0,KErrNone);
+ RunHelper(KSoundScRxUnit0,KErrNone);
+
+ CHECK_NOERROR(DeleteHelper());
+ }
+
+TInt E32Main()
+ {
+ TInt r;
+
+ __UHEAP_MARK;
+
+ Test.Title();
+
+ Test.Start(_L("Load"));
+ if (Load()==KErrNotFound)
+ {
+ Test.Printf(_L("Shared chunk sound driver not supported - test skipped\r\n"));
+ Test.End();
+ Test.Close();
+ __UHEAP_MARKEND;
+ return(KErrNone);
+ }
+
+ // The __KHEAP_MARK and __KHEAP_MARKEND macros unfortunately have to be commented out or they
+ // generate false positives on the x86pc target build. This is to do with the launching of the
+ // helper executable, which results in another component allocating memory and not freeing it,
+ // thus causing the macros here to trigger a kern-exec 17 that is not related to the sound driver
+ // itself. The same macros are fine on other platforms. See DEF129273 for more information
+ //__KHEAP_MARK;
+
+ Test.Next(_L("Test Capability Checking"));
+ TestCapabilityChecks();
+
+ Test.Next(_L("Open playback channel"));
+ r = TxSoundDevice.Open(KSoundScTxUnit0);
+ CHECK_NOERROR(r);
+
+ Test.Next(_L("Open record channel"));
+ r = RxSoundDevice.Open(KSoundScRxUnit0);
+ CHECK_NOERROR(r);
+
+ Test.Next(_L("Query play formats supported"));
+ TxSoundDevice.Caps(PlayCapsBuf);
+ TSoundFormatsSupportedV02 playCaps=PlayCapsBuf();
+ PrintCaps(playCaps,Test);
+
+ Test.Next(_L("Query record formats supported"));
+ RxSoundDevice.Caps(RecordCapsBuf);
+ TSoundFormatsSupportedV02 recordCaps=RecordCapsBuf();
+ PrintCaps(recordCaps,Test);
+
+ TestSetAudioFormat();
+ TestSetBufferConfig(0); // Without guard pages.
+ TestSetBufferConfig(KScFlagUseGuardPages); // With guard pages.
+ TestPlay();
+ TestRecord();
+#ifdef _DEBUG
+ TestChangeOfHwConfigNotifier();
+#endif
+ // Note that API testing of pause/resume and volume setting are covered in T_SOUND2.
+
+ /** @SYMTestCaseID PBASE-T_SOUND_API-226
+ @SYMTestCaseDesc Closing the channel
+ @SYMTestPriority Critical
+ @SYMTestActions 1) With a playback channel open on the device, close the channel.
+ 2) With a record channel open on the device, close the channel.
+ @SYMTestExpectedResults 1) No errors occur closing the channel.
+ 2) No errors occur closing the channel.
+ @SYMREQ PREQ1073.4 */
+
+ Test.Next(_L("Close channels"));
+ RxSoundDevice.Close();
+ TxSoundDevice.Close();
+
+ //__KHEAP_MARKEND;
+
+ // Now that both the channels are closed, unload the LDD and the PDDs.
+ TestUnloadDrivers();
+
+ Test.End();
+ Test.Close();
+
+ Cleanup();
+
+ __UHEAP_MARKEND;
+
+ return(KErrNone);
+ }