Adaptation/GUID-AC560324-798C-5D0A-B23D-2419A7688A5B.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-AC560324-798C-5D0A-B23D-2419A7688A5B" xml:lang="en"><title>Channel
       
    13 Implementation</title><shortdesc>Describes how to implement the physical channels with the template
       
    14 port. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>A Sound Driver PDD must implement physical channels to use the audio hardware
       
    16 of the phone. The main Sound Driver PDD class is derived from <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita"><apiname>DSoundScPdd</apiname></xref>.
       
    17 A Sound Driver PDD that provides record and playback functions must implement
       
    18 a record driver channel and a playback driver channel. </p>
       
    19 <p>The template defines two classes: <codeph>DTemplateSoundScRxPdd</codeph> and <codeph>DTemplateSoundScTxPdd</codeph>,
       
    20 corresponding to record and playback respectively. The classes provide default
       
    21 implementations for the virtual functions defined by <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita"><apiname>DSoundScPdd</apiname></xref>,
       
    22 together with a constructor and destructor, and typically need little or no
       
    23 modification. </p>
       
    24 <section id="GUID-61725EEB-5114-5A85-9C28-57A47F14000C"><title>PDD class constructor</title> <p>Implement
       
    25 the PDD class constructor for both the playback and record driver channels.
       
    26 This is normally limited to </p> <ul>
       
    27 <li id="GUID-E02B0EE1-5171-5E9F-9BFE-FFAB6E15B290"><p>initialising any data
       
    28 members that need values other than zero </p> </li>
       
    29 <li id="GUID-4B39AEC4-0A02-5099-9805-F35B2AF4AD90"><p>initialising any DFC
       
    30 call-backs added. </p> </li>
       
    31 </ul> <p>Access to hardware has the potential to fail and so should be deferred
       
    32 to the second stage constructor <xref href="GUID-AC560324-798C-5D0A-B23D-2419A7688A5B.dita#GUID-AC560324-798C-5D0A-B23D-2419A7688A5B/GUID-F66BF339-FCE6-5859-87D1-7A0B0ED69D84">DoCreate()</xref>. </p> </section>
       
    33 <section id="GUID-CD12E6E9-C363-5CF9-91E1-694C34DE2BD9"><title>PDD class destructor</title> <p>Implement
       
    34 the PDD class destructor for both the playback and record driver channels.
       
    35 The destructor must release any hardware and Symbian platform resources that
       
    36 have been allocated to the driver. For example, this might include: </p> <ul>
       
    37 <li id="GUID-6D33C44B-B88F-504B-B750-FF010A72A290"><p>unbinding ISRs </p> </li>
       
    38 <li id="GUID-9DF0D93B-6782-5E94-80EB-A806BC1AB6B9"><p>cancelling private DFCs </p> </li>
       
    39 <li id="GUID-157C24A6-52F6-5BF1-BF94-035394F274F5"><p>closing DMA channels </p> </li>
       
    40 <li id="GUID-47452140-FA8E-55A8-BE2D-32AC87FF215E"><p>deleting any mono-to-stereo
       
    41 conversion buffers </p> </li>
       
    42 </ul> <p>The template versions of this function delete each DMA request object
       
    43 created in the PDD second stage constructor <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-C0CA28E4-2356-333D-B708-CBE469F1614F"><apiname>DSoundScPdd::DoCreate()</apiname></xref> and
       
    44 close the DMA channel. </p> </section>
       
    45 <section id="GUID-F66BF339-FCE6-5859-87D1-7A0B0ED69D84"><title>DoCreate()</title> <p>Implement
       
    46 a PDD class second stage constructor for both the playback and record driver
       
    47 channels. In the template version, the function <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-C0CA28E4-2356-333D-B708-CBE469F1614F"><apiname>DSoundScPdd::DoCreate()</apiname></xref> is
       
    48 called from the PDD factory when a channel is opened on the device. Generally,
       
    49 any hardware or Symbian platform resources required by the driver
       
    50 channel should be acquired here. However, powering up the sound device should
       
    51 be deferred to the <xref href="GUID-AC560324-798C-5D0A-B23D-2419A7688A5B.dita#GUID-AC560324-798C-5D0A-B23D-2419A7688A5B/GUID-B72057E6-B93C-505F-9789-83251D09B78E">PowerUp()</xref> function.
       
    52 Operations performed by this function include: </p> <ul>
       
    53 <li id="GUID-C3E2E6ED-14AE-52D1-9F11-618DCE7D2C1E"><p>binding an ISR to an
       
    54 audio related interrupt </p> </li>
       
    55 <li id="GUID-129BD014-9302-50AE-A33B-728D40DBF428"><p>open a DMA channel </p> </li>
       
    56 <li id="GUID-51B51BEC-B8B8-50CF-8618-BB0B5B00F999"><p>allocate a mono-to-stereo
       
    57 conversion buffer </p> </li>
       
    58 </ul> <p>The template versions of this function include code to set up a DMA
       
    59 channel. This involves opening a DMA channel in the appropriate direction
       
    60 for the driver channel and then allocating a set of DMA request objects. However,
       
    61 to use this implementation you must supply the missing platform specific information: </p> <ul>
       
    62 <li id="GUID-64F62CF9-9D26-5E39-A632-39DF91AB1E98"><p>Provide values for the
       
    63 maximum number of DMA requests outstanding on the DMA channel. These values
       
    64 determine the number of separate DMA request objects allocated for the DMA
       
    65 channel, and so the number of transfer fragments that the PDD can accept from
       
    66 the LDD at any time. See <xref href="GUID-15FDDEED-89F1-5BE5-97AD-8DFD3640369A.dita">playback</xref> and <xref href="GUID-4AEF7595-17C0-513E-9568-B212E6194388.dita">record</xref>. </p> </li>
       
    67 <li id="GUID-60C86EBD-B26F-501D-B7D5-CE113D4368C0"><p>Set the appropriate
       
    68 DMA values for your device within the file <filepath>soundsc_plat.h</filepath>.
       
    69 These values, renamed in section <xref href="GUID-C6ABE2CA-901E-55F1-9837-7018A1612BCF.dita">copying
       
    70 the template port implementation</xref> to reflect your device name, are <codeph>KTemplateMaxTxDmaRequests</codeph> or <codeph>KTemplateMaxRxDmaRequests</codeph> for playback and record respectively. </p> </li>
       
    71 <li id="GUID-BBF4F320-22A7-54AE-ACD1-6C10138F5031"><p>Setup the DMA channel
       
    72 information for the device. This includes the following members of <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita#GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37/GUID-6B973278-8BE7-3CE5-97D8-60E8D3F4D473"><apiname>TDmaChannel::SCreateInfo</apiname></xref>. </p> <ul>
       
    73 <li id="GUID-084CF2BA-308D-5F32-9BC2-C5B39DEC497B"><p> <codeph>iCookie</codeph>:
       
    74 The platform specific ID used by the DMA controller to select the DMA channel
       
    75 to open. </p> </li>
       
    76 <li id="GUID-7EE1F596-9FB5-5C29-8130-097CE6129F91"><p> <codeph>iDesCount</codeph>:
       
    77 The number of DMA descriptors the DMA controller should create. This is typically
       
    78 set with the same value as <codeph>KTemplateMaxTxDmaRequests</codeph> or <codeph>KTemplateMaxRxDmaRequests</codeph>. </p> </li>
       
    79 <li id="GUID-0B12DDF1-AC34-5592-AC55-E0363C60449A"><p> <codeph>iDfcQ</codeph>:
       
    80 The DFC queue to use to service DMA interrupts. This should point to the same
       
    81 DFC queue that is returned to the LDD for client request handling. See the <xref href="GUID-AC560324-798C-5D0A-B23D-2419A7688A5B.dita#GUID-AC560324-798C-5D0A-B23D-2419A7688A5B/GUID-32C77B77-76CE-54AE-B791-28A7DD309A7D">DfcQ()</xref> section. </p> </li>
       
    82 <li id="GUID-AE4E59DD-4FBB-54A8-BE79-F4138AB34D5C"><p> <codeph>iDfcPriority</codeph>:
       
    83 The DFC priority. This should be set to a higher value than that used by the
       
    84 LDD for handling client requests. For example, higher than one. </p> </li>
       
    85 </ul> </li>
       
    86 </ul> </section>
       
    87 <section id="GUID-32C77B77-76CE-54AE-B791-28A7DD309A7D"><title>DfcQ()</title> <p>Make
       
    88 sure that the template version of the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-C41B9733-BE86-3CF1-83A7-150EC9D35249"><apiname>DSoundScPdd::DfcQ()</apiname></xref> function
       
    89 is appropriate for your configuration. This function has the following signature: </p> <codeblock id="GUID-28E301B7-C032-5F6E-BCA7-A6D20FC541EA" xml:space="preserve">TDfcQue* DfcQ()</codeblock> <p>The
       
    90 supplied implementation is as follows </p> <codeblock id="GUID-D95DC9F9-C68A-50E2-ADA6-8D1268A18147" xml:space="preserve">TDfcQue* DTemplateSoundScTxPdd::DfcQ()
       
    91     {
       
    92     return(iPhysicalDevice-&gt;iDfcQPtr);
       
    93     }</codeblock> <p>Many requests are executed in the context of a kernel-side
       
    94 thread. Rather than assign a kernel thread for the driver in the LDD, the
       
    95 Sound Driver allows the PDD to specify the DFC thread returned via the <xref href="GUID-71190437-912E-3E23-8E68-4FA8FF913D7A.dita"><apiname>DfcQ()</apiname></xref> function,
       
    96 which it calls when the driver channel is opened. </p> <p>The default implementation
       
    97 for the record and playback driver channels, returns a pointer to the DFC
       
    98 queue created by the PDD factory class. </p> <p>See also <xref href="GUID-1138D29D-2EC5-59DF-9AA7-2D863FBC024F.dita">Implementing
       
    99 the PDD factory</xref>  </p> </section>
       
   100 <section id="GUID-B549F062-061D-5876-AB43-AC10C62477EE"><title>GetChunkCreateInfo()</title> <p>Implement
       
   101 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-9F845935-A6AA-320B-AF09-F121F95C44B2"><apiname>DSoundScPdd::GetChunkCreateInfo()</apiname></xref> function for both
       
   102 the playback and record driver channels. This function has the following signature: </p> <codeblock id="GUID-934D39E5-5DDE-5165-BCED-255CA6D0B0F2" xml:space="preserve">void DSoundScPdd::GetChunkCreateInfo(TChunkCreateInfo&amp; aChunkCreateInfo)</codeblock> <p>The
       
   103 supplied implementation is as follows: </p> <codeblock id="GUID-47334636-5E5D-59CF-A894-62747DD648BD" xml:space="preserve">void DTemplateSoundScTxPdd::GetChunkCreateInfo(TChunkCreateInfo&amp; aChunkCreateInfo)
       
   104     {
       
   105     __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::GetChunkCreateInfo"));
       
   106 
       
   107     // TO DO: (mandatory)
       
   108     // Setup the shared chunk create information in aChunkCreateInfo for this play device.
       
   109     aChunkCreateInfo.iType=TChunkCreateInfo::ESharedKernelMultiple;
       
   110     // aChunkCreateInfo.iMapAttr=???
       
   111     aChunkCreateInfo.iOwnsMemory=ETrue;                 // Using RAM pages.
       
   112     aChunkCreateInfo.iDestroyedDfc=NULL;                // No chunk destroy DFC.
       
   113     }</codeblock> <p>The PDD must initialise the <xref href="GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4.dita"><apiname>TChunkCreateInfo</apiname></xref> object
       
   114 with the information that defines the characteristics of the shared chunk
       
   115 required for the audio device. This function is called by the LDD just before
       
   116 it creates a shared chunk for the channel, in response to an <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-1978D84C-6E2A-39C0-AF5F-17C85E5B25B4"><apiname>RSoundSc::SetBufferChunkCreate()</apiname></xref> request
       
   117 from the client. </p> <p>Values for the following data members must be supplied
       
   118 by the PDD: </p> <ul>
       
   119 <li id="GUID-10F7ED98-299F-5D90-A7EC-85BD97BBECEF"><p> <xref href="GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4.dita#GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4/GUID-4384AF76-CECE-3B86-BE92-375C1DEA36DA"><apiname>TChunkCreateInfo::iType</apiname></xref>  </p> </li>
       
   120 <li id="GUID-10159693-8680-5CD7-88C8-A967DDC53024"><p> <xref href="GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4.dita#GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4/GUID-4D355352-04CA-34D2-B1F4-684E07E7DDE9"><apiname>TChunkCreateInfo::iMapAttr</apiname></xref>  </p> </li>
       
   121 <li id="GUID-06459B1A-5D5A-5013-912D-0C52E7FD398A"><p> <xref href="GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4.dita#GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4/GUID-106850A0-5498-387F-AF70-F9D04EB6318D"><apiname>TChunkCreateInfo::iOwnsMemory</apiname></xref>  </p> </li>
       
   122 <li id="GUID-D8DE49EB-04D5-50BA-8CEA-7EFFA7584A74"><p> <xref href="GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4.dita#GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4/GUID-58271733-146A-3ECB-91AC-C38BD2ADC9A0"><apiname>TChunkCreateInfo::iDestroyedDfc</apiname></xref>  </p> </li>
       
   123 </ul> <p>The data member <xref href="GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4.dita#GUID-51F7DBCF-BFB6-31F9-8882-5D263A1AD4B4/GUID-3BE6D452-84D0-3E80-8238-7A9114A89ED5"><apiname>TChunkCreateInfo::iMaxSize</apiname></xref> is
       
   124 calculated by the LDD so there is no need to define it. </p> <p>See <xref href="GUID-51514A4B-0220-557B-9F7A-FB110CEFEF10.dita">How to share chunks</xref>. </p> </section>
       
   125 <section id="GUID-9D4D9F06-8C88-51C1-9E29-D0B95B523A8D"><title>Caps()</title> <p>Implement
       
   126 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-B80B86C6-696A-37AA-9ACD-2BC76B88762C"><apiname>DSoundScPdd::Caps()</apiname></xref> function for both the playback
       
   127 and record driver channels. The function has the following signature: </p> <codeblock id="GUID-8306A135-350C-5F8D-B51D-F8A2EED41244" xml:space="preserve">void DSoundScPdd::Caps(TDes8&amp; aCapsBuf) const</codeblock> <p>The
       
   128 supplied implementation is as follows: </p> <codeblock id="GUID-27BE7DD7-D42B-54BA-AC77-1201C1F09F68" xml:space="preserve">void DTemplateSoundScTxPdd::Caps(TDes8&amp; aCapsBuf) const
       
   129     {
       
   130     __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::Caps"));
       
   131     
       
   132     // Copy iCaps back.
       
   133     TPtrC8 ptr((const TUint8*)&amp;iCaps,sizeof(iCaps));
       
   134     aCapsBuf.FillZ(aCapsBuf.MaxLength());
       
   135     aCapsBuf=ptr.Left(Min(ptr.Length(),aCapsBuf.MaxLength()));      
       
   136     }</codeblock> <p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita"><apiname>TSoundFormatsSupportedV02</apiname></xref> is the
       
   137 main audio capabilities class. The PDD must fill this object with the capabilities
       
   138 for the particular audio device. the LDD uses this to get the play or record
       
   139 capabilities of a particular sound device once a driver channel to the device
       
   140 has been opened. </p> <p>Values for the following variables must be supplied
       
   141 by the PDD: </p> <ul>
       
   142 <li id="GUID-2F03F186-D9AF-5431-B3F8-D3B794352208"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-1FE2868A-1823-308A-B1C9-2DAD557F6F3A"><apiname>TSoundFormatsSupportedV02::iDirection</apiname></xref>  </p> <ul>
       
   143 <li id="GUID-053B114E-2A52-53FD-912F-F8FF890601C4"><p> <xref href="GUID-AF772B74-0D5F-3270-BA61-2503BA5DFE6B.dita"><apiname>ESoundDirRecord</apiname></xref>  </p> </li>
       
   144 <li id="GUID-CEADC6F1-6016-5AB1-9349-EEFB63EF26AA"><p> <xref href="GUID-708043EB-5ED5-3923-B41A-321AD7DF3D8C.dita"><apiname>ESoundDirPlayback</apiname></xref>  </p> </li>
       
   145 </ul> </li>
       
   146 <li id="GUID-95FC1D2B-BBFB-52DC-ADE3-BA980E7E46F3"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-75B0E2F7-44BE-3A97-B482-E1CB29D9F2E5"><apiname>TSoundFormatsSupportedV02::iChannels</apiname></xref>  </p> <ul>
       
   147 <li id="GUID-998425C3-E73B-5DB4-94F8-10BDCFBBE779"><p> <xref href="GUID-65BCF594-59A1-335F-AADB-1920E7AD3F71.dita"><apiname>KSoundMonoChannel</apiname></xref>  </p> </li>
       
   148 <li id="GUID-7D5EE578-16AC-56A0-B064-6000F5A9C2DF"><p> <xref href="GUID-4E63CE9C-C604-3B2C-993D-9A0502A39064.dita"><apiname>KSoundStereoChannel</apiname></xref>  </p> </li>
       
   149 <li id="GUID-0C17CB17-7452-5A1A-B76D-75A57960BDE8"><p> <xref href="GUID-30E8F803-39E1-3F53-AB5A-3B593BC1D69F.dita"><apiname>KSoundThreeChannel</apiname></xref>  </p> </li>
       
   150 <li id="GUID-E1DE0CD0-DD63-5140-A5C5-7141A5E9632D"><p> <xref href="GUID-BD021640-3457-3721-9DF1-A15EE8A874AC.dita"><apiname>KSoundFourChannel</apiname></xref>  </p> </li>
       
   151 <li id="GUID-E59E9D5E-F360-52FD-A0D0-C7CDAE5593DC"><p> <xref href="GUID-3E3B5485-F69B-3ECC-A0A4-12183444E61F.dita"><apiname>KSoundFiveChannel</apiname></xref>  </p> </li>
       
   152 <li id="GUID-56DD5098-0C0C-5175-B375-766FE628C359"><p> <xref href="GUID-83C9F5FE-DE44-3940-B738-BD4486293C39.dita"><apiname>KSoundSixChannel</apiname></xref>  </p> </li>
       
   153 </ul> </li>
       
   154 <li id="GUID-A6847CF6-48DC-510E-BCFF-33E7E5FB0161"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-1F79E9BB-BF7C-31AD-AA0C-A85748F4231A"><apiname>TSoundFormatsSupportedV02::iRates</apiname></xref>  </p> <ul>
       
   155 <li id="GUID-99377F03-BA89-5DB0-AC4D-5F8892EB1F65"><p> <xref href="GUID-F98BADA5-852B-3859-B74A-B9747F79A754.dita"><apiname>KSoundRate7350Hz</apiname></xref>  </p> </li>
       
   156 <li id="GUID-99FFC99B-740B-5809-9C75-C8CC1157F4E3"><p> <xref href="GUID-47512813-5787-3328-9980-399AA782E6A2.dita"><apiname>KSoundRate8000Hz</apiname></xref>  </p> </li>
       
   157 <li id="GUID-D2C75BB5-5D8B-556B-A5BF-6A8C24D07D74"><p> <xref href="GUID-A622C93B-DF18-359D-B74A-0F90695900B7.dita"><apiname>KSoundRate8820Hz</apiname></xref>  </p> </li>
       
   158 <li id="GUID-83D98EBD-AD0E-588E-8CFD-59B44C22FE6A"><p> <xref href="GUID-165180AC-1227-30BF-97DA-860C3AC3AA4E.dita"><apiname>KSoundRate9600Hz</apiname></xref>  </p> </li>
       
   159 <li id="GUID-8D99D6B7-7FA7-5B8A-BEB9-2D982273C201"><p> <xref href="GUID-8DF1D395-4AC1-38AA-9F6A-C8867B1F4A60.dita"><apiname>KSoundRate11025Hz</apiname></xref>  </p> </li>
       
   160 <li id="GUID-98353A3A-EFAC-5B6C-A779-8F12BB9150BA"><p> <xref href="GUID-512150A4-0796-3016-9CBC-83117E2930ED.dita"><apiname>KSoundRate12000Hz</apiname></xref>  </p> </li>
       
   161 <li id="GUID-C27DD198-13FA-522A-9079-0BAA37094E16"><p> <xref href="GUID-892B4698-4914-348B-AB88-A1AC33D1E5EE.dita"><apiname>KSoundRate14700Hz</apiname></xref>  </p> </li>
       
   162 <li id="GUID-71087DE2-06A9-536A-94DF-74FFFCB2F0DF"><p> <xref href="GUID-1A199051-5D76-396B-AA44-89506A128BFF.dita"><apiname>KSoundRate16000Hz</apiname></xref>  </p> </li>
       
   163 <li id="GUID-666FA027-30AF-593B-894B-443B5C57E2DF"><p> <xref href="GUID-4021CE80-6667-36BB-9839-583E84AB9E83.dita"><apiname>KSoundRate22050Hz</apiname></xref>  </p> </li>
       
   164 <li id="GUID-9D0D7E14-1FBE-5C80-A108-D3903D57ED49"><p> <xref href="GUID-73C38AA3-92AD-3EF0-BF60-3A207CD29C0E.dita"><apiname>KSoundRate24000Hz</apiname></xref>  </p> </li>
       
   165 <li id="GUID-721DCA57-6E9B-5B02-9EA4-7640C652C5CE"><p> <xref href="GUID-9092C33B-C406-3044-AC8F-885F3EAE8B86.dita"><apiname>KSoundRate29400Hz</apiname></xref>  </p> </li>
       
   166 <li id="GUID-5362CD78-1981-559B-9E1B-C999CDC8E3D9"><p> <xref href="GUID-0237DB93-3C16-3DCF-836E-CDECE95EAB1E.dita"><apiname>KSoundRate32000Hz</apiname></xref>  </p> </li>
       
   167 <li id="GUID-61D0A788-2160-538F-82DB-414E6A34EC97"><p> <xref href="GUID-D3045D52-3092-3CCA-9AA5-05DE1ACAB92C.dita"><apiname>KSoundRate44100Hz</apiname></xref>  </p> </li>
       
   168 <li id="GUID-28474DAC-AD25-506B-9112-F56825F845D2"><p> <xref href="GUID-DBD2AD6A-79F9-3D94-B6CB-1ED1E45F401A.dita"><apiname>KSoundRate48000Hz</apiname></xref>  </p> </li>
       
   169 </ul> </li>
       
   170 <li id="GUID-CB112345-C035-5F7E-9AE5-B5222FF4F0A9"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-21F664A7-046E-3B1F-8C0B-A8B0EC0EC16C"><apiname>TSoundFormatsSupportedV02::iEncodings</apiname></xref>  </p> <ul>
       
   171 <li id="GUID-F5833DD3-D273-5B62-9F4B-FEEC51D8CDF2"><p> <xref href="GUID-5BE58F42-47B2-3EB8-9F3B-DEF019C79499.dita"><apiname>KSoundEncodings8BitPCM</apiname></xref>  </p> </li>
       
   172 <li id="GUID-B58CB616-CDCD-5CD0-AEC4-622F5AAB2474"><p> <xref href="GUID-790BA733-2B34-33B2-BF7B-7113DB1856A6.dita"><apiname>KSoundEncodings16BitPCM</apiname></xref>  </p> </li>
       
   173 <li id="GUID-A4019328-CC8B-5224-8808-F3822230C389"><p> <xref href="GUID-EAB5A509-B0D6-3E2F-8106-D87A7C9D504F.dita"><apiname>KSoundEncodings24BitPCM</apiname></xref>  </p> </li>
       
   174 </ul> </li>
       
   175 <li id="GUID-52DDB751-925B-5CC5-81F9-6F65A9D2039E"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-7950BC29-5C2E-34E0-B037-DDDDE0261DB7"><apiname>TSoundFormatsSupportedV02::iDataFormats</apiname></xref>  </p> <ul>
       
   176 <li id="GUID-AD7EA560-7914-5D9D-B548-14DB3FA4AC7A"><p> <xref href="GUID-E02D661C-430F-306F-BD12-42238A91D83A.dita"><apiname>KSoundDataFormatInterleaved</apiname></xref>  </p> </li>
       
   177 <li id="GUID-36EAAA69-B18A-555A-9646-FB8F6EC66505"><p> <xref href="GUID-ACC09AC6-A29B-3926-8AE4-4DA60416A3C1.dita"><apiname>KSoundDataFormatNonInterleaved</apiname></xref>  </p> </li>
       
   178 </ul> </li>
       
   179 <li id="GUID-905CC707-760B-52F3-A942-0ADA02B69FA8"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-6F2D37B3-C465-3C77-A861-7FF9061F8EB9"><apiname>TSoundFormatsSupportedV02::iRequestMinSize</apiname></xref>  </p> </li>
       
   180 <li id="GUID-8FCD4F3E-F70F-5E1B-8952-B667DC9D4AD2"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-472BCD65-11CE-3AEE-8DAE-9E56523AC096"><apiname>TSoundFormatsSupportedV02::iRequestAlignment</apiname></xref>  </p> </li>
       
   181 <li id="GUID-749CE201-0554-5202-ABFC-FF9C0C4B1C1A"><p> <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita#GUID-39915413-31A6-360F-9758-5DBDF9D70103/GUID-AB35243B-ECD9-3268-A6FF-5079D1A45EA0"><apiname>TSoundFormatsSupportedV02::iHwConfigNotificationSupport</apiname></xref> </p> </li>
       
   182 </ul> <p>Many of the attribute ranges are passed as bit settings, and can
       
   183 assume all the values independently of one another. </p> <p>The following
       
   184 is a portion of the <xref href="GUID-161BA615-FD2C-3A7E-992E-FBBED621CBBB.dita"><apiname>Caps()</apiname></xref> function for the template port
       
   185 for the playback path of the AC97 Controller Unit (UCB140) codec device. </p> <p>The
       
   186 PDD maintains a <xref href="GUID-39915413-31A6-360F-9758-5DBDF9D70103.dita"><apiname>TSoundFormatsSupportedV02</apiname></xref> object as one
       
   187 of its data members named <codeph>iCaps</codeph>. The contents of <codeph>iCaps</codeph> is
       
   188 copied into the descriptor and passed as an argument to the <xref href="GUID-161BA615-FD2C-3A7E-992E-FBBED621CBBB.dita"><apiname>Caps()</apiname></xref> function: </p> <codeblock id="GUID-21B70DCD-7133-53A1-AE5C-848E0F68DF43" xml:space="preserve">void DTemplateSoundScTxPdd::Caps(TDes8&amp; aCapsBuf) const
       
   189     {
       
   190      __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::Caps"));
       
   191     
       
   192      // Copy iCaps back.
       
   193      TPtrC8 ptr((const TUint8*)&amp;iCaps,sizeof(iCaps));
       
   194      aCapsBuf.FillZ(aCapsBuf.MaxLength());
       
   195      aCapsBuf=ptr.Left(Min(ptr.Length(),aCapsBuf.MaxLength()));        
       
   196     }
       
   197 </codeblock> <p>The data member <codeph>iCaps</codeph> is initialised by the
       
   198 function <xref href="GUID-681FB26E-0027-38E6-88A1-9E9046011312.dita"><apiname>SetCaps()</apiname></xref> called from the second stage constructor
       
   199 of the PDD object: </p> <codeblock id="GUID-B17BA93D-14D6-56A9-8F1F-9FFEF88559D3" xml:space="preserve">void DTemplateSoundScTxPdd::SetCaps()
       
   200     {
       
   201      __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::SetCaps"));
       
   202     
       
   203      // The data transfer direction for this unit is play.
       
   204      iCaps.iDirection=ESoundDirPlayback;
       
   205     
       
   206      // TO DO: (mandatory)
       
   207      // Setup the rest of the capabilities structure DTemplateSoundScTxPdd::iCaps with the capabilities of this
       
   208      // audio playback device.
       
   209     }</codeblock> </section>
       
   210 <section id="GUID-A2A7A6FF-8F46-589D-B5D6-E33ED3FF0692"><title>MaxTransferLen()</title> <p>Implement
       
   211 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-534D46F4-2CB1-3130-9E72-A1C3BF085865"><apiname>DSoundScPdd::MaxTransferLen()</apiname></xref> function for both playback
       
   212 and record driver channels. The function has the following signature: </p> <codeblock id="GUID-039E8EF1-AA13-5C38-92DD-46AFC8E1E8F3" xml:space="preserve">TInt DSoundScPdd::MaxTransferLen() const</codeblock> <p>The
       
   213 supplied implementation is as follows: </p> <codeblock id="GUID-E27E52F5-175A-5264-8B08-AE0BDAD5B495" xml:space="preserve">TInt DTemplateSoundScTxPdd::MaxTransferLen() const
       
   214     {
       
   215     return(KTemplateMaxTxDmaTransferLen);
       
   216     }</codeblock> <p>This function is called each time the LDD alters the
       
   217 audio configuration of the channel. For example, after calling <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-39AA2B2D-E98B-33A0-9C46-08B783413860"><apiname>DSoundScPdd::SetConfig()</apiname></xref>.
       
   218 The LDD uses the value returned to fragment record and playback data transfers
       
   219 so that they are manageable by the PDD. See <xref href="GUID-15FDDEED-89F1-5BE5-97AD-8DFD3640369A.dita">playback</xref> and <xref href="GUID-4AEF7595-17C0-513E-9568-B212E6194388.dita">record</xref>. </p> <p>The
       
   220 value returned by <xref href="GUID-615DF55C-EC50-3BF0-9C46-AB24E9505C5E.dita"><apiname>MaxTransferLen()</apiname></xref> is not as important
       
   221 for PDDs that use the Symbian DMA framework because the DMA framework handles
       
   222 fragmentation. </p> <p>If the PDD has to employ mono-to-stereo data conversion
       
   223 using a conversion buffer when configured in mono mode, then it needs to return
       
   224 the value that corresponds with the size of the conversion buffer each time
       
   225 it is configured in mono mode. See <xref href="GUID-E2641957-8163-5EF4-B282-FC3FD9CA75A6.dita#GUID-E2641957-8163-5EF4-B282-FC3FD9CA75A6/GUID-5C66667B-55C0-521D-86E3-67593DB381C9">mono
       
   226 to stereo conversion</xref>. </p> </section>
       
   227 <section id="GUID-B72057E6-B93C-505F-9789-83251D09B78E"><title>PowerUp()</title> <p>Implement
       
   228 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-6301A4AA-CC41-3DBC-A349-9BD5C9B01276"><apiname>DSoundScPdd::PowerUp</apiname></xref> function for both the playback
       
   229 and record driver channels. The function has the following signature: </p> <codeblock id="GUID-F9706BE3-125F-56B3-947E-3534FB3A5D23" xml:space="preserve">TInt DSoundScPdd::PowerUp()</codeblock> <p>The
       
   230 supplied implementation is as follows: </p> <codeblock id="GUID-DB986B0B-CC10-5842-BB54-76683A35EB38" xml:space="preserve">TInt DTemplateSoundScTxPdd::PowerUp()
       
   231     {
       
   232     // TO DO: (mandatory)
       
   233     // Power up the audio device.
       
   234     
       
   235     return(KErrNone);
       
   236     }</codeblock> <p>This function initialises the codec device and any associated
       
   237 controller hardware that allows the CPU to communicate with it. However, at
       
   238 this stage only basic initialisation of these hardware components is required,
       
   239 as the specific audio configuration has not yet been specified, and data transfer
       
   240 has not yet started. </p> <p>If the PDD supports both record and playback
       
   241 driver channels then most, if not all, of this hardware initialisation is
       
   242 common to both channels. It may be necessary to ensure that such initialisation
       
   243 on one channel cannot interfere with the other. For example, when calling <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-1B2E2F89-75A8-3740-893A-4DCDB0A350D3"><apiname>DSoundScPdd::PowerUp()</apiname></xref> on
       
   244 the record driver channel while the playback driver channel is active, make
       
   245 sure that it does not interfere with audio playback. This typically requires
       
   246 hardware status information to be held in the PDD factory object that is common
       
   247 to both channels. </p> </section>
       
   248 <section id="GUID-3764C238-A458-5D13-8AB2-EE53CA91F6E5"><title>SetConfig()</title> <p>Implement
       
   249 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-39AA2B2D-E98B-33A0-9C46-08B783413860"><apiname>DSoundScPdd::SetConfig()</apiname></xref> function for both playback
       
   250 and record driver channels. The function has the following signature: </p> <codeblock id="GUID-DB782F12-E5CE-5D13-8C12-8E57AB47BDB4" xml:space="preserve">TInt DSoundScPdd::SetConfig(const TDesC8&amp; aConfigBuf)</codeblock> <codeblock id="GUID-868A3301-3CAD-5077-88AC-2A2A6C125AFD" xml:space="preserve">TInt DTemplateSoundScTxPdd::SetConfig(const TDesC8&amp; aConfigBuf)
       
   251     {
       
   252     __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::SetConfig"));
       
   253     
       
   254     // Read the new configuration from the LDD.
       
   255     TCurrentSoundFormatV02 config;
       
   256     TPtr8 ptr((TUint8*)&amp;config,sizeof(config));
       
   257     Kern::InfoCopy(ptr,aConfigBuf);
       
   258     
       
   259     // TO DO: (mandatory)
       
   260     // Apply the specified audio configuration to the audio device.
       
   261     TInt r=KErrNone;
       
   262     
       
   263     __KTRACE_SND(Kern::Printf("&lt;DTemplateSoundScTxPdd::SetConfig - %d",r));
       
   264     return(r);
       
   265     }</codeblock> <p>A configuration buffer in a packaged <xref href="GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68.dita"><apiname>TCurrentSoundFormatV02</apiname></xref> object
       
   266 containing the new configuration settings. </p> <ul>
       
   267 <li id="GUID-2D88064E-2258-55FA-BE68-831889E9E2C8"><p> <xref href="GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68.dita#GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68/GUID-AE4EDE94-5902-3D73-BAE4-4A49B3E3CC6C"><apiname>TCurrentSoundFormatV02::iChannels</apiname></xref>  </p> </li>
       
   268 <li id="GUID-CBACC0C9-1C73-59E0-BAA4-63110DECDED9"><p> <xref href="GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68.dita#GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68/GUID-FA39A28F-4B0C-3B89-AB4B-763E0369AD31"><apiname>TCurrentSoundFormatV02::iRate</apiname></xref>  </p> <ul>
       
   269 <li id="GUID-00FD1F5A-7941-5ED8-9878-69EDAE03F630"><p> <xref href="GUID-306655BD-FD24-37CE-8F67-F6BC5FBAA455.dita"><apiname>ESoundRate7350Hz</apiname></xref>  </p> </li>
       
   270 <li id="GUID-3BEB74D8-B829-5B49-A740-F4BC0597E389"><p> <xref href="GUID-F6D595E9-BE6E-3D5F-AEEF-57FEBA5D165F.dita"><apiname>ESoundRate8000Hz</apiname></xref>  </p> </li>
       
   271 <li id="GUID-E077B1A6-A625-55C8-8587-96EF7242C5F0"><p> <xref href="GUID-256AD4BA-8D30-38B8-8AC3-A63AFDCDF82E.dita"><apiname>ESoundRate8820Hz</apiname></xref>  </p> </li>
       
   272 <li id="GUID-5664E1E2-DBC3-5F2C-A5BD-3EE5512C254E"><p> <xref href="GUID-3A48C172-FEEF-3A5A-A986-E5C1FD8E5048.dita"><apiname>ESoundRate9600Hz</apiname></xref>  </p> </li>
       
   273 <li id="GUID-7E607F76-3975-591F-AEE3-D4CBC2B0F003"><p> <xref href="GUID-0B13D3F1-57D0-3741-BCC8-3E3BE50B59DE.dita"><apiname>ESoundRate11025Hz</apiname></xref>  </p> </li>
       
   274 <li id="GUID-8054CF86-27CF-531A-9233-C6602BB958EF"><p> <xref href="GUID-88C3603E-D69F-3DE9-9AA0-F6F724432C76.dita"><apiname>ESoundRate12000Hz</apiname></xref>  </p> </li>
       
   275 <li id="GUID-1AD1415C-0D0D-508F-B63E-69B553AA4109"><p> <xref href="GUID-D49E0BA6-AB68-334A-BECF-7221996C71CF.dita"><apiname>ESoundRate14700Hz</apiname></xref>  </p> </li>
       
   276 <li id="GUID-1D23B890-0AFC-5E2B-8D00-E56CF1E75D07"><p> <xref href="GUID-6FDDFE56-B32E-3DA1-8E90-DCAE1476A75F.dita"><apiname>ESoundRate16000Hz</apiname></xref>  </p> </li>
       
   277 <li id="GUID-A2637B2C-AD6B-5A87-86AC-FDB56DBF46C0"><p> <xref href="GUID-86882923-4DB3-3461-AF9E-D36BF75125AB.dita"><apiname>ESoundRate22050Hz</apiname></xref>  </p> </li>
       
   278 <li id="GUID-8682C600-A7C8-5B8B-9824-DD670812C598"><p> <xref href="GUID-2E1FC700-5B43-39DE-8B67-7DADD38B55A5.dita"><apiname>ESoundRate24000Hz</apiname></xref>  </p> </li>
       
   279 <li id="GUID-51A42D66-5B71-5325-90B7-B5A1503F21C5"><p> <xref href="GUID-244A1091-0F4A-376B-AE3E-93F09029ECF0.dita"><apiname>ESoundRate29400Hz</apiname></xref>  </p> </li>
       
   280 <li id="GUID-04621385-220C-587B-9C59-68115E251D8C"><p> <xref href="GUID-1C1526A2-4BA2-3296-BBE0-152070B43EE9.dita"><apiname>ESoundRate32000Hz</apiname></xref>  </p> </li>
       
   281 <li id="GUID-5DECBAD3-09E7-5967-82B3-7C923F870DA6"><p> <xref href="GUID-028FCDA8-E1FC-3E5D-827B-E4513991C1F2.dita"><apiname>ESoundRate44100Hz</apiname></xref>  </p> </li>
       
   282 <li id="GUID-27AA4D39-3CA5-52A0-9F97-C8543AAECB97"><p> <xref href="GUID-14D9C50A-2F72-3D1D-A15B-BDE4FAA33ED8.dita"><apiname>ESoundRate48000Hz</apiname></xref>  </p> </li>
       
   283 </ul> </li>
       
   284 <li id="GUID-95DDDF4C-B70E-56B1-92E6-616ADCB45025"><p> <xref href="GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68.dita#GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68/GUID-1A4256A2-A2FE-3FD0-8849-A9F37E1D7A77"><apiname>TCurrentSoundFormatV02::iEncoding</apiname></xref>  </p> <ul>
       
   285 <li id="GUID-48484A2E-6970-59AE-9CD5-C93BE349C28D"><p> <xref href="GUID-866386CC-C9CA-3029-95C2-800F6B6C3C2D.dita"><apiname>ESoundEncoding8BitPCM</apiname></xref>  </p> </li>
       
   286 <li id="GUID-357130A0-C112-5803-A4D3-9B1237B5931C"><p> <xref href="GUID-E69FCDC5-9A22-3C5A-89C9-A7B869744948.dita"><apiname>ESoundEncoding16BitPCM</apiname></xref>  </p> </li>
       
   287 <li id="GUID-E2920329-BDFC-5B28-BF53-F4CF45DBE9AC"><p> <xref href="GUID-289CBD4B-ACEF-3A43-8935-201635AC658F.dita"><apiname>ESoundEncoding24BitPCM</apiname></xref>  </p> </li>
       
   288 </ul> </li>
       
   289 <li id="GUID-406F8EE9-885D-5569-98E0-A473BB7462FB"><p> <xref href="GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68.dita#GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68/GUID-3A9546CB-33D6-3171-A8F7-0E642EB8E798"><apiname>TCurrentSoundFormatV02::iDataformat</apiname></xref>  </p> <ul>
       
   290 <li id="GUID-D21416A0-3E78-5D5C-BFE3-0C8A75F80429"><p> <xref href="GUID-5ADC3C98-2D05-35E1-96D2-42B3A65BF25F.dita"><apiname>ESoundDateFormatInterleaved</apiname></xref>  </p> </li>
       
   291 <li id="GUID-1A7EC2CC-D94F-514E-BB8A-9A3B3551B13F"><p> <xref href="GUID-352ED2EF-C98C-305E-80F1-FE30DF1BE4CA.dita"><apiname>ESoundDateFormatNonInterleaved</apiname></xref>  </p> </li>
       
   292 </ul> </li>
       
   293 </ul> <p>The PDD must read and locally save the contents of the <xref href="GUID-EF1D41AB-929D-3E51-98AA-F175DDB58F68.dita"><apiname>TCurrentSoundFormatV02</apiname></xref> configuration
       
   294 object that has been passed as a descriptor from the LDD. The template version
       
   295 contains the following code to achieve this: </p> <codeblock id="GUID-7FF5383E-FAE0-51A7-8E9E-0F489D841C72" xml:space="preserve">// Read the new configuration from the LDD.
       
   296 TCurrentSoundFormatV02 config;
       
   297 TPtr8 ptr((TUint8*)&amp;config, sizeof(config));
       
   298 Kern::InfoCopy(ptr, aConfigBuf);</codeblock> <p>It is not necessary to check
       
   299 for configurations requested by the LDD that are not supported by the audio
       
   300 hardware device if the <xref href="GUID-161BA615-FD2C-3A7E-992E-FBBED621CBBB.dita"><apiname>Caps()</apiname></xref> function has been implemented
       
   301 correctly by the PDD. This is because the LDD rejects such audio configuration
       
   302 requests from the client. However, if the PDD supports both playback and record
       
   303 driver channels then it needs to check that the specified configuration does
       
   304 not conflict with one already in use by the other channel. </p> <p>The PDD
       
   305 sets up the audio hardware device according to the audio configuration specified
       
   306 if it is required. Some, if not all of this hardware configuration may be
       
   307 put off until data transfer is started, this is when <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-54D3CC19-0C00-3FFA-BD1A-62618D36EB20"><apiname>DSoundScPdd::StartTransfer()</apiname></xref> is
       
   308 called, so for now the PDD needs to save the configuration. </p> <p>If the
       
   309 PDD has to employ mono-to-stereo conversion of data using a conversion buffer
       
   310 while the audio configuration is set to mono, then the memory for the conversion
       
   311 buffer should be allocated at this time. </p> </section>
       
   312 <section id="GUID-51420A2F-180B-5916-AF5A-685ABD156A2D"><title>SetVolume()</title> <p>Implement
       
   313 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-3C56E870-1F05-31BC-B799-AF49F77E2930"><apiname>DSoundScPdd::SetVolume</apiname></xref> function for both the playback
       
   314 and record driver channels. This has the following signature: </p> <codeblock id="GUID-6FEA0876-7753-54C7-A414-9A54913F1778" xml:space="preserve">TInt DSoundScPdd::SetVolume(TInt aVolume)</codeblock> <p>The
       
   315 supplied implementation is as follows: </p> <codeblock id="GUID-14196DC5-8630-5E06-869A-D9A5EE423BF6" xml:space="preserve">TInt DTemplateSoundScTxPdd::SetVolume(TInt aVolume)
       
   316     {
       
   317     __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::SetVolume"));
       
   318     
       
   319     // TO DO: (mandatory)
       
   320     // Set the specified play volume on the audio device.
       
   321     TInt r=KErrNone;
       
   322     
       
   323     return(r);
       
   324     }</codeblock> <p>The PDD must first convert the volume/record level information
       
   325 specified into a form which can be used to program the hardware. This may
       
   326 require converting the value from a gain factor to an attenuation factor and/or
       
   327 applying a scaling factor. The LDD detects situations where the client specifies
       
   328 a record level /volume that is already in effect, and in this case does not
       
   329 unnecessarily call the PDD. </p> <p>The PDD may opt to setup the audio hardware
       
   330 device within this function or it may defer this until data transfer is started
       
   331 with the function <xref href="GUID-CCACE58D-8884-37A4-B7DB-F1DFDEE4A8F1.dita#GUID-CCACE58D-8884-37A4-B7DB-F1DFDEE4A8F1/GUID-788592C9-FCCA-3E34-BEA7-5DC5E6A497C8"><apiname>DSOundScPdd::StartTransfer()</apiname></xref>. For PDDs
       
   332 which support both record and playback driver channels, it is normal for audio
       
   333 devices to allow the record and playback gains to be programmed independently,
       
   334 this means that checking for conflicts between the channels is rarely required
       
   335 for this function. </p> </section>
       
   336 <section id="GUID-287BB55C-E0FD-5214-9FAA-857AB46C64ED"><title>StartTransfer()</title> <p>Implement
       
   337 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-66F3D9DA-F61F-3C1D-8C95-02C7C561AE64"><apiname>DSoundScPdd::StartTransfer</apiname></xref> function for both the playback
       
   338 and record driver channels. This has the following signature: </p> <codeblock id="GUID-02F7B0B7-35A7-525C-A88D-6555113D6D62" xml:space="preserve">TInt DSoundScPdd::StartTransfer()</codeblock> <p>The
       
   339 supplied implementation is as follows: </p> <codeblock id="GUID-DE7BF31A-B5D4-5348-9280-0C326D37DAF8" xml:space="preserve">TInt DTemplateSoundScTxPdd::StartTransfer()
       
   340     {
       
   341     __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::StartTransfer"));
       
   342     
       
   343     // TO DO: (mandatory)
       
   344     // Prepare the audio device for playback.
       
   345     TInt r=KErrNone;
       
   346     
       
   347     __KTRACE_SND(Kern::Printf("&lt;DTemplateSoundScTxPdd::StartTransfer - %d",r));
       
   348     return(r);
       
   349     }</codeblock> <p>This function performs any configurations of the audio
       
   350 hardware device that were deferred from the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-39AA2B2D-E98B-33A0-9C46-08B783413860"><apiname>DSoundScPdd::SetConfig()</apiname></xref> function.
       
   351 These configurations may include start-up of the DMA engine, enabling any
       
   352 interrupts related to audio transfer and interrupts that detect error conditions,
       
   353 for example. At this stage, no data has yet been supplied to the device for
       
   354 transfer as the function <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref> has
       
   355 not yet been called. </p> <p>If the PDD supports both record and playback
       
   356 driver channels then it may be necessary to ensure that such hardware configuration
       
   357 on one channel cannot interfere with the other. </p> </section>
       
   358 <section id="GUID-5E29637F-140F-5F1B-B969-DF9682CEF5E2"><title>TransferData()</title> <p>Implement
       
   359 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-EF749829-6C35-3954-A48D-483FD0182CC9"><apiname>DSoundScPdd::TransferData</apiname></xref> function for both playback
       
   360 and record driver channels. This has the following signature: </p> <codeblock id="GUID-F13C3C46-D208-5E24-B986-3A32FAFBE453" xml:space="preserve">TInt DSoundScPdd::TransferData(TUint aTransferID,TLinAddr aLinAddr,
       
   361                                TPhysAddr aPhysAddr,TInt aNumBytes)</codeblock> <p>Once
       
   362 transfer has been started by calling <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-54D3CC19-0C00-3FFA-BD1A-62618D36EB20"><apiname>DSoundScPdd::StartTransfer()</apiname></xref>,
       
   363 the function <xref href="GUID-209D8909-56BD-3601-98C4-FB6E004D78EE.dita"><apiname>TransferData</apiname></xref> is called repeatedly by the LDD
       
   364 for the transfer of each fragment. See the <xref href="GUID-15FDDEED-89F1-5BE5-97AD-8DFD3640369A.dita">playback</xref> and <xref href="GUID-4AEF7595-17C0-513E-9568-B212E6194388.dita">record</xref> sections for
       
   365 details. </p> <p>The template version for the record driver channel contains
       
   366 the following code: </p> <codeblock id="GUID-C86982D4-A2FE-5904-A46C-D52D349D018E" xml:space="preserve">TInt DTemplateSoundScRxPdd::TransferData(TUint aTransferID, TLinAddr aLinAddr,
       
   367                                          TPhysAddr /*aPhysAddr*/, TInt aNumBytes)
       
   368     {  
       
   369     TInt r=KErrNone;
       
   370    
       
   371     // Check that we can accept the request
       
   372     if (iPendingRecord&gt;=KTemplateMaxRxDmaRequests)
       
   373         r=KErrNotReady;
       
   374     else
       
   375         {
       
   376         // Start a DMA transfer.
       
   377         iDmaRequest[iFlag]-&gt;iTransferID=aTransferID;
       
   378         iDmaRequest[iFlag]-&gt;iTransferSize=aNumBytes;
       
   379         // TO DO: (mandatory)
       
   380         // Supply the DMA source information.
       
   381         TUint32 src=0; // ???
       
   382         r=iDmaRequest[iFlag]-&gt;Fragment(src,aLinAddr,aNumBytes,KDmaMemDest|KDmaIncDest,0);
       
   383         if (r==KErrNone)
       
   384             {
       
   385             iDmaRequest[iFlag]-&gt;Queue();
       
   386             iPendingRecord++;
       
   387             if ((++iFlag)&gt;=KTemplateMaxRxDmaRequests)
       
   388                 iFlag=0;
       
   389          
       
   390             // TO DO: (mandatory)
       
   391             // Start the audio device transferring data.
       
   392             }
       
   393         }
       
   394                                     
       
   395     return(r);
       
   396     }</codeblock> <p><note> The template version used by the playback function
       
   397 is very similar. </note></p> <p>The first step is for the PDD to check that
       
   398 it has the capacity to accept a further transfer. For example, check that
       
   399 the PDD has a DMA request object that is free and that the DMA controller
       
   400 has the capacity for another transfer to be queued. If the PDD does not have
       
   401 the capacity to accept another transfer then it should immediately return <xref href="GUID-51298FCE-7857-39F8-BFAB-49AF5556D0CC.dita"><apiname>KErrNotReady</apiname></xref> to
       
   402 signal this. </p> <p>Otherwise, the PDD can start a DMA transfer. To do this
       
   403 it must acquire a DMA request object. The class <xref href="GUID-6B0DB695-9033-3F85-AC3A-1867E99BE2BD.dita"><apiname>DTemplateSoundScRxDmaRequest</apiname></xref> is
       
   404 the abstraction for a DMA record request and is defined as follows: </p> <codeblock id="GUID-04B1D7FD-4E17-5CD0-974F-A3A1BCB04C58" xml:space="preserve">/** Wrapper function for a shared chunk sound driver record DMA request. */
       
   405 class DTemplateSoundScRxDmaRequest : public DDmaRequest
       
   406     {
       
   407 public:  
       
   408     DTemplateSoundScRxDmaRequest(TDmaChannel&amp; aChannel, DTemplateSoundScRxPdd* aPdd,
       
   409                                  TInt aMaxTransferSize=0);
       
   410     static void DmaService(TResult aResult, TAny* aArg);
       
   411 public:
       
   412     /** Pointer back to the PDD. */
       
   413     DTemplateSoundScRxPdd* iPdd;
       
   414     /** The transfer ID for this DMA request - supplied by the LDD. */
       
   415     TUint iTransferID;
       
   416     /** The transfer sizes in progress. */
       
   417     TUint iTransferSize;
       
   418     };
       
   419     This is derived from DDmaRequest the base class
       
   420     for a DMA request.</codeblock> <p>The data member <codeph>iPdd</codeph> is
       
   421 a pointer to the owning PDD object. This is used within the member function <xref href="GUID-8B538AA6-9489-309F-8756-2474310CD5DA.dita"><apiname>DmaService()</apiname></xref> which
       
   422 is the DMA callback function, and is called when the DMA request has been
       
   423 completed by the DMA framework. The data member <codeph>iTransferID</codeph> is
       
   424 a value supplied by the LDD which it uses to identify the transfer fragment.
       
   425 The PDD must save this value and pass it back to the LDD when the transfer
       
   426 is completed. Similarly, the member <codeph>iTransferSize</codeph> is used
       
   427 to hold the length of the transfer fragment in bytes. If the transfer is successful
       
   428 then this value is also passed back to the LDD to allow it to maintain its
       
   429 count of bytes recorded. </p> <p>The record PDD class owns an array of DMA
       
   430 request objects: </p> <codeblock id="GUID-8314BE9B-2D19-585F-B44E-17C8529CEFEF" xml:space="preserve">/** The DMA request structures used for transfers. */             
       
   431 DTemplateSoundScRxDmaRequest* iDmaRequest[KTemplateMaxRxDmaRequests];</codeblock> <p>It
       
   432 also owns the data member <codeph>iFlag</codeph>, which always holds the number
       
   433 for the next DMA request that should be used for transfer. Before starting
       
   434 the DMA transfer, setup the appropriate DMA request object with the transfer
       
   435 ID and the transfer length. </p> <codeblock id="GUID-2F4CB025-C2E2-52DD-A679-CF1DCC3677FA" xml:space="preserve">/** A flag selecting the next DMA request for transfer. */
       
   436 TInt iFlag;</codeblock> <p>Next the function <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita#GUID-780F4D53-5546-3B69-B328-0226C70EBDE2/GUID-B14B0478-80D6-3F5E-88B6-1676411D9CF2"><apiname>DDmaRequest::Fragment()</apiname></xref> is
       
   437 called to specify the details of the transfer to the DMA framework and to
       
   438 allow it to analyse this. Here the appropriate platform specific 32-bit DMA
       
   439 source identifier, <codeph>src</codeph>, needs to be supplied. The template
       
   440 driver shown previously specifies the destination memory address as a linear
       
   441 address but the physical address may be used instead. Both forms of this address
       
   442 are passed as arguments to the <xref href="GUID-34E7FF1F-091A-3C45-B83A-AEB64E2AD286.dita"><apiname>TransferData()</apiname></xref> function. </p> <p>If
       
   443 fragmentation is successful then the request object is queued on the DMA channel <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita#GUID-780F4D53-5546-3B69-B328-0226C70EBDE2/GUID-0A83F782-DB62-39ED-8D32-DBD5949C8D3F"><apiname>DDmaRequest::Queue()</apiname></xref> and
       
   444 the value of <codeph>iFlag</codeph> is updated ready for the next transfer.
       
   445 The PDD class also keeps a count of the number of transfer fragments outstanding
       
   446 by incrementing the variable <codeph>iPendingRecord</codeph>: </p> <codeblock id="GUID-5C738134-0683-5FAB-8733-29D9A336402F" xml:space="preserve">/** The number of outstanding DMA record requests on the DMA channel. */   
       
   447 TInt iPendingRecord;</codeblock> <p>The final part of this function requires
       
   448 platform specific code to start the audio hardware device transferring data.
       
   449 This needs to be executed for each fragment transferred or just for the first
       
   450 fragment queued following the <xref href="GUID-FE6DE994-719C-3900-B4A0-009914697380.dita"><apiname>StartTransfer()</apiname></xref> function. </p> <p>Once
       
   451 the transfer is complete, either successfully or with an error, the DMA framework
       
   452 executes the static DMA callback function, <xref href="GUID-6B0DB695-9033-3F85-AC3A-1867E99BE2BD.dita#GUID-6B0DB695-9033-3F85-AC3A-1867E99BE2BD/GUID-E12BA027-3D58-30A8-A9F7-B7B7DC55D0D5"><apiname>DTemplateSoundScRxDmaRequest::DmaService()</apiname></xref>,
       
   453 as follows: </p> <codeblock id="GUID-2ED07474-F489-5545-9FB6-BC229C00D4F3" xml:space="preserve">/**
       
   454 DMA rx service routine. Called in the sound thread's DFC context by the s/w DMA controller.
       
   455 @param aResult Status of DMA transfer.
       
   456 @param aArg Argument passed to DMA controller.
       
   457 */ 
       
   458 void DTemplateSoundScRxDmaRequest::DmaService(TResult aResult, TAny* aArg)
       
   459     {
       
   460     DTemplateSoundScRxDmaRequest&amp; req=*(DTemplateSoundScRxDmaRequest*)aArg;
       
   461    
       
   462     TInt res=KErrNone;
       
   463     TInt bytesTransferred=req.iTransferSize;
       
   464     if (aResult!=DDmaRequest::EOk)
       
   465         {
       
   466         res=KErrCorrupt;
       
   467         bytesTransferred=0;
       
   468         }
       
   469       
       
   470     // Inform the LDD of the result of the transfer.
       
   471     req.iPdd-&gt;RecordCallback(req.iTransferID,res,bytesTransferred);   
       
   472     return;
       
   473     }</codeblock> <p>This function receives two arguments: </p> <ul>
       
   474 <li id="GUID-7D4D15BD-3BA0-5899-B67E-C7F24F548D22"><p>the result of the transfer
       
   475 from the DMA framework </p> </li>
       
   476 <li id="GUID-FE18B3C9-A3B3-5599-8CC6-66977D0FA56A"><p>an argument supplied
       
   477 to the DMA framework when the request object was created </p> </li>
       
   478 </ul> <p>In this specific case, the argument type is a pointer to the DMA
       
   479 request object, and allows the retrieval of the transfer ID and the transfer
       
   480 size. In the template driver version an unsuccessful transfer returns an error
       
   481 value of <xref href="GUID-253F06EA-F14E-3A8E-BA4C-8E787B5F0670.dita"><apiname>KErrCorrupt</apiname></xref> with a transfer byte count of zero. </p> <p>From
       
   482 the callback function we call the record PDD function to decrement the count
       
   483 of transfer fragments outstanding and to inform the LDD of the completion
       
   484 of transfer. </p> <codeblock id="GUID-69C81D24-D725-51B2-8099-1D089A70AE00" xml:space="preserve">void DTemplateSoundScRxPdd::RecordCallback(TUint aTransferID, TInt aTransferResult,TInt aBytesTransferred)
       
   485     {
       
   486     iPendingRecord--;
       
   487     Ldd()-&gt;RecordCallback(aTransferID,aTransferResult,aBytesTransferred);
       
   488     } 
       
   489 </codeblock> </section>
       
   490 <section id="GUID-E9B63AC5-4AED-53E3-B7CA-21AACE04FC37"><title>StopTransfer()</title> <p>Implement
       
   491 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-7C629A7C-0C64-32AB-8159-A4075DEEF544"><apiname>DSoundScPdd::StopTransfer</apiname></xref> function for both the play
       
   492 and record driver channels. This has the following signature: </p> <codeblock id="GUID-E56EFFEC-59CA-595F-BFA8-72299999DD05" xml:space="preserve">void DSoundScPdd::StopTransfer()</codeblock> <p>The
       
   493 PDD must reverse any operation performed on the audio hardware device done
       
   494 as part of <xref href="GUID-FE6DE994-719C-3900-B4A0-009914697380.dita"><apiname>StartTransfer()</apiname></xref> or <xref href="GUID-34E7FF1F-091A-3C45-B83A-AEB64E2AD286.dita"><apiname>TransferData()</apiname></xref>.
       
   495 This includes stopping the audio hardware device from transferring data and
       
   496 stopping the DMA channel. </p> <p>The template version for the record driver
       
   497 channel contains the following code: </p> <codeblock id="GUID-D8A0C5F9-3E9D-54F5-8906-465801CC3A3E" xml:space="preserve">void DTemplateSoundScRxPdd::StopTransfer()
       
   498     {
       
   499     // Stop the DMA channel.
       
   500     iDmaChannel-&gt;CancelAll();
       
   501     iFlag=0;
       
   502     iPendingRecord=0;
       
   503     
       
   504     // TO DO: (mandatory)
       
   505     // Stop the audio device transferring data.
       
   506     }</codeblock> <p> <note> The version used by the playback function is
       
   507 very similar. </note></p> </section>
       
   508 <section id="GUID-2F694050-660B-5941-B9AA-FB21C1D33400"><title>PauseTransfer()</title> <p>Implement
       
   509 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-0608766F-2645-3E28-B804-BD4B953DB5FF"><apiname>DSoundScPdd::PauseTransfer()</apiname></xref> function for both the
       
   510 playback and record driver channels. This has the following signature: </p> <codeblock id="GUID-51C0B918-4883-574A-B1AF-476C61A85120" xml:space="preserve">TInt DSoundScPdd::PauseTransfer()</codeblock> <p>When
       
   511 pausing playback, there is normally some way to temporarily stop the codec
       
   512 and pause the DMA channel so that it can be resumed later starting from the
       
   513 next play sample. </p> <p>Pausing record requires a different implementation.
       
   514 All active transfers must be aborted. When this has been achieved, the PDD
       
   515 must report back to the LDD how much data has been received for the fragment
       
   516 that was actively being transferred when the abort took place by calling <xref href="GUID-5807543D-A30F-3EB9-8F28-91A623B0D484.dita#GUID-5807543D-A30F-3EB9-8F28-91A623B0D484/GUID-9112E399-DC3C-334F-BE16-B5F42216F903"><apiname>DSoundScLdd::RecordCallBack()</apiname></xref>.
       
   517 If it is not possible to determine the byte count for the last fragment from
       
   518 the DMA controller, then you must find some other way to discover its value.
       
   519 One solution is to re-start a timer at the start of each record fragment,
       
   520 and use this to calculate how much data will have been written into the record
       
   521 buffer at the point the transfer is aborted. </p><p><note> In this case the
       
   522 returned transfer ID is not important.</note> </p> <p>The supplied template
       
   523 implementation is as follows: </p> <codeblock id="GUID-5B5B290E-C751-5599-AA67-0AC59E697898" xml:space="preserve">TInt DTemplateSoundScRxPdd::PauseTransfer()
       
   524     {    
       
   525     // Stop the DMA channel.
       
   526     iDmaChannel-&gt;CancelAll();
       
   527    
       
   528     if (iPendingRecord)
       
   529         {
       
   530         // TO DO: (mandatory)
       
   531         // Determine how much data was successfully transferred to the
       
   532         // record buffer before transfer was aborted.
       
   533         TInt byteCount=0; // ???
       
   534         Ldd()-&gt;RecordCallback(0,KErrNone,byteCount);
       
   535         iPendingRecord=0;
       
   536         }
       
   537     iFlag=0;
       
   538     
       
   539     // TO DO: (mandatory)
       
   540     // Halt recording on the audio device.
       
   541     TInt r=KErrNone;
       
   542     
       
   543     return(r); 
       
   544     }
       
   545 </codeblock> <p> <note> There is no need for the PDD to perform any state
       
   546 checking as this is already performed by the LDD. For example, checking that
       
   547 the device is not already paused or transferring data. </note></p> </section>
       
   548 <section id="GUID-00368C95-2AE6-5EBA-8C09-787D0E7C10BC"><title>ResumeTransfer()</title> <p>Implement
       
   549 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-788AEAF9-E33A-3BD2-8B60-9A066DBA2496"><apiname>DSoundScPdd::ResumeTransfer</apiname></xref> function for both the playback
       
   550 and record driver channels. This has the following signature: </p> <codeblock id="GUID-81A86CB7-E089-5B3D-A28F-A371AFDF5471" xml:space="preserve">TInt DSoundScPdd::ResumeTransfer()</codeblock> <p>The
       
   551 template version for the record driver channel contains the following code: </p> <codeblock id="GUID-D72D3F34-197F-500F-8483-E307418127F6" xml:space="preserve">TInt DTemplateSoundScTxPdd::ResumeTransfer()
       
   552     {
       
   553     __KTRACE_SND(Kern::Printf("&gt;DTemplateSoundScTxPdd::ResumeTransfer"));
       
   554     
       
   555     // TO DO: (mandatory)
       
   556     // Resume playback on the audio device.
       
   557     TInt r=KErrNone;
       
   558             
       
   559     return(r);
       
   560     }</codeblock> <p>To resume playback, it is normally necessary to re-start
       
   561 the codec and resume the DMA channel in order to restart playback from the
       
   562 next play sample. </p> <p>To resume record, all active transfers should have
       
   563 been aborted when the device was paused with the function <xref href="GUID-1126E802-39C1-3BAD-85BA-A6DDED981B8A.dita"><apiname>PauseTransfer()</apiname></xref>.
       
   564 However, the LDD issues a new <xref href="GUID-34E7FF1F-091A-3C45-B83A-AEB64E2AD286.dita"><apiname>TransferData()</apiname></xref> request subsequent
       
   565 to this function to resume record data transfer so the only action required
       
   566 here is to recreate the same audio hardware setup that was achieved in response
       
   567 to the <xref href="GUID-FE6DE994-719C-3900-B4A0-009914697380.dita"><apiname>StartTransfer()</apiname></xref> function. </p> <p>There is no need
       
   568 for the PDD to perform any state checking as this is already performed by
       
   569 the LDD. For example, checking that the device is not already paused. </p> </section>
       
   570 <section id="GUID-3155494B-AFFD-5E07-8E2F-D6EC81E4E69B"><title>PowerDown()</title> <p>Implement
       
   571 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-53CDB4F4-470C-3A40-B948-C14B0FCA0E24"><apiname>DSoundScPdd::PowerDown()</apiname></xref> function for both the playback
       
   572 and record driver channels. This has the following signature: </p> <codeblock id="GUID-69B46DDC-DA62-55E2-9E7C-A4E0B1550E03" xml:space="preserve">void DSoundScPdd::PowerDown()</codeblock> <p>The
       
   573 PDD must reverse any operation performed on the audio hardware as part of <xref href="GUID-B70A3916-5644-330F-872B-FADB8E3D80B5.dita"><apiname>PowerUp()</apiname></xref>. </p> </section>
       
   574 <section id="GUID-4B71AE98-3692-54B3-9CD8-525991DBAEAA"><title>CustomConfig()</title> <p>Implement
       
   575 the <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-B0F89BCD-69AF-3D40-A601-EB22C6FA0435"><apiname>DSoundScPdd::CustomConfig()</apiname></xref> function for both the playback
       
   576 and record driver channels. This has the following signature: </p> <codeblock id="GUID-C24D93F2-9A7E-5E43-8750-6BE8978B9C01" xml:space="preserve">TInt DSoundScPdd::CustomConfig(TInt aFunction,TAny* aParam)</codeblock> <p> <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-78AA2782-80D0-3815-8F71-AA218756BAE6"><apiname>RSoundSc::CustomConfig()</apiname></xref> is called by the LDD in response to a custom configuration request by the
       
   577 client. Custom configurations allow clients to issue requests to setup platform
       
   578 specific audio configuration settings. Any such requests from the client with
       
   579 a function identifier equal to or above 0x10000000 are passed straight through
       
   580 to the PDD for function identification and implementation. These are handled
       
   581 in the context of the sound driver DFC thread. </p> <p>If custom configuration
       
   582 is not supported, then the PDD should simply return <codeph>KErrNotSupported</codeph>. </p> </section>
       
   583 </conbody></concept>