1 /* |
|
2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Handles SendDtmf command |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "MSatApi.h" |
|
20 #include "MSatUtils.h" |
|
21 #include "MSatSystemState.h" |
|
22 #include "MSatUiSession.h" |
|
23 #include "SatSOpcodes.h" |
|
24 #include "MSatSUiClientHandler.h" |
|
25 #include "CSendDtmfHandler.h" |
|
26 #include "csatdtmfsender.h" |
|
27 #include "msatmultimodeapi.h" |
|
28 #include "SatLog.h" |
|
29 |
|
30 const TUint KBcdZero = 0x00; |
|
31 const TUint KBcdOne = 0x01; |
|
32 const TUint KBcdTwo = 0x02; |
|
33 const TUint KBcdThree = 0x03; |
|
34 const TUint KBcdFour = 0x04; |
|
35 const TUint KBcdFive = 0x05; |
|
36 const TUint KBcdSix = 0x06; |
|
37 const TUint KBcdSeven = 0x07; |
|
38 const TUint KBcdEight = 0x08; |
|
39 const TUint KBcdNine = 0x09; |
|
40 const TUint KBcdStar = 0x0A; |
|
41 const TUint KBcdHash = 0x0B; |
|
42 const TUint KBcdPause = 0x0C; |
|
43 const TUint KBcdWild = 0x0D; |
|
44 const TUint KBcdExpansion = 0x0E; |
|
45 const TUint KBcdEnd = 0x0F; |
|
46 |
|
47 const TUint KUcs2Zero = 0x30; // '0' |
|
48 const TUint KUcs2Star = 0x2A; // '*' |
|
49 const TUint KUcs2Hash = 0x23; // '#' |
|
50 const TUint KUcs2Pause = 0x70; // 'p' |
|
51 |
|
52 const TUint KHighNibble = 0xF0; |
|
53 const TUint KLowNibble = 0x0F; |
|
54 const TUint KBitsInNibble = 4; |
|
55 |
|
56 // ======== MEMBER FUNCTIONS ======== |
|
57 |
|
58 // ----------------------------------------------------------------------------- |
|
59 // Two-phased constructor. |
|
60 // ----------------------------------------------------------------------------- |
|
61 // |
|
62 CSendDtmfHandler* CSendDtmfHandler::NewL( MSatUtils* aUtils ) |
|
63 { |
|
64 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::NewL calling" ) |
|
65 |
|
66 CSendDtmfHandler* self = new( ELeave ) CSendDtmfHandler; |
|
67 |
|
68 CleanupStack::PushL( self ); |
|
69 self->BaseConstructL( aUtils ); |
|
70 self->ConstructL(); |
|
71 CleanupStack::Pop( self ); |
|
72 |
|
73 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::NewL exiting" ) |
|
74 return self; |
|
75 } |
|
76 |
|
77 |
|
78 // ----------------------------------------------------------------------------- |
|
79 // Destructor. |
|
80 // ----------------------------------------------------------------------------- |
|
81 // |
|
82 CSendDtmfHandler::~CSendDtmfHandler() |
|
83 { |
|
84 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::~CSendDtmfHandler calling" ) |
|
85 |
|
86 Cancel(); |
|
87 |
|
88 if ( iDtmfSender ) |
|
89 { |
|
90 delete iDtmfSender; |
|
91 } |
|
92 |
|
93 if ( iDtmfStringUcs2 ) |
|
94 { |
|
95 delete iDtmfStringUcs2; |
|
96 iDtmfStringUcs2 = NULL; |
|
97 } |
|
98 |
|
99 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::~CSendDtmfHandler exiting" ) |
|
100 } |
|
101 |
|
102 // ----------------------------------------------------------------------------- |
|
103 // Gets the result of DTMF sending. |
|
104 // ----------------------------------------------------------------------------- |
|
105 // |
|
106 void CSendDtmfHandler::SendDtmfComplete( const TInt aErrCode ) |
|
107 { |
|
108 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendDtmfComplete calling" ) |
|
109 |
|
110 iDtmfResult = aErrCode; |
|
111 // Handles result and sends terminal response. |
|
112 HandleResult(); |
|
113 |
|
114 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendDtmfComplete exiting" ) |
|
115 } |
|
116 |
|
117 // ----------------------------------------------------------------------------- |
|
118 // From class MSatCommand. |
|
119 // Response from the client |
|
120 // ----------------------------------------------------------------------------- |
|
121 // |
|
122 void CSendDtmfHandler::ClientResponse() |
|
123 { |
|
124 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ClientResponse calling" ) |
|
125 |
|
126 iClientResponseReceived = ETrue; |
|
127 if( iWait.IsStarted() ) |
|
128 { |
|
129 iWait.AsyncStop(); |
|
130 } |
|
131 |
|
132 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ClientResponse exiting" ) |
|
133 } |
|
134 |
|
135 // ----------------------------------------------------------------------------- |
|
136 // From class CSatCommandHandler. |
|
137 // Waits for indication of user rejection |
|
138 // ----------------------------------------------------------------------------- |
|
139 // |
|
140 void CSendDtmfHandler::Event( TInt aEvent ) |
|
141 { |
|
142 LOG2( SIMPLE, |
|
143 "SENDTMF: CSendDtmfHandler::Event calling, aEvent:%d", aEvent ) |
|
144 |
|
145 switch ( aEvent ) |
|
146 { |
|
147 case MSatUtils::ECommandCancelled: |
|
148 { |
|
149 // Cancel DTMF sending |
|
150 if ( iDtmfSender ) |
|
151 { |
|
152 LOG( SIMPLE, |
|
153 "SENDTMF: CSendDtmfHandler::Event Cancel DTMF sending" ) |
|
154 iDtmfSender->Cancel(); |
|
155 } |
|
156 |
|
157 // Cancel key pressed. Send terminal response. |
|
158 iSendDtmfRsp.iGeneralResult = RSat::KPSessionTerminatedByUser; |
|
159 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
160 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
161 |
|
162 SendTerminalResponse(); |
|
163 break; |
|
164 } |
|
165 |
|
166 case MSatUtils::ECancelledUsingEndKey: |
|
167 { |
|
168 // Cancel DTMF sending |
|
169 if ( iDtmfSender ) |
|
170 { |
|
171 LOG( SIMPLE, |
|
172 "CSendDtmfHandler::Event Cancel DTMF sending by endkey" ) |
|
173 iDtmfSender->Cancel(); |
|
174 } |
|
175 |
|
176 // End key pressed. Send terminal response. |
|
177 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
178 iSendDtmfRsp.iInfoType = RSat::KMeProblem; |
|
179 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
180 iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall ); |
|
181 |
|
182 // Next SimSession end will close the ui session |
|
183 iUtils->NotifyEvent( MSatUtils::ESessionTerminatedByUser ); |
|
184 SendTerminalResponse(); |
|
185 break; |
|
186 } |
|
187 |
|
188 default: |
|
189 { |
|
190 // Move event to base class |
|
191 CSatCommandHandler::Event( aEvent ); |
|
192 } |
|
193 } |
|
194 |
|
195 LOG( SIMPLE, "SENDTMF: CSendDtmfHandler::Event exiting" ) |
|
196 } |
|
197 |
|
198 // ----------------------------------------------------------------------------- |
|
199 // From class CActive. |
|
200 // Cancels the sat request. |
|
201 // ----------------------------------------------------------------------------- |
|
202 // |
|
203 void CSendDtmfHandler::DoCancel() |
|
204 { |
|
205 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::DoCancel calling" ) |
|
206 |
|
207 iUtils->USatAPI().NotifySendDtmfCancel(); |
|
208 |
|
209 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::DoCancel exiting" ) |
|
210 } |
|
211 |
|
212 // ----------------------------------------------------------------------------- |
|
213 // From class CSatCommandHandler. |
|
214 // Requests the command notification. |
|
215 // ----------------------------------------------------------------------------- |
|
216 // |
|
217 void CSendDtmfHandler::IssueUSATRequest( TRequestStatus& aStatus ) |
|
218 { |
|
219 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::IssueUSATRequest calling" ) |
|
220 |
|
221 // Clear the IPC package. |
|
222 new (&iSendDtmfData) RSat::TSendDtmfV1(); |
|
223 |
|
224 if ( iDtmfStringUcs2 ) |
|
225 { |
|
226 LOG( SIMPLE, |
|
227 "CSendDtmfHandler::IssueUSATRequest iDtmfStringUcs2 true" ) |
|
228 delete iDtmfStringUcs2; |
|
229 iDtmfStringUcs2 = NULL; |
|
230 } |
|
231 |
|
232 iUtils->USatAPI().NotifySendDtmf( aStatus, iSendDtmfPckg ); |
|
233 |
|
234 // Unregister from events |
|
235 iUtils->UnregisterEvent( this, MSatUtils::ECommandCancelled ); |
|
236 iUtils->UnregisterEvent( this, MSatUtils::ECancelledUsingEndKey ); |
|
237 |
|
238 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::IssueUSATRequest exiting" ) |
|
239 } |
|
240 |
|
241 // ----------------------------------------------------------------------------- |
|
242 // From class CSatCommandHandler. |
|
243 // SendDtmf command is not allowed if there is not active speech call. |
|
244 // ----------------------------------------------------------------------------- |
|
245 // |
|
246 TBool CSendDtmfHandler::CommandAllowed() |
|
247 { |
|
248 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed calling" ) |
|
249 |
|
250 // By default, this is true |
|
251 TBool commandAllowed( ETrue ); |
|
252 |
|
253 // Allow next terminal response to be sent |
|
254 iTerminalRespSent = EFalse; |
|
255 |
|
256 // This is needed every time |
|
257 iSendDtmfRsp.SetPCmdNumber( iSendDtmfData.PCmdNumber() ); |
|
258 |
|
259 // Call has to be established, otherwise DTMF cannot be sent. |
|
260 #ifdef SAT_USE_DUMMY_TSY |
|
261 TInt firstChar( ' ' ); |
|
262 if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdProvided ) |
|
263 { |
|
264 firstChar = iSendDtmfData.iAlphaId.iAlphaId[0]; |
|
265 } |
|
266 const TBool callIsOngoing( firstChar != 'T' ); |
|
267 #else |
|
268 const TBool callIsOngoing( iUtils->SystemState().IsCallActive() ); |
|
269 #endif |
|
270 |
|
271 const TInt dtmfLength( iSendDtmfData.iDtmfString.Length() ); |
|
272 |
|
273 // DTMF string shall have at least one BCD character. |
|
274 // Otherwise, minimum set of data objects is not complete, |
|
275 // and command has to be rejected with 'Error, required |
|
276 // values are missing'. |
|
277 const TBool dtmfStringHasContent( dtmfLength > 0 ); |
|
278 |
|
279 // DTMF string shall not be longer than is possible |
|
280 // according to TS 11.14, clause 6.6.24. If the string is |
|
281 // longer than this, the DTMF String data object is not valid, |
|
282 // which means that the minimum set of data objects |
|
283 // is not complete, and the command has to be rejected |
|
284 // with 'Error, required values are missing'. |
|
285 const TBool dtmfStringNotTooLong( dtmfLength <= RSat::KDtmfStringMaxSize ); |
|
286 |
|
287 // If icon data without alpha id. |
|
288 if ( ( RSat::EAlphaIdProvided != iSendDtmfData.iAlphaId.iStatus ) && |
|
289 ( ( RSat::ESelfExplanatory == iSendDtmfData.iIconId.iQualifier ) || |
|
290 ( RSat::ENotSelfExplanatory == iSendDtmfData.iIconId.iQualifier ) ) ) |
|
291 { |
|
292 commandAllowed = EFalse; |
|
293 iSendDtmfRsp.iGeneralResult = RSat::KCmdDataNotUnderstood; |
|
294 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
295 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
296 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed data not \ |
|
297 understood" ) |
|
298 } |
|
299 else if ( !( dtmfStringHasContent && callIsOngoing && dtmfStringNotTooLong ) ) |
|
300 { // Handle the error cases. |
|
301 |
|
302 if ( !dtmfStringHasContent || !dtmfStringNotTooLong ) |
|
303 { |
|
304 LOG( SIMPLE, |
|
305 "SENDDTMF: !dtmfStringHasContent || !dtmfStringNotTooLong" ) |
|
306 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
307 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
308 iSendDtmfRsp.iGeneralResult = RSat::KErrorRequiredValuesMissing; |
|
309 } |
|
310 else // No callIsOngoing |
|
311 { |
|
312 LOG( SIMPLE, "SENDDTMF: !callIsOngoing" ) |
|
313 // ME is not in speech call and dtmf string cannot be sent. |
|
314 iSendDtmfRsp.iInfoType = RSat::KMeProblem; |
|
315 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
316 iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall ); |
|
317 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
318 } |
|
319 // Command is not allowed |
|
320 commandAllowed = EFalse; |
|
321 } |
|
322 else |
|
323 { |
|
324 // Convert DTMF string. This is done here, so UI is not launched. |
|
325 // for no reason. |
|
326 |
|
327 // At the ETel interface level, the DTMF string uses a TBuf where each |
|
328 // buffer character represents two DTMF digits coded as BCD characters. |
|
329 const TUint KDtmfStringETelNumberOfBcdPerBufferCharacter = 2; |
|
330 |
|
331 // The DTMF string uses a TBuf where each buffer character represents |
|
332 // one DTMF digit. |
|
333 const TUint KDtmfStringMaxLength = |
|
334 KDtmfStringETelNumberOfBcdPerBufferCharacter * |
|
335 RSat::KDtmfStringMaxSize; |
|
336 |
|
337 TRAPD( noMemory, iDtmfStringUcs2 = |
|
338 HBufC16::NewL( KDtmfStringMaxLength ) ) |
|
339 |
|
340 if ( KErrNone != noMemory ) |
|
341 { |
|
342 LOG( SIMPLE, |
|
343 "SENDDTMF: CSendDtmfHandler::CommandAllowed KErrNone != noMemory" ) |
|
344 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
345 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
346 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
347 // Command is not allowed |
|
348 commandAllowed = EFalse; |
|
349 } |
|
350 else |
|
351 { |
|
352 |
|
353 TPtr ptr = iDtmfStringUcs2->Des(); |
|
354 |
|
355 if ( ! ConvertDtmfStringToUcs2( ptr ) ) |
|
356 { |
|
357 LOG( SIMPLE, |
|
358 "CSendDtmfHandler::CommandAllowed not allowed" ) |
|
359 // DTMF string contains illegal characters |
|
360 iSendDtmfRsp.iGeneralResult = RSat::KCmdDataNotUnderstood; |
|
361 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
362 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
363 // Command is not allowed |
|
364 commandAllowed = EFalse; |
|
365 } |
|
366 } |
|
367 } |
|
368 |
|
369 if ( !commandAllowed ) |
|
370 { |
|
371 LOG( SIMPLE, |
|
372 "CSendDtmfHandler::CommandAllowed commandAllowed false" ) |
|
373 SendTerminalResponse(); |
|
374 } |
|
375 // Set icon command flag whether icon data was received and set qualifier |
|
376 // to no icon id |
|
377 // To be removed when icons are allowed in this command |
|
378 else if ( ( RSat::ESelfExplanatory == |
|
379 iSendDtmfData.iIconId.iQualifier ) || |
|
380 ( RSat::ENotSelfExplanatory == |
|
381 iSendDtmfData.iIconId.iQualifier ) ) |
|
382 { |
|
383 LOG( SIMPLE, |
|
384 "CSendDtmfHandler::CommandAllowed ENoIconId" ) |
|
385 iIconCommand = ETrue; |
|
386 iSendDtmfData.iIconId.iQualifier = RSat::ENoIconId; |
|
387 } |
|
388 else |
|
389 { |
|
390 iIconCommand = EFalse; |
|
391 } |
|
392 |
|
393 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::CommandAllowed exiting" ) |
|
394 return commandAllowed; |
|
395 } |
|
396 |
|
397 // ----------------------------------------------------------------------------- |
|
398 // From class CSatCommandHandler. |
|
399 // Need for ui session. |
|
400 // ----------------------------------------------------------------------------- |
|
401 // |
|
402 TBool CSendDtmfHandler::NeedUiSession() |
|
403 { |
|
404 LOG( NORMAL, "SENDDTMF: CSendDtmfHandler::NeedUiSession calling" ) |
|
405 iNeedUiSession = ETrue; |
|
406 |
|
407 if ( RSat::EAlphaIdNull == iSendDtmfData.iAlphaId.iStatus ) |
|
408 { |
|
409 LOG( NORMAL, "SENDDTMF: CSendDtmfHandler::NeedUiSession EAlphaIdNull" ) |
|
410 iNeedUiSession = EFalse; |
|
411 } |
|
412 |
|
413 // Notify Cover UI if it's supported |
|
414 if ( iNeedUiSession && iUtils->CoverUiSupported() ) |
|
415 { |
|
416 LOG( NORMAL, |
|
417 "SENDDTMF: CSendDtmfHandler::NeedUiSession CoverUiSupported" ) |
|
418 TSatCommandData medEventData; |
|
419 medEventData.iPCmdNumber = RSat::ESendDtmf; |
|
420 medEventData.iAlphaId = iSendDtmfData.iAlphaId; |
|
421 medEventData.iDuration.iNumOfUnits = KSatDefaultDuration; |
|
422 medEventData.iDuration.iTimeUnit = RSat::ESeconds; |
|
423 medEventData.iIconID = iSendDtmfData.iIconId; |
|
424 TSatCommandPckg tPckg( medEventData ); |
|
425 iUtils->RaiseSatEvent( tPckg ); |
|
426 } |
|
427 |
|
428 LOG2( NORMAL, |
|
429 "SENDDTMF: CSendDtmfHandler::NeedUiSession exiting,iNeedUiSession: %d", |
|
430 iNeedUiSession ) |
|
431 return iNeedUiSession; |
|
432 } |
|
433 |
|
434 // ----------------------------------------------------------------------------- |
|
435 // From class CSatCommandHandler. |
|
436 // Called when USAT API notifies that command. |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 void CSendDtmfHandler::HandleCommand() |
|
440 { |
|
441 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleCommand calling" ) |
|
442 |
|
443 iUtils->NotifyEvent( MSatUtils::ESendDtmfExecuting ); |
|
444 |
|
445 // Lower error granularity. This helps for mapping error cases |
|
446 iUtils->MultiModeApi().LowerErrorGranularity(); |
|
447 |
|
448 // Pointer to converted DTMF string |
|
449 TPtr ptr = iDtmfStringUcs2->Des(); |
|
450 |
|
451 iClientResponseReceived = EFalse; |
|
452 |
|
453 // First, send DTMF string |
|
454 iDtmfSender->SendToneString( ptr ); |
|
455 |
|
456 if ( iNeedUiSession ) |
|
457 { |
|
458 TRAPD( regErr, |
|
459 // Register to listen user cancel events: |
|
460 // Cancel key event from dialog |
|
461 iUtils->RegisterL( this, MSatUtils::ECommandCancelled ); |
|
462 // End key from dialog |
|
463 iUtils->RegisterL( this, MSatUtils::ECancelledUsingEndKey ); |
|
464 |
|
465 // Then send notification to UI |
|
466 // Register notification observer |
|
467 iUtils->RegisterServiceRequestL( |
|
468 ESatSProactiveNotification, |
|
469 ESatSProactiveNotificationResponse, |
|
470 this ) |
|
471 ); // TRAPD |
|
472 LOG2( NORMAL, |
|
473 "CSendDtmfHandler::HandleCommand regErr: %d", regErr ) |
|
474 if ( KErrNone != regErr ) |
|
475 { |
|
476 iDtmfSender->Cancel(); |
|
477 // Raise error granularity back to extended errors |
|
478 iUtils->MultiModeApi().RaiseErrorGranularity(); |
|
479 |
|
480 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
481 iSendDtmfRsp.iInfoType = RSat::KMeProblem; |
|
482 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
483 iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem ); |
|
484 SendTerminalResponse(); |
|
485 } |
|
486 else |
|
487 { |
|
488 TSatAlphaIdStatus alphaIdStatus; |
|
489 if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdNotPresent ) |
|
490 { |
|
491 LOG( SIMPLE, |
|
492 "SENDDTMF: CSendDtmfHandler::HandleCommand EAlphaIdNotPresent" ) |
|
493 // If AlphaID is not provided, show DTMF string in note. |
|
494 // Deliver empty text if DTMF string is bigger than it is |
|
495 // capable to deliver to SAT UI. |
|
496 alphaIdStatus = ESatAlphaIdNotProvided; |
|
497 LOG2( NORMAL, |
|
498 "SENDDTMF: CSendDtmfHandler::HandleCommand ptr.Length: %d", |
|
499 ptr.Length() ) |
|
500 if ( RSat::KAlphaIdMaxSize >= ptr.Length() ) |
|
501 { |
|
502 iNotificationData.iText = ptr; |
|
503 } |
|
504 else |
|
505 { |
|
506 iNotificationData.iText.Zero(); |
|
507 } |
|
508 } |
|
509 else if ( iSendDtmfData.iAlphaId.iStatus == RSat::EAlphaIdProvided ) |
|
510 { |
|
511 LOG( SIMPLE, |
|
512 "SENDDTMF: CSendDtmfHandler::HandleCommand EAlphaIdProvided" ) |
|
513 alphaIdStatus = ESatAlphaIdNotNull; |
|
514 iNotificationData.iText = iSendDtmfData.iAlphaId.iAlphaId; |
|
515 } |
|
516 else |
|
517 { |
|
518 LOG( SIMPLE, |
|
519 "SENDDTMF: CSendDtmfHandler::HandleCommand others" ) |
|
520 alphaIdStatus = ESatAlphaIdNull; |
|
521 iNotificationData.iText.Zero(); |
|
522 } |
|
523 |
|
524 // Build notification data |
|
525 iNotificationData.iAlphaIdStatus = alphaIdStatus; |
|
526 iNotificationData.iCommand = ESatSSendDtmfNotify; |
|
527 |
|
528 // Has to be casted to TInt before casting to TSatIconQualifier, |
|
529 // because GCC warns about the direct cast. |
|
530 const struct TSatIconId iconId = |
|
531 { iSendDtmfData.iIconId.iIdentifier, |
|
532 static_cast<TSatIconQualifier>( |
|
533 static_cast<TInt>( iSendDtmfData.iIconId.iQualifier ) ) }; |
|
534 |
|
535 iNotificationData.iIconId = iconId; |
|
536 |
|
537 // Send notification |
|
538 iUtils->SatUiHandler().UiSession()->SendCommand( |
|
539 &iNotificationDataPckg, |
|
540 &iNotificationRspPckg, |
|
541 ESatSProactiveNotification ); |
|
542 |
|
543 // DTMF String sent, wait for completion |
|
544 } |
|
545 } |
|
546 |
|
547 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleCommand exiting" ) |
|
548 } |
|
549 |
|
550 // ----------------------------------------------------------------------------- |
|
551 // From class CSatCommandHandler. |
|
552 // Called when UI launch fails. |
|
553 // ----------------------------------------------------------------------------- |
|
554 // |
|
555 void CSendDtmfHandler::UiLaunchFailed() |
|
556 { |
|
557 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::UiLaunchFailed calling" ) |
|
558 |
|
559 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
560 iSendDtmfRsp.iInfoType = RSat::KMeProblem; |
|
561 iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem ); |
|
562 iSendDtmfRsp.SetPCmdNumber( iSendDtmfData.PCmdNumber() ); |
|
563 SendTerminalResponse(); |
|
564 |
|
565 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::UiLaunchFailed exiting" ) |
|
566 } |
|
567 |
|
568 // ----------------------------------------------------------------------------- |
|
569 // C++ default constructor can NOT contain any code, that |
|
570 // might leave. |
|
571 // ----------------------------------------------------------------------------- |
|
572 // |
|
573 //lint -e{1403, 1769} Can not be initialized, harmless. |
|
574 CSendDtmfHandler::CSendDtmfHandler() : |
|
575 CSatCommandHandler(), |
|
576 iSendDtmfData(), |
|
577 iSendDtmfPckg( iSendDtmfData ), |
|
578 iSendDtmfRsp(), |
|
579 iSendDtmfRspPckg( iSendDtmfRsp ), |
|
580 iNotificationData(), |
|
581 iNotificationDataPckg( iNotificationData ), |
|
582 iNotificationRsp(), |
|
583 iNotificationRspPckg( iNotificationRsp ), |
|
584 // To be removed when icons are allowed in this command |
|
585 iIconCommand( EFalse ) |
|
586 { |
|
587 LOG( SIMPLE, |
|
588 "SENDDTMF: CSendDtmfHandler::CSendDtmfHandler calling - exiting" ) |
|
589 } |
|
590 |
|
591 // ----------------------------------------------------------------------------- |
|
592 // Symbian 2nd phase constructor can leave. |
|
593 // ----------------------------------------------------------------------------- |
|
594 // |
|
595 void CSendDtmfHandler::ConstructL() |
|
596 { |
|
597 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConstructL calling" ) |
|
598 |
|
599 // Register notification observer |
|
600 iUtils->RegisterServiceRequestL( |
|
601 ESatSProactiveNotification, |
|
602 ESatSProactiveNotificationResponse, |
|
603 this ); |
|
604 |
|
605 // DTMF Sender |
|
606 iDtmfSender = |
|
607 new ( ELeave ) CSatDtmfSender( *this, iUtils->MultiModeApi() ); |
|
608 |
|
609 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConstructL exiting" ) |
|
610 } |
|
611 |
|
612 |
|
613 // ----------------------------------------------------------------------------- |
|
614 // Converts DTMF string from extended BCD to UCS2. |
|
615 // ----------------------------------------------------------------------------- |
|
616 // |
|
617 TBool CSendDtmfHandler::ConvertDtmfStringToUcs2( TDes& aDtmfString ) |
|
618 { |
|
619 LOG( SIMPLE, |
|
620 "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 calling" ) |
|
621 aDtmfString.Zero(); |
|
622 |
|
623 const TInt bcdLength = iSendDtmfData.iDtmfString.Length(); |
|
624 TInt i( 0 ); |
|
625 TBool retVal( ETrue ); |
|
626 TBool continueLoop( ETrue ); |
|
627 |
|
628 for ( i = 0; i < bcdLength && continueLoop; i++ ) |
|
629 { |
|
630 // each 16 bit DTMF character of SAT ETel API holds two nibbles, |
|
631 // high byte always being 0 |
|
632 TChar twoBcd = iSendDtmfData.iDtmfString[i]; |
|
633 |
|
634 // low nibble yields first BCD in semi-octet representation |
|
635 TChar firstBcd = twoBcd & KLowNibble; |
|
636 |
|
637 // high nibble yields second BCD in semi-octet representation |
|
638 TChar secondBcd = ( twoBcd & KHighNibble ) >> KBitsInNibble; |
|
639 |
|
640 TChar destChar; |
|
641 TBool endOfString; |
|
642 TBool dtmfCharacter; |
|
643 |
|
644 // convert first extended BCD character |
|
645 ConvertDtmfCharacterToUcs2( |
|
646 firstBcd, endOfString, dtmfCharacter, destChar ); |
|
647 |
|
648 if ( endOfString ) |
|
649 { |
|
650 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \ |
|
651 (End of string in first BCD)" ) |
|
652 retVal = ETrue; // completed string (F digit) |
|
653 continueLoop = EFalse; |
|
654 } |
|
655 else if ( !dtmfCharacter ) |
|
656 { |
|
657 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \ |
|
658 (not dtmfCharacter in first BCD)" ) |
|
659 retVal = EFalse; |
|
660 continueLoop = EFalse; |
|
661 } |
|
662 else |
|
663 { |
|
664 aDtmfString.Append( destChar ); |
|
665 |
|
666 // convert second extended BCD character |
|
667 ConvertDtmfCharacterToUcs2( |
|
668 secondBcd, endOfString, dtmfCharacter, destChar ); |
|
669 |
|
670 if ( endOfString ) |
|
671 { |
|
672 LOG( SIMPLE, |
|
673 "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \ |
|
674 (End of string in second BCD)" ) |
|
675 retVal = ETrue; // completed string (F digit) |
|
676 continueLoop = EFalse; |
|
677 } |
|
678 else if ( !dtmfCharacter ) |
|
679 { |
|
680 LOG( SIMPLE, |
|
681 "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \ |
|
682 (not dtmfCharacter in second BCD)" ) |
|
683 retVal = EFalse; |
|
684 continueLoop = EFalse; |
|
685 } |
|
686 else |
|
687 { |
|
688 LOG( SIMPLE, |
|
689 "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 \ |
|
690 others" ) |
|
691 aDtmfString.Append( destChar ); |
|
692 } |
|
693 } |
|
694 } |
|
695 LOG2( NORMAL, |
|
696 "CSendDtmfHandler::ConvertDtmfStringToUcs2 i: %d", i ) |
|
697 LOG2( SIMPLE, |
|
698 "SENDDTMF: CSendDtmfHandler::ConvertDtmfStringToUcs2 exiting,\ |
|
699 retVal: %d", retVal ) |
|
700 return retVal; // completed string (all bytes converted) |
|
701 } |
|
702 |
|
703 // ----------------------------------------------------------------------------- |
|
704 // Converts character from extended BCD to UCS2. |
|
705 // ----------------------------------------------------------------------------- |
|
706 // |
|
707 void CSendDtmfHandler::ConvertDtmfCharacterToUcs2( |
|
708 const TChar& aExtBcd, |
|
709 TBool& aEndOfString, |
|
710 TBool& aDtmfCharacter, |
|
711 TChar& aUcs2Char ) const |
|
712 { |
|
713 LOG( SIMPLE, |
|
714 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 calling" ) |
|
715 |
|
716 aEndOfString = EFalse; |
|
717 aDtmfCharacter = ETrue; |
|
718 |
|
719 switch ( aExtBcd ) |
|
720 { |
|
721 case KBcdZero: |
|
722 case KBcdOne: |
|
723 case KBcdTwo: |
|
724 case KBcdThree: |
|
725 case KBcdFour: |
|
726 case KBcdFive: |
|
727 case KBcdSix: |
|
728 case KBcdSeven: |
|
729 case KBcdEight: |
|
730 case KBcdNine: |
|
731 { |
|
732 LOG( SIMPLE, |
|
733 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 Digit" ) |
|
734 aUcs2Char = KUcs2Zero + aExtBcd; |
|
735 break; |
|
736 } |
|
737 |
|
738 case KBcdStar: |
|
739 { |
|
740 LOG( SIMPLE, |
|
741 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdStar" ) |
|
742 aUcs2Char = KUcs2Star; |
|
743 break; |
|
744 } |
|
745 |
|
746 case KBcdHash: |
|
747 { |
|
748 LOG( SIMPLE, |
|
749 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdHash" ) |
|
750 aUcs2Char = KUcs2Hash; |
|
751 break; |
|
752 } |
|
753 |
|
754 case KBcdPause: |
|
755 { |
|
756 LOG( SIMPLE, |
|
757 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdPause" ) |
|
758 aUcs2Char = KUcs2Pause; |
|
759 break; |
|
760 } |
|
761 |
|
762 case KBcdEnd: |
|
763 { |
|
764 LOG( SIMPLE, |
|
765 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 KBcdEnd" ) |
|
766 aEndOfString = ETrue; |
|
767 break; |
|
768 } |
|
769 |
|
770 case KBcdWild: |
|
771 case KBcdExpansion: |
|
772 default: |
|
773 { |
|
774 LOG( SIMPLE, |
|
775 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 unknown" ) |
|
776 aDtmfCharacter = EFalse; |
|
777 } |
|
778 } |
|
779 |
|
780 LOG( SIMPLE, |
|
781 "SENDDTMF: CSendDtmfHandler::ConvertDtmfCharacterToUcs2 exiting" ) |
|
782 } |
|
783 |
|
784 // ----------------------------------------------------------------------------- |
|
785 // Handles the result of DTMF sending and sends terminal response. |
|
786 // ----------------------------------------------------------------------------- |
|
787 // |
|
788 void CSendDtmfHandler::HandleResult() |
|
789 { |
|
790 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult calling" ) |
|
791 |
|
792 // If UI is needed, send DTMF Done event to close any progress bar |
|
793 if ( iNeedUiSession ) |
|
794 { |
|
795 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult NeedUiSession" ) |
|
796 // To prevent client traffic jamming. |
|
797 // Send UI event only when client response is received. |
|
798 if ( !iClientResponseReceived && !iWait.IsStarted() ) |
|
799 { |
|
800 LOG( SIMPLE, |
|
801 "SENDDTMF: CSendDtmfHandler::HandleResult start iwait" ) |
|
802 iWait.Start(); |
|
803 } |
|
804 // No need to send command result since this only removes any |
|
805 // existing wait notes... |
|
806 iUtils->NotifyUiEvent( ESatSDtmfEndEvent, ESatEventNone, KErrNone ); |
|
807 } |
|
808 |
|
809 // Raise error granularity back to extended errors |
|
810 iUtils->MultiModeApi().RaiseErrorGranularity(); |
|
811 |
|
812 #ifdef __WINS__ |
|
813 if ( KErrTimedOut == iDtmfResult ) |
|
814 { |
|
815 iDtmfResult = KErrNone; |
|
816 } |
|
817 #endif |
|
818 |
|
819 LOG2( NORMAL, |
|
820 "SENDDTMF: CSendDtmfHandler::HandleResult Send DTMF result: %i", |
|
821 iDtmfResult ) |
|
822 |
|
823 switch ( iDtmfResult ) |
|
824 { |
|
825 case KErrNone: |
|
826 { |
|
827 // No errors in DTMF sending. But cases like user termination and |
|
828 // icons are handled here. |
|
829 if ( iNotificationRsp.iSessionTerminatedByUser ) |
|
830 { |
|
831 LOG( DETAILED, |
|
832 "SENDDTMF: CSendDtmfHandler::HandleResult session terminated \ |
|
833 by user" ) |
|
834 iSendDtmfRsp.iGeneralResult = RSat::KPSessionTerminatedByUser; |
|
835 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
836 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
837 } |
|
838 else |
|
839 { |
|
840 iSendDtmfRsp.iGeneralResult = RSat::KSuccess; |
|
841 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
842 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
843 |
|
844 // If command had icon data and was done succesfully, |
|
845 // report that icon was not shown. |
|
846 // To be removed and correct handling (i.e. ClientResponse to |
|
847 // notification is received) for general result |
|
848 // KSuccessRequestedIconNotDisplayed must be added when icons |
|
849 // are allowed in this command. |
|
850 if ( iIconCommand ) |
|
851 { |
|
852 LOG( DETAILED, |
|
853 "SENDDTMF: CSendDtmfHandler::HandleResult iIconCommand \ |
|
854 true" ) |
|
855 iSendDtmfRsp.iGeneralResult = |
|
856 RSat::KSuccessRequestedIconNotDisplayed; |
|
857 } |
|
858 } |
|
859 |
|
860 break; |
|
861 } |
|
862 case KErrCancel: |
|
863 case KErrEtelNoCarrier: |
|
864 { |
|
865 // Problems in communicating with receiving device are handled here |
|
866 // e.g. call was unexpectedly dropped. |
|
867 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
868 iSendDtmfRsp.iInfoType = RSat::KMeProblem; |
|
869 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
870 iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNoSpecificMeProblem ); |
|
871 break; |
|
872 } |
|
873 case KErrArgument: |
|
874 { |
|
875 // Maximum length of DTMF string reached. |
|
876 LOG( DETAILED, |
|
877 "SENDDTMF: CSendDtmfHandler Over maximum DTMF length" ) |
|
878 iSendDtmfRsp.iGeneralResult = RSat::KErrorRequiredValuesMissing; |
|
879 iSendDtmfRsp.iInfoType = RSat::KNoAdditionalInfo; |
|
880 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
881 break; |
|
882 } |
|
883 default: |
|
884 { |
|
885 // By default for other errors. |
|
886 iSendDtmfRsp.iGeneralResult = RSat::KMeUnableToProcessCmd; |
|
887 iSendDtmfRsp.iInfoType = RSat::KMeProblem; |
|
888 iSendDtmfRsp.iAdditionalInfo.Zero(); |
|
889 iSendDtmfRsp.iAdditionalInfo.Append( RSat::KNotInSpeechCall ); |
|
890 break; |
|
891 } |
|
892 } |
|
893 |
|
894 // Cancel DTMF sending if it is running. |
|
895 iDtmfSender->Cancel(); |
|
896 SendTerminalResponse(); |
|
897 |
|
898 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::HandleResult exiting" ) |
|
899 } |
|
900 |
|
901 // ----------------------------------------------------------------------------- |
|
902 // Sends terminal response. Makes sure that terminal response |
|
903 // is not send more that once / command. |
|
904 // ----------------------------------------------------------------------------- |
|
905 // |
|
906 void CSendDtmfHandler::SendTerminalResponse() |
|
907 { |
|
908 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendTerminalResponse calling" ) |
|
909 |
|
910 if ( !iTerminalRespSent ) |
|
911 { |
|
912 LOG( SIMPLE, |
|
913 "CSendDtmfHandler::SendTerminalResponse iTerminalRespSent false" ) |
|
914 iTerminalRespSent = ETrue; |
|
915 TerminalRsp( RSat::ESendDtmf, iSendDtmfRspPckg ); |
|
916 } |
|
917 |
|
918 LOG( SIMPLE, "SENDDTMF: CSendDtmfHandler::SendTerminalResponse exiting" ) |
|
919 } |
|
920 |
|