1 /* |
|
2 * Copyright (c) 2010 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: Pairing handler for local device initiated pairing |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "btnotifoutgoingpairinghandler.h" |
|
19 #include <btengconstants.h> |
|
20 #include <btservices/btdevextension.h> |
|
21 #include "btnotifsecuritymanager.h" |
|
22 #include "bluetoothtrace.h" |
|
23 #include "bluetoothnotification.h" |
|
24 #include "btnotifserver.h" |
|
25 #include "btnotifconnectiontracker.h" |
|
26 #include "btnotificationmanager.h" |
|
27 |
|
28 /** Length of the default PIN. */ |
|
29 const TInt KDefaultHeadsetPinLength = 4; |
|
30 |
|
31 /** Maximum repeated outgoing pairing attempt. |
|
32 * if the pairing fails the UI specs says |
|
33 * we can ask twice the user if he/she want |
|
34 * to retry pairing. |
|
35 */ |
|
36 const TInt KMaxRepeatedPairingAttempt = 2; |
|
37 |
|
38 enum TPairingStageId |
|
39 { |
|
40 /** |
|
41 * no pairing operation ongoing |
|
42 */ |
|
43 ENoBonding = 0, |
|
44 |
|
45 /** |
|
46 * pair with dedicated bonding method |
|
47 */ |
|
48 EDedicatedBonding = 200, |
|
49 |
|
50 /** |
|
51 * pair with general bonding by establishing L2CAP connection. |
|
52 */ |
|
53 EGeneralBonding, |
|
54 |
|
55 /** |
|
56 * delaying next pairing request for a while |
|
57 */ |
|
58 EGeneralBondingRetryTimer, |
|
59 |
|
60 /** |
|
61 * The last pairing retry |
|
62 */ |
|
63 EGeneralBondingRetry, |
|
64 |
|
65 /** |
|
66 * disconnecting physical link after pairing operation. |
|
67 * |
|
68 * todo: not used yet. |
|
69 */ |
|
70 EDisconnectLinkAfterBonding, |
|
71 }; |
|
72 |
|
73 /** SDP PSM (used for pairing) */ |
|
74 const TInt KSDPPSM = 0x0001; |
|
75 |
|
76 // Delay time to void Repeated Attempts on pairing |
|
77 const TInt KGeneralBondingRetryDelayMicroSeconds = 5000000; // 5.0s |
|
78 |
|
79 // ======== MEMBER FUNCTIONS ======== |
|
80 |
|
81 // --------------------------------------------------------------------------- |
|
82 // C++ default constructor |
|
83 // --------------------------------------------------------------------------- |
|
84 // |
|
85 CBTNotifOutgoingPairingHandler::CBTNotifOutgoingPairingHandler( CBTNotifSecurityManager& aParent, const TBTDevAddr& aAddr) |
|
86 : CBTNotifBasePairingHandler( aParent, aAddr ) |
|
87 { |
|
88 } |
|
89 |
|
90 // --------------------------------------------------------------------------- |
|
91 // Symbian 2nd-phase constructor |
|
92 // --------------------------------------------------------------------------- |
|
93 // |
|
94 void CBTNotifOutgoingPairingHandler::ConstructL() |
|
95 { |
|
96 BaseConstructL(); |
|
97 User::LeaveIfError( iTimer.CreateLocal() ); |
|
98 iPairingAttempt = KMaxRepeatedPairingAttempt; |
|
99 } |
|
100 |
|
101 // --------------------------------------------------------------------------- |
|
102 // NewL |
|
103 // --------------------------------------------------------------------------- |
|
104 // |
|
105 CBTNotifBasePairingHandler* CBTNotifOutgoingPairingHandler::NewL( CBTNotifSecurityManager& aParent, |
|
106 const TBTDevAddr& aAddr ) |
|
107 { |
|
108 CBTNotifOutgoingPairingHandler* self = new( ELeave ) CBTNotifOutgoingPairingHandler( aParent, aAddr ); |
|
109 CleanupStack::PushL( self ); |
|
110 self->ConstructL(); |
|
111 CleanupStack::Pop( self ); |
|
112 return self; |
|
113 } |
|
114 |
|
115 // --------------------------------------------------------------------------- |
|
116 // Destructor |
|
117 // --------------------------------------------------------------------------- |
|
118 // |
|
119 CBTNotifOutgoingPairingHandler::~CBTNotifOutgoingPairingHandler() |
|
120 { |
|
121 if ( iActive ) |
|
122 { |
|
123 iActive->Cancel(); |
|
124 } |
|
125 iBondingSession.Close(); |
|
126 iSocket.Close(); |
|
127 iTimer.Close(); |
|
128 if( iNotification ) |
|
129 { |
|
130 // Clear the notification callback, we cannot receive them anymore. |
|
131 iNotification->RemoveObserver(); |
|
132 iNotification->Close(); // Also dequeues the notification from the queue. |
|
133 iNotification = NULL; |
|
134 } |
|
135 } |
|
136 |
|
137 // --------------------------------------------------------------------------- |
|
138 // Simply deny the request as this is handing outgoing pairing |
|
139 // --------------------------------------------------------------------------- |
|
140 // |
|
141 TInt CBTNotifOutgoingPairingHandler::ObserveIncomingPair( const TBTDevAddr& aAddr ) |
|
142 { |
|
143 (void)aAddr; |
|
144 return KErrServerBusy; |
|
145 } |
|
146 |
|
147 // --------------------------------------------------------------------------- |
|
148 // Accept the request only this device is not busy with another pairing request. |
|
149 // --------------------------------------------------------------------------- |
|
150 // |
|
151 void CBTNotifOutgoingPairingHandler::HandleOutgoingPairL( const TBTDevAddr& aAddr, TUint aCod ) |
|
152 { |
|
153 BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST," cod 0x%08x", aCod ); |
|
154 if ( iActive->IsActive() || aAddr != iAddr ) |
|
155 { |
|
156 // we don't allow another pairing request. |
|
157 User::Leave( KErrServerBusy ); |
|
158 } |
|
159 iAddr = aAddr; |
|
160 iCod = TBTDeviceClass( aCod ); |
|
161 UnSetPairResult(); |
|
162 iParent.UnpairDevice( iAddr ); |
|
163 if ( CBtDevExtension::IsHeadset( iCod ) ) |
|
164 { |
|
165 // If the devie is a headset, set to 0000 pin auto pairing |
|
166 iPairMode = EBTOutgoingHeadsetAutoPairing; |
|
167 } |
|
168 else |
|
169 { |
|
170 iPairMode = EBTOutgoingNoneHeadsetPairing; |
|
171 } |
|
172 DoPairingL(); |
|
173 } |
|
174 |
|
175 // --------------------------------------------------------------------------- |
|
176 // Cancels an outstanding pair request by self-destruct |
|
177 // --------------------------------------------------------------------------- |
|
178 // |
|
179 void CBTNotifOutgoingPairingHandler::CancelOutgoingPair() |
|
180 { |
|
181 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
182 iParent.RenewPairingHandler( NULL ); |
|
183 if( iNotification ) |
|
184 { |
|
185 // Cancel the user query |
|
186 // This will also unregister us from the notification. |
|
187 TInt err = iNotification->Close(); |
|
188 NOTIF_NOTHANDLED( !err ) |
|
189 iNotification = NULL; |
|
190 } |
|
191 } |
|
192 |
|
193 |
|
194 // --------------------------------------------------------------------------- |
|
195 // when phone initiated a pairing request towards a headset, |
|
196 // Pin code 0000 is first tried. |
|
197 // --------------------------------------------------------------------------- |
|
198 // |
|
199 void CBTNotifOutgoingPairingHandler::GetPinCode( |
|
200 TBTPinCode& aPin, const TBTDevAddr& aAddr, TInt aMinPinLength ) |
|
201 { |
|
202 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
203 aPin().iLength = 0; |
|
204 if ( aMinPinLength <= KDefaultHeadsetPinLength |
|
205 && aAddr == iAddr |
|
206 && iPairMode == EBTOutgoingHeadsetAutoPairing) |
|
207 { |
|
208 // if the pairing requires a stronger security level (indicated |
|
209 // by aMinPinLength), |
|
210 // 0000 will not be supplied as it does not mmet the security |
|
211 // requirements |
|
212 const TUint8 KZeroPinValue = '0'; |
|
213 for (TInt i = 0; i < KDefaultHeadsetPinLength; ++i) |
|
214 { |
|
215 aPin().iPIN[i] = KZeroPinValue; |
|
216 } |
|
217 aPin().iLength = KDefaultHeadsetPinLength; |
|
218 } |
|
219 } |
|
220 |
|
221 // --------------------------------------------------------------------------- |
|
222 // Abort pairing handling, request the owner to destroy this. |
|
223 // --------------------------------------------------------------------------- |
|
224 // |
|
225 void CBTNotifOutgoingPairingHandler::StopPairHandling( const TBTDevAddr& aAddr ) |
|
226 { |
|
227 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
228 if ( aAddr == iAddr ) |
|
229 { |
|
230 iParent.OutgoingPairCompleted( KErrCancel ); |
|
231 iParent.RenewPairingHandler( NULL ); |
|
232 if( iNotification ) |
|
233 { |
|
234 // Cancel the user query |
|
235 // This will also unregister us from the notification. |
|
236 TInt err = iNotification->Close(); |
|
237 NOTIF_NOTHANDLED( !err ) |
|
238 iNotification = NULL; |
|
239 } |
|
240 } |
|
241 } |
|
242 |
|
243 // --------------------------------------------------------------------------- |
|
244 // Pairing result will be received when pairing operation completes. |
|
245 // --------------------------------------------------------------------------- |
|
246 // |
|
247 void CBTNotifOutgoingPairingHandler::DoHandlePairServerResult( TInt aResult ) |
|
248 { |
|
249 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
250 if (aResult == (KHCIErrorBase-EPairingNotAllowed)) |
|
251 { |
|
252 // if EPairingNotAllowed is recieved then any further pairing attempts will fail |
|
253 // so don't attampt to pair |
|
254 iPairMode = EBTOutgoingPairNone; |
|
255 } |
|
256 } |
|
257 |
|
258 // --------------------------------------------------------------------------- |
|
259 // Cancels possible outstanding pairing and notify user pair success. |
|
260 // --------------------------------------------------------------------------- |
|
261 // |
|
262 void CBTNotifOutgoingPairingHandler::DoHandleRegistryNewPairedEvent( |
|
263 const TBTNamelessDevice& aDev ) |
|
264 { |
|
265 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
266 TInt err( KErrNone ); |
|
267 // If pairing was performed using Just Works mode, we set a |
|
268 // UICookie to indicate that the device is successfully |
|
269 // bonded so that this device will be listed in paired device view of |
|
270 // bluetooth application: |
|
271 if ( aDev.LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable ) |
|
272 { |
|
273 BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST,"[BTNOTIF] Outgoing Pairing, Just Works pairing"); |
|
274 err = iParent.AddUiCookieJustWorksPaired( aDev ); |
|
275 } |
|
276 iActive->Cancel(); |
|
277 SetPairResult( err ? err : KErrNone ); |
|
278 if(err == KErrNone){ |
|
279 TRAP_IGNORE(ShowPairingResultNoteL(err)); |
|
280 } |
|
281 iParent.OutgoingPairCompleted( err ); |
|
282 iParent.RenewPairingHandler( NULL ); |
|
283 } |
|
284 |
|
285 // --------------------------------------------------------------------------- |
|
286 // From class MBTNotifPairingAOObserver. |
|
287 // Based on the result code, decides the next operation, either try pairing |
|
288 // with another mode, or complete pair request. |
|
289 // --------------------------------------------------------------------------- |
|
290 // |
|
291 void CBTNotifOutgoingPairingHandler::RequestCompletedL( |
|
292 CBtSimpleActive* aActive, TInt aStatus ) |
|
293 { |
|
294 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
295 BOstraceExt3(TRACE_DEBUG,DUMMY_DEVLIST,"reqid %d, status: %d, pair mode %d ", aActive->RequestId(), aStatus, iPairMode); |
|
296 if( aActive->RequestId() == EDedicatedBonding && |
|
297 ( aStatus == KErrRemoteDeviceIndicatedNoBonding || |
|
298 ( aStatus && iPairMode != EBTOutgoingNoneHeadsetPairing && iPairMode != EBTOutgoingPairNone ) ) ) |
|
299 { |
|
300 // try general pairing if the remote doesn't have dedicated bonding, or |
|
301 // pairing fails with a headset. |
|
302 DoPairingL(); |
|
303 } |
|
304 else if ( aStatus && iPairMode == EBTOutgoingHeadsetAutoPairing ) |
|
305 { |
|
306 iPairMode = EBTOutgoingHeadsetManualPairing; |
|
307 // auto pairing with headset failed, try to pair again with manual pin: |
|
308 BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST," auto pairing failed, switch to manual pairing"); |
|
309 DoPairingL(); |
|
310 } |
|
311 else if ( aStatus && aActive->RequestId() == EGeneralBonding && |
|
312 iPairMode == EBTOutgoingHeadsetManualPairing ) |
|
313 { |
|
314 // pairing headset with manual pin failed, wait for a while and try again: |
|
315 iActive->SetRequestId( EGeneralBondingRetryTimer ); |
|
316 iTimer.After( iActive->iStatus, KGeneralBondingRetryDelayMicroSeconds ); |
|
317 iActive->GoActive(); |
|
318 } |
|
319 else if( aActive->RequestId() == EGeneralBondingRetryTimer ) |
|
320 { |
|
321 // try to pair headset again with manual pin again: |
|
322 DoPairingL(); |
|
323 } |
|
324 else if ( aStatus ) |
|
325 { |
|
326 // we only starts showing note if pairing failed. |
|
327 // For a successful pair, we must wait until registry has been updated. |
|
328 if ( !IsPairResultSet() ) |
|
329 { |
|
330 SetPairResult( aStatus ); |
|
331 } |
|
332 if ( aStatus ) |
|
333 { |
|
334 // retry pairing |
|
335 if(aStatus && iPairingAttempt > 0) |
|
336 { |
|
337 if(aActive->RequestId() == EGeneralBondingRetry && iPairMode == EBTOutgoingHeadsetManualPairing) |
|
338 { |
|
339 // Headset pairing failed, reset and try again from auto pairing |
|
340 iActive->SetRequestId(EGeneralBonding); |
|
341 } |
|
342 iPairingAttempt --; |
|
343 ShowPairingRetryDialog(); |
|
344 } |
|
345 else |
|
346 { |
|
347 iPairingAttempt --; |
|
348 ShowPairingFailureDialog(); |
|
349 } |
|
350 } |
|
351 } |
|
352 } |
|
353 |
|
354 // --------------------------------------------------------------------------- |
|
355 // From class MBTEngActiveObserver. |
|
356 // cancels an outstanding request according to the given id. |
|
357 // --------------------------------------------------------------------------- |
|
358 // |
|
359 void CBTNotifOutgoingPairingHandler::CancelRequest( TInt aRequestId ) |
|
360 { |
|
361 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
362 switch ( aRequestId ) |
|
363 { |
|
364 case EDedicatedBonding: |
|
365 { |
|
366 iBondingSession.Close(); |
|
367 break; |
|
368 } |
|
369 case EGeneralBonding: |
|
370 case EGeneralBondingRetry: |
|
371 { |
|
372 iSocket.CancelConnect(); |
|
373 iSocket.Close(); |
|
374 break; |
|
375 } |
|
376 case EGeneralBondingRetryTimer: |
|
377 { |
|
378 iTimer.Cancel(); |
|
379 break; |
|
380 } |
|
381 } |
|
382 } |
|
383 |
|
384 // --------------------------------------------------------------------------- |
|
385 // From class MBTEngActiveObserver. |
|
386 // Handles a leave in RequestCompleted by self-destructing. |
|
387 // --------------------------------------------------------------------------- |
|
388 // |
|
389 void CBTNotifOutgoingPairingHandler::HandleError( |
|
390 CBtSimpleActive* aActive, TInt aError ) |
|
391 { |
|
392 BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"error: %d", aError ); |
|
393 // Our RunL can actually not leave, so we should never reach here. |
|
394 (void) aActive; |
|
395 iParent.OutgoingPairCompleted( aError ); |
|
396 iParent.RenewPairingHandler( NULL ); |
|
397 if( iNotification ) |
|
398 { |
|
399 // Cancel the user query |
|
400 // This will also unregister us from the notification. |
|
401 TInt err = iNotification->Close(); |
|
402 NOTIF_NOTHANDLED( !err ) |
|
403 iNotification = NULL; |
|
404 } |
|
405 } |
|
406 |
|
407 // --------------------------------------------------------------------------- |
|
408 // decide the next state and issue pair request |
|
409 // --------------------------------------------------------------------------- |
|
410 // |
|
411 void CBTNotifOutgoingPairingHandler::DoPairingL() |
|
412 { |
|
413 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
414 TPairingStageId currentMode = ( TPairingStageId ) iActive->RequestId(); |
|
415 ASSERT( !iActive->IsActive() ); |
|
416 TPairingStageId nextMode( EGeneralBonding ); |
|
417 |
|
418 // if running BTv2.0 stack, dedicated bonding method |
|
419 // is not available. |
|
420 if ( currentMode == ENoBonding && iParent.PairingServer() != NULL ) |
|
421 { |
|
422 nextMode = EDedicatedBonding; |
|
423 } |
|
424 else if(currentMode == EGeneralBondingRetryTimer) |
|
425 { |
|
426 nextMode = EGeneralBondingRetry; |
|
427 } |
|
428 |
|
429 BOstraceExt2(TRACE_DEBUG,DUMMY_DEVLIST,"[BTENG] CBTEngOtgPair::DoPairingL: bonding mode: pre %d, next %d", currentMode, nextMode); |
|
430 |
|
431 iActive->SetRequestId( nextMode ); |
|
432 if ( nextMode == EDedicatedBonding ) |
|
433 { |
|
434 iBondingSession.Start( *iParent.PairingServer(), iAddr, iActive->RequestStatus() ); |
|
435 } |
|
436 else |
|
437 { |
|
438 TBTServiceSecurity sec; |
|
439 sec.SetAuthentication( ETrue ); |
|
440 iSockAddr.SetBTAddr( iAddr ); |
|
441 iSockAddr.SetPort(KSDPPSM); |
|
442 iSockAddr.SetSecurity( sec ); |
|
443 iSocket.Close(); |
|
444 User::LeaveIfError( iSocket.Open( iParent.SocketServ(), KL2CAPDesC ) ); |
|
445 iSocket.Connect( iSockAddr, iActive->RequestStatus() ); |
|
446 } |
|
447 iActive->GoActive(); |
|
448 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
449 } |
|
450 |
|
451 // --------------------------------------------------------------------------- |
|
452 // From class MBTNotificationResult. |
|
453 // Handle a result from a user query. |
|
454 // --------------------------------------------------------------------------- |
|
455 // |
|
456 void CBTNotifOutgoingPairingHandler::MBRDataReceived( CHbSymbianVariantMap& aData ) |
|
457 { |
|
458 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
459 (void) aData; |
|
460 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
461 } |
|
462 |
|
463 // --------------------------------------------------------------------------- |
|
464 // From class MBTNotificationResult. |
|
465 // The notification is finished. |
|
466 // --------------------------------------------------------------------------- |
|
467 // |
|
468 void CBTNotifOutgoingPairingHandler::MBRNotificationClosed( TInt aError, const TDesC8& aData ) |
|
469 { |
|
470 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError ); |
|
471 // First unregister from the notification, so we can already get the next one. |
|
472 iNotification->RemoveObserver(); |
|
473 iNotification = NULL; |
|
474 TRAP_IGNORE( NotificationClosedL( aError, aData ) ); |
|
475 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
476 } |
|
477 |
|
478 // --------------------------------------------------------------------------- |
|
479 // Get and configure a notification. |
|
480 // --------------------------------------------------------------------------- |
|
481 // |
|
482 void CBTNotifOutgoingPairingHandler::PrepareNotificationL( TBluetoothDialogParams::TBTDialogType aType, |
|
483 TBTDialogResourceId aResourceId ) |
|
484 { |
|
485 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
486 iNotification = |
|
487 iParent.ConnectionTracker().NotificationManager()->GetNotification(); |
|
488 User::LeaveIfNull( iNotification ); // For OOM exception, leaves with KErrNoMemory |
|
489 iNotification->SetObserver( this ); |
|
490 iNotification->SetNotificationType( aType, aResourceId ); |
|
491 const CBtDevExtension* dev = iParent.BTDevRepository().Device(iAddr); |
|
492 if(dev) |
|
493 { |
|
494 User::LeaveIfError(iNotification->SetData( TBluetoothDeviceDialog::EDeviceName, dev->Alias())); |
|
495 } |
|
496 else |
|
497 { |
|
498 TBTDeviceName name; |
|
499 iAddr.GetReadable(name); |
|
500 User::LeaveIfError(iNotification->SetData( TBluetoothDeviceDialog::EDeviceName, name)); |
|
501 NOTIF_NOTHANDLED( !err ) |
|
502 } |
|
503 iParent.ConnectionTracker().NotificationManager()->QueueNotificationL( iNotification); |
|
504 NOTIF_NOTHANDLED( !err ) |
|
505 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
506 } |
|
507 |
|
508 // --------------------------------------------------------------------------- |
|
509 // The notification is finished, handle the result. |
|
510 // --------------------------------------------------------------------------- |
|
511 // |
|
512 void CBTNotifOutgoingPairingHandler::NotificationClosedL( TInt aError, const TDesC8& aData ) |
|
513 { |
|
514 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError ); |
|
515 // Read the result. |
|
516 TPckgC<TBool> result( EFalse ); |
|
517 result.Set( aData.Ptr(), result.Length() ); // Read the part containing the result |
|
518 // Set a pointer descriptor to capture the remaining data, if any. |
|
519 TPtrC8 dataPtr( aData.Mid( result.Length() ) ); |
|
520 |
|
521 if(result() && iPairingAttempt >= 0) |
|
522 { |
|
523 HandleOutgoingPairL(iAddr,iCod.DeviceClass()); |
|
524 } |
|
525 else |
|
526 { |
|
527 iPairingAttempt = KMaxRepeatedPairingAttempt; // reset the counter |
|
528 iParent.OutgoingPairCompleted( KErrCancel ); |
|
529 iParent.RenewPairingHandler( NULL ); |
|
530 } |
|
531 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
532 } |
|
533 |
|
534 // --------------------------------------------------------------------------- |
|
535 // Show a dialog to ask the user to retry the pairing |
|
536 // --------------------------------------------------------------------------- |
|
537 // |
|
538 void CBTNotifOutgoingPairingHandler::ShowPairingRetryDialog() |
|
539 { |
|
540 PrepareNotificationL( TBluetoothDialogParams::EQuery, EPairingFailureRetry); |
|
541 } |
|
542 |
|
543 // --------------------------------------------------------------------------- |
|
544 // Show a dialog to tell the user pairing retry attempt failed |
|
545 // --------------------------------------------------------------------------- |
|
546 // |
|
547 void CBTNotifOutgoingPairingHandler::ShowPairingFailureDialog() |
|
548 { |
|
549 PrepareNotificationL( TBluetoothDialogParams::EQuery, EPairingFailureOk ); |
|
550 } |
|
551 |
|
552 |
|
553 |
|