1 /* |
1 /* |
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
2 * This component and the accompanying materials are made available |
5 * under the terms of the License "Eclipse Public License v1.0" |
3 * under the terms of the License "Eclipse Public License v1.0" |
6 * which accompanies this distribution, and is available |
4 * which accompanies this distribution, and is available |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
5 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
8 * |
6 * |
9 * Initial Contributors: |
7 * Initial Contributors: |
10 * Nokia Corporation - initial contribution. |
8 * Nokia Corporation - initial contribution. |
11 * |
9 * |
12 * Contributors: |
10 * Contributors: |
|
11 * Accenture Ltd |
13 * |
12 * |
14 * Description: |
13 * Description: This file is a part of sound driver for Syborg adaptation. |
15 * |
14 * |
16 */ |
15 */ |
17 |
16 |
18 #include "shared_sound.h" |
17 #include "shared_sound.h" |
19 #include "variant_sound.h" |
18 #include "variant_sound.h" |
20 |
19 #include "../specific/syborg.h" |
21 void TimerCallback(TAny* aData) |
20 |
22 { |
21 #include "virtio.h" |
23 DDriverSyborgSoundScPdd * soundscpdd = (DDriverSyborgSoundScPdd*) aData; |
22 #include "virtio_audio.h" |
|
23 #include "virtio_iohandler.h" |
|
24 |
|
25 using namespace VirtIo; |
|
26 |
|
27 static TInt GetSampleRate( TSoundRate aRate) |
|
28 { |
|
29 switch(aRate) |
|
30 { |
|
31 case ESoundRate7350Hz: return 7350; |
|
32 case ESoundRate8000Hz: return 8000; |
|
33 case ESoundRate8820Hz: return 8820; |
|
34 case ESoundRate9600Hz: return 9600; |
|
35 case ESoundRate11025Hz: return 11025; |
|
36 case ESoundRate12000Hz: return 12000; |
|
37 case ESoundRate14700Hz: return 14700; |
|
38 case ESoundRate16000Hz: return 16000; |
|
39 case ESoundRate22050Hz: return 22050; |
|
40 case ESoundRate24000Hz: return 24000; |
|
41 case ESoundRate29400Hz: return 29400; |
|
42 case ESoundRate32000Hz: return 32000; |
|
43 case ESoundRate44100Hz: return 44100; |
|
44 case ESoundRate48000Hz: return 48000; |
|
45 } |
|
46 return KErrNotFound; |
|
47 } |
|
48 |
|
49 static TInt GetSoundEncoding( TSoundEncoding aV ) |
|
50 { |
|
51 switch (aV) |
|
52 { |
|
53 case ESoundEncoding8BitPCM: return Audio::EFormatS8; |
|
54 case ESoundEncoding16BitPCM: return Audio::EFormatS16; |
|
55 case ESoundEncoding24BitPCM: break; // not supported |
|
56 } |
|
57 return -KErrNotFound; |
|
58 } |
|
59 static TInt GetChannels( TInt aV ) |
|
60 { |
|
61 switch (aV) |
|
62 { |
|
63 case KSoundMonoChannel: return 1; |
|
64 case KSoundStereoChannel: return 2; |
|
65 } |
|
66 return KErrNotFound; |
|
67 } |
|
68 |
|
69 DDriverSyborgSoundScPdd::DDriverSyborgSoundScPdd(DDriverSyborgSoundScPddFactory* aPhysicalDevice, |
|
70 TInt aUnitType, VirtIo::DIoHandler* aIoHandler, TUint aDataQueueId ) |
|
71 : iPhysicalDevice(aPhysicalDevice), iUnitType(aUnitType), iIoHandler( aIoHandler ), iDataQueueId( aDataQueueId ) |
|
72 { |
|
73 } |
|
74 |
|
75 DDriverSyborgSoundScPdd::~DDriverSyborgSoundScPdd() |
|
76 { |
|
77 SYBORG_SOUND_DEBUG("~DDriverSyborgSoundScPdd()"); |
|
78 iIoHandler->UnregisterClient( this ); |
|
79 delete iAudioControl; |
|
80 SYBORG_SOUND_DEBUG("~DDriverSyborgSoundScPdd() - done"); |
|
81 } |
|
82 |
|
83 TInt DDriverSyborgSoundScPdd::DoCreate() |
|
84 { |
|
85 SetCaps(); |
|
86 |
|
87 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::DoCreate TxPdd"); |
|
88 |
|
89 SYBORG_SOUND_DEBUG("Registering with IOHandler %x", iIoHandler ); |
|
90 iIoHandler->RegisterClient( this ); |
|
91 SYBORG_SOUND_DEBUG("Registered with IoHandler... Done %x", iIoHandler); |
|
92 |
|
93 iAudioControl = new Audio::DControl( *iIoHandler, iDataQueueId ); |
|
94 iAudioControl->Construct(); |
24 |
95 |
25 soundscpdd->Callback(soundscpdd->iTransferArray[0].iTransferID, KErrNone, soundscpdd->iTransferArray[0].iNumBytes); |
|
26 |
|
27 } |
|
28 |
|
29 |
|
30 DDriverSyborgSoundScPdd::DDriverSyborgSoundScPdd() : iTimer(TimerCallback,this) |
|
31 { |
|
32 |
|
33 } |
|
34 |
|
35 DDriverSyborgSoundScPdd::~DDriverSyborgSoundScPdd() |
|
36 { |
|
37 iTimer.Cancel(); |
|
38 } |
|
39 |
|
40 |
|
41 TInt DDriverSyborgSoundScPdd::DoCreate() |
|
42 { |
|
43 |
|
44 SetCaps(); |
|
45 |
|
46 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::DoCreate TxPdd"); |
|
47 |
|
48 return KErrNone; |
96 return KErrNone; |
49 } |
97 } |
50 |
98 |
51 void DDriverSyborgSoundScPdd::GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo) |
99 void DDriverSyborgSoundScPdd::GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo) |
52 { |
100 { |
71 aCapsBuf = ptr.Left(Min(ptr.Length(), aCapsBuf.MaxLength())); |
118 aCapsBuf = ptr.Left(Min(ptr.Length(), aCapsBuf.MaxLength())); |
72 } |
119 } |
73 |
120 |
74 TInt DDriverSyborgSoundScPdd::SetConfig(const TDesC8& aConfigBuf) |
121 TInt DDriverSyborgSoundScPdd::SetConfig(const TDesC8& aConfigBuf) |
75 { |
122 { |
76 |
|
77 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetConfig TxPdd"); |
123 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetConfig TxPdd"); |
78 |
124 |
79 // Read the new configuration from the LDD |
125 // Read the new configuration from the LDD |
80 TCurrentSoundFormatV02 config; |
126 TCurrentSoundFormatV02 config; |
81 TPtr8 ptr((TUint8*) &config, sizeof(config)); |
127 TPtr8 ptr((TUint8*) &config, sizeof(config)); |
82 Kern::InfoCopy(ptr, aConfigBuf); |
128 Kern::InfoCopy(ptr, aConfigBuf); |
83 |
129 |
|
130 TInt channels = GetChannels(config.iChannels); |
|
131 Audio::FormatId encoding = static_cast<Audio::FormatId>( GetSoundEncoding(config.iEncoding) ); |
|
132 TInt freq = GetSampleRate(config.iRate); |
|
133 Audio::StreamDirection direction = static_cast<Audio::StreamDirection>( |
|
134 (iUnitType == KSoundScRxUnit0)?Audio::EDirectionRecord |
|
135 :(iUnitType == KSoundScTxUnit0)?Audio::EDirectionPlayback:-1 ); |
|
136 |
|
137 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetConfig c %x, e %x, f %x, d %x", |
|
138 channels, encoding, freq, direction ); |
|
139 |
|
140 if ( (channels < 0 ) |
|
141 || ( encoding < 0 ) |
|
142 || ( freq < 0 ) |
|
143 || ( direction < 0 ) |
|
144 ) |
|
145 { |
|
146 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetConfig failed"); |
|
147 return KErrArgument; |
|
148 } |
|
149 |
|
150 TInt st = iAudioControl->Setup( direction, channels, encoding, freq ); |
|
151 if (st !=KErrNone) |
|
152 { |
|
153 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetConfig failed %d", st); |
|
154 return st; |
|
155 } |
|
156 |
84 iConfig = config; |
157 iConfig = config; |
85 |
158 |
86 return KErrNone; |
159 return KErrNone; |
87 } |
160 } |
88 |
161 |
89 |
162 |
90 TInt DDriverSyborgSoundScPdd::SetVolume(TInt aVolume) |
163 TInt DDriverSyborgSoundScPdd::SetVolume(TInt aVolume) |
91 { |
164 { |
92 |
|
93 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Setvolume TxPdd"); |
165 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Setvolume TxPdd"); |
94 |
166 |
95 return KErrNone; |
167 return KErrNone; |
96 } |
168 } |
97 |
169 |
98 |
170 |
99 TInt DDriverSyborgSoundScPdd::StartTransfer() |
171 TInt DDriverSyborgSoundScPdd::StartTransfer() |
100 { |
172 { |
101 |
173 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::starttransfer TxPdd S"); |
102 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::starttransfer TxPdd"); |
174 iAudioControl->SendCommand( Audio::DControl::ERun ); |
103 |
175 return KErrNone; |
104 //Prepare for transfer |
176 } |
105 return KErrNone; |
177 |
106 |
178 |
107 } |
|
108 |
|
109 TInt DDriverSyborgSoundScPdd::CalculateBufferTime(TInt aNumBytes) |
179 TInt DDriverSyborgSoundScPdd::CalculateBufferTime(TInt aNumBytes) |
110 { |
180 { |
111 |
181 TUint samplerate=GetSampleRate( iConfig.iRate ); |
112 TUint samplerate=0; |
|
113 |
|
114 // Let the compiler perform an integer division of rates |
|
115 switch(iConfig.iRate) |
|
116 { |
|
117 case ESoundRate7350Hz: samplerate = 7350; break; |
|
118 case ESoundRate8000Hz: samplerate = 8000; break; |
|
119 case ESoundRate8820Hz: samplerate = 8820; break; |
|
120 case ESoundRate9600Hz: samplerate = 9600; break; |
|
121 case ESoundRate11025Hz: samplerate = 11025; break; |
|
122 case ESoundRate12000Hz: samplerate = 12000; break; |
|
123 case ESoundRate14700Hz: samplerate = 14700; break; |
|
124 case ESoundRate16000Hz: samplerate = 16000; break; |
|
125 case ESoundRate22050Hz: samplerate = 22050; break; |
|
126 case ESoundRate24000Hz: samplerate = 24000; break; |
|
127 case ESoundRate29400Hz: samplerate = 29400; break; |
|
128 case ESoundRate32000Hz: samplerate = 32000; break; |
|
129 case ESoundRate44100Hz: samplerate = 44100; break; |
|
130 case ESoundRate48000Hz: samplerate = 48000; break; |
|
131 } |
|
132 |
|
133 |
182 |
134 // integer division by number of channels |
183 // integer division by number of channels |
135 aNumBytes /= iConfig.iChannels; |
184 aNumBytes /= iConfig.iChannels; |
136 |
185 |
137 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::iChannels =%d", iConfig.iChannels); |
|
138 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::iEncoding =%d", iConfig.iEncoding); |
|
139 |
|
140 // integer division by bytes per sample |
186 // integer division by bytes per sample |
141 switch(iConfig.iEncoding) |
187 switch(iConfig.iEncoding) |
142 { |
188 { |
143 case ESoundEncoding8BitPCM: break; |
189 case ESoundEncoding8BitPCM: break; |
144 case ESoundEncoding16BitPCM: aNumBytes /= 2; break; |
190 case ESoundEncoding16BitPCM: aNumBytes /= 2; break; |
145 case ESoundEncoding24BitPCM: aNumBytes /= 3; break; |
191 case ESoundEncoding24BitPCM: aNumBytes /= 3; break; |
146 } |
192 } |
147 |
193 |
148 return (aNumBytes * 1000) / samplerate; //return time in milliseconds |
194 return (aNumBytes * 1000) / samplerate; //return time in milliseconds |
149 |
195 } |
150 |
196 |
151 } |
197 TInt DDriverSyborgSoundScPdd::TransferData(TUint aTransferID, TLinAddr aLinAddr, TPhysAddr aPhysAddr, TInt aNumBytes) |
152 |
198 { |
153 TInt DDriverSyborgSoundScPdd::TransferData(TUint aTransferID, TLinAddr aLinAddr, TPhysAddr /*aPhysAddr*/, TInt aNumBytes) |
199 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::TransferData unit %x aTId=%x, linAddr=%x,phAddr=%x,len=%x", |
154 { |
200 iUnitType, aTransferID, aLinAddr, aPhysAddr, aNumBytes); |
155 |
201 |
156 //function wil get called multiple times while transfer is in progress therefore keep fifo queue of requests |
202 iAudioControl->SendDataBuffer( |
157 TTransferArrayInfo transfer; |
203 reinterpret_cast<TAny*>( aLinAddr ), aNumBytes, reinterpret_cast<Token>( aTransferID ) ); |
|
204 |
|
205 return KErrNone; |
|
206 } |
|
207 |
|
208 void DDriverSyborgSoundScPdd::StopTransfer() |
|
209 { |
|
210 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::stoptransfer TxPdd"); |
|
211 |
|
212 iAudioControl->SendCommand( Audio::DControl::EStop ); |
|
213 } |
|
214 |
|
215 |
|
216 TInt DDriverSyborgSoundScPdd::PauseTransfer() |
|
217 { |
|
218 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::pausetransfer TxPdd"); |
|
219 iAudioControl->SendCommand( Audio::DControl::EPause ); |
|
220 return KErrNone; |
|
221 } |
|
222 |
|
223 |
|
224 TInt DDriverSyborgSoundScPdd::ResumeTransfer() |
|
225 { |
|
226 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::resumetransfer TxPdd"); |
|
227 iAudioControl->SendCommand( Audio::DControl::EResume ); |
|
228 return KErrNone; |
|
229 } |
|
230 |
|
231 TInt DDriverSyborgSoundScPdd::PowerUp() |
|
232 { |
|
233 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::PowerUp TxPdd"); |
|
234 return KErrNone; |
|
235 } |
|
236 |
|
237 void DDriverSyborgSoundScPdd::PowerDown() |
|
238 { |
|
239 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Powerdown TxPdd"); |
|
240 } |
|
241 |
|
242 TInt DDriverSyborgSoundScPdd::CustomConfig(TInt /*aFunction*/,TAny* /*aParam*/) |
|
243 { |
|
244 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::CustomConfig TxPdd"); |
|
245 return KErrNotSupported; |
|
246 } |
|
247 |
|
248 TBool DDriverSyborgSoundScPdd::VirtIoCallback( MIoHandler& aVirtIoHandler, MQueue& aQueue, |
|
249 Token aToken, TUint aBytesTransferred ) |
|
250 { |
|
251 if ( &aQueue != &iAudioControl->DataQueue() ) |
|
252 { return ETrue; } |
|
253 |
|
254 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::VirtIoCallback t%x, s%x", aToken, aBytesTransferred); |
|
255 |
|
256 if ( iCaps.iDirection == ESoundDirPlayback ) |
|
257 { |
|
258 Ldd()->PlayCallback( (TUint) aToken, KErrNone, aBytesTransferred ); |
|
259 } |
|
260 else |
|
261 { |
|
262 Ldd()->RecordCallback( (TUint) aToken, KErrNone, aBytesTransferred ); |
|
263 } |
158 |
264 |
159 transfer.iTransferID = aTransferID; |
265 return EFalse; // cannot process any more buffers in this go due to a bug in LDD? |
160 transfer.iLinAddr = aLinAddr; |
266 } |
161 transfer.iNumBytes = aNumBytes; |
|
162 |
|
163 //calculate the amount of time required to play/record buffer |
|
164 TInt buffer_play_time = CalculateBufferTime(aNumBytes); |
|
165 TInt timerticks = NKern::TimerTicks(buffer_play_time); |
|
166 transfer.iPlayTime = timerticks; |
|
167 |
|
168 iTransferArray.Append(transfer); |
|
169 |
|
170 //Timer will callback when correct time has elapsed, will return KErrInUse if transfer |
|
171 //already active, this is ok becuase will be started again in callback |
|
172 TInt err = iTimer.OneShot(timerticks, ETrue); |
|
173 |
|
174 |
|
175 return KErrNone; |
|
176 } |
|
177 |
|
178 void DDriverSyborgSoundScPdd::StopTransfer() |
|
179 { |
|
180 // Stop transfer |
|
181 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::stoptransfer TxPdd"); |
|
182 |
|
183 //If timer is currently active then cancel it and call back buffer |
|
184 if(iTimer.Cancel()) |
|
185 { |
|
186 Callback(iTransferArray[0].iTransferID, KErrNone, iTransferArray[0].iNumBytes); |
|
187 } |
|
188 |
|
189 |
|
190 } |
|
191 |
|
192 |
|
193 TInt DDriverSyborgSoundScPdd::PauseTransfer() |
|
194 { |
|
195 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::pausetransfer TxPdd"); |
|
196 //Pause Transfer |
|
197 |
|
198 return KErrNone; |
|
199 } |
|
200 |
|
201 |
|
202 TInt DDriverSyborgSoundScPdd::ResumeTransfer() |
|
203 { |
|
204 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::resumetransfer TxPdd"); |
|
205 //Resume Transfer |
|
206 |
|
207 return KErrNone; |
|
208 } |
|
209 |
|
210 TInt DDriverSyborgSoundScPdd::PowerUp() |
|
211 { |
|
212 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::PowerUp TxPdd"); |
|
213 return KErrNone; |
|
214 } |
|
215 |
|
216 void DDriverSyborgSoundScPdd::PowerDown() |
|
217 { |
|
218 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Powerdown TxPdd"); |
|
219 } |
|
220 |
|
221 TInt DDriverSyborgSoundScPdd::CustomConfig(TInt /*aFunction*/,TAny* /*aParam*/) |
|
222 { |
|
223 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::customconfig TxPdd"); |
|
224 return KErrNotSupported; |
|
225 } |
|
226 |
|
227 |
|
228 void DDriverSyborgSoundScPdd::Callback(TUint aTransferID, TInt aTransferResult, TInt aBytesTransferred) |
|
229 { |
|
230 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::playcallback TxPdd"); |
|
231 //Callback when Transfer completes or is stopped |
|
232 |
|
233 iTransferArray.Remove(0); |
|
234 |
|
235 if(iUnitType == KSoundScTxUnit0) |
|
236 { |
|
237 Ldd()->PlayCallback(aTransferID, aTransferResult, aBytesTransferred); |
|
238 } |
|
239 else if(iUnitType == KSoundScRxUnit0) |
|
240 { |
|
241 Ldd()->RecordCallback(aTransferID, aTransferResult, aBytesTransferred); |
|
242 } |
|
243 |
|
244 if( iTransferArray.Count()>0) |
|
245 { |
|
246 iTimer.OneShot(iTransferArray[0].iPlayTime, ETrue); |
|
247 } |
|
248 |
|
249 } |
|
250 |
|
251 TDfcQue*DDriverSyborgSoundScPdd::DfcQ(TInt /* aUnit*/ ) |
|
252 { |
|
253 return this->DfcQ(); |
|
254 } |
|
255 |
267 |
256 TDfcQue*DDriverSyborgSoundScPdd::DfcQ() |
268 TDfcQue*DDriverSyborgSoundScPdd::DfcQ() |
257 { |
269 { |
258 return iPhysicalDevice->iDfcQ; |
270 return iPhysicalDevice->iDfcQ; |
259 } |
271 } |
|
272 |
|
273 TDfcQue*DDriverSyborgSoundScPdd::DfcQ( TInt /* aUinit */ ) |
|
274 { |
|
275 return iPhysicalDevice->iDfcQ; |
|
276 } |
|
277 |
260 |
278 |
261 TInt DDriverSyborgSoundScPdd::MaxTransferLen() const |
279 TInt DDriverSyborgSoundScPdd::MaxTransferLen() const |
262 { |
280 { |
263 |
281 return KMaxTransferLength; |
264 SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::MaxTransferLen TxPdd"); |
|
265 |
|
266 TInt maxlength = 200*1024; |
|
267 return maxlength; |
|
268 } |
282 } |
269 |
283 |
270 |
284 |
271 void DDriverSyborgSoundScPdd::SetCaps() |
285 void DDriverSyborgSoundScPdd::SetCaps() |
272 { |
286 { |