|
1 /* |
|
2 * ============================================================================ |
|
3 * Name : btnotifconnection.cpp |
|
4 * Part of : bluetoothengine / btnotif |
|
5 * Description : Class for observing events of a single connection, and for |
|
6 * managing any user notifications related to the connection. |
|
7 * |
|
8 * Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
9 * All rights reserved. |
|
10 * This component and the accompanying materials are made available |
|
11 * under the terms of "Eclipse Public License v1.0" |
|
12 * which accompanies this distribution, and is available |
|
13 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
14 * |
|
15 * Initial Contributors: |
|
16 * Nokia Corporation - initial contribution. |
|
17 * |
|
18 * Contributors: |
|
19 * Nokia Corporation |
|
20 * ============================================================================ |
|
21 * Template version: 4.1 |
|
22 */ |
|
23 |
|
24 #include "btnotifconnection.h" |
|
25 #include <btextnotifiers.h> |
|
26 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
27 #include <btextnotifierspartner.h> |
|
28 #endif |
|
29 |
|
30 #include "btnotifconnectiontracker.h" |
|
31 #include "btnotifpairinghelper.h" |
|
32 #include "btnotificationmanager.h" |
|
33 #include "btnotifclientserver.h" |
|
34 #include "bluetoothtrace.h" |
|
35 |
|
36 /** Id for the baseband connection watcher active object. */ |
|
37 const TInt KConnectionWatcher = 40; |
|
38 /** Id for the registry watcher active object. */ |
|
39 const TInt KRegistryWatcher = 41; |
|
40 /** Id for the active object for updating the registry. */ |
|
41 const TInt KRegistryRetriever = 42; |
|
42 /** Event mask for subscribing to baseband connection events |
|
43 * (need to check if these are appropriate). */ |
|
44 const TInt KBbEventMask = ENotifyAnyRole | ENotifyAuthenticationComplete | |
|
45 ENotifyPhysicalLinkUp | ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError; |
|
46 |
|
47 |
|
48 // ======== LOCAL FUNCTIONS ======== |
|
49 |
|
50 // --------------------------------------------------------------------------- |
|
51 // Decide the device name to display from the device information, and |
|
52 // converts the name if necessary. |
|
53 // --------------------------------------------------------------------------- |
|
54 // |
|
55 void GetDeviceNameL( TBTDeviceName& aName, const CBTDevice& aDevice ) |
|
56 { |
|
57 if( aDevice.IsValidFriendlyName() ) |
|
58 { |
|
59 aName.Copy( aDevice.FriendlyName() ); |
|
60 } |
|
61 else |
|
62 { |
|
63 aName.Zero(); |
|
64 if( aDevice.IsValidDeviceName() ) |
|
65 { |
|
66 aName = BTDeviceNameConverter::ToUnicodeL( aDevice.DeviceName() ); |
|
67 } |
|
68 } |
|
69 } |
|
70 |
|
71 |
|
72 // --------------------------------------------------------------------------- |
|
73 // Compare 2 device records device pairing has succeeded. |
|
74 // aDev2 is the updated device record, aDev1 is the previous record. |
|
75 // --------------------------------------------------------------------------- |
|
76 // |
|
77 TBool CheckRegistryPairedStatus( const CBTDevice* aOrig, const CBTDevice* aNew ) |
|
78 { |
|
79 TBool result = EFalse; |
|
80 // Use the device class to check that this has any valid information. |
|
81 if( aOrig->AsNamelessDevice().IsValidDeviceClass() && |
|
82 !( aOrig->IsValidPaired() && aOrig->IsPaired() ) || |
|
83 aOrig->LinkKeyType() == ELinkKeyUnauthenticatedUpgradable ) |
|
84 { |
|
85 // Only consider the result if the original device is not marked as paired. |
|
86 if( aNew->IsValidPaired() && aNew->IsPaired() && aNew->IsValidLinkKey() && |
|
87 aNew->LinkKeyType() != ELinkKeyUnauthenticatedUpgradable ) |
|
88 { |
|
89 // The new device record has valid pairing information, so |
|
90 // this device is now paired. |
|
91 result = ETrue; |
|
92 } |
|
93 } |
|
94 return result; |
|
95 } |
|
96 |
|
97 |
|
98 // ======== MEMBER FUNCTIONS ======== |
|
99 |
|
100 // --------------------------------------------------------------------------- |
|
101 // C++ default constructor |
|
102 // --------------------------------------------------------------------------- |
|
103 // |
|
104 CBTNotifConnection::CBTNotifConnection( const TBTDevAddr& aAddr, |
|
105 CBTNotifConnectionTracker* aTracker ) |
|
106 : iAddr( aAddr ), |
|
107 iTracker( aTracker ) |
|
108 { |
|
109 } |
|
110 |
|
111 |
|
112 // --------------------------------------------------------------------------- |
|
113 // Symbian 2nd-phase constructor |
|
114 // --------------------------------------------------------------------------- |
|
115 // |
|
116 void CBTNotifConnection::ConstructL() |
|
117 { |
|
118 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
119 iDevice = CBTDevice::NewL( iAddr ); |
|
120 iPhyActive = CBtSimpleActive::NewL(*this, KConnectionWatcher ); |
|
121 iRegActive = CBtSimpleActive::NewL( *this, KRegistryRetriever ); |
|
122 // ToDo: need to check if this succeeds if a connection is |
|
123 // being created, in case of outgoing pairing. |
|
124 User::LeaveIfError( iPhyLink.Open( iTracker->SocketServerSession(), iAddr ) ); |
|
125 // Subscribe to events. |
|
126 iBasebandEvent.FillZ(); // To be sure that we are not reading false events. |
|
127 iPhyLink.NotifyNextBasebandChangeEvent( iBasebandEvent, |
|
128 iPhyActive->RequestStatus(), KBbEventMask ); |
|
129 iPhyActive->GoActive(); |
|
130 // Get the details from BT registry |
|
131 TBTRegistrySearch pattern; |
|
132 pattern.FindAddress( iAddr ); |
|
133 User::LeaveIfError( iRegistry.Open( iTracker->RegistryServerSession() ) ); |
|
134 iRegistry.CreateView( pattern, iRegActive->RequestStatus() ); |
|
135 iRegActive->GoActive(); |
|
136 iCurrentOp = EReadingRegistry; |
|
137 iRegDevArray = new CBTDeviceArray(1); // only 1 entry ever used |
|
138 // ToDo: more initialization needed? |
|
139 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
140 } |
|
141 |
|
142 |
|
143 // --------------------------------------------------------------------------- |
|
144 // NewLC. |
|
145 // --------------------------------------------------------------------------- |
|
146 // |
|
147 CBTNotifConnection* CBTNotifConnection::NewLC( const TBTDevAddr& aAddr, |
|
148 CBTNotifConnectionTracker* aTracker ) |
|
149 { |
|
150 CBTNotifConnection* self = new( ELeave ) CBTNotifConnection( aAddr, aTracker ); |
|
151 CleanupStack::PushL( self ); |
|
152 self->ConstructL(); |
|
153 return self; |
|
154 } |
|
155 |
|
156 |
|
157 // --------------------------------------------------------------------------- |
|
158 // Destructor |
|
159 // --------------------------------------------------------------------------- |
|
160 // |
|
161 CBTNotifConnection::~CBTNotifConnection() |
|
162 { |
|
163 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
164 if( iNotification ) |
|
165 { |
|
166 // Clear the notification callback, we cannot receive them anymore. |
|
167 iNotification->RemoveObserver(); |
|
168 iNotification->Close(); // Also dequeues the notification from the queue. |
|
169 iNotification = NULL; |
|
170 } |
|
171 delete iRegActive; |
|
172 delete iRegistryResponse; |
|
173 iRegistry.Close(); |
|
174 delete iDevMan; |
|
175 |
|
176 delete iPhyActive; |
|
177 iPhyLink.Close(); |
|
178 delete iDevice; |
|
179 delete iPairingHelper; |
|
180 |
|
181 while( iMsgHandleQ.Count() ) |
|
182 { |
|
183 CompleteClientRequest( KErrDisconnected, KNullDesC8 ); |
|
184 } |
|
185 iMsgHandleQ.Close(); |
|
186 iAcceptedConnections.Close(); |
|
187 iDeniedConnections.Close(); |
|
188 iRegDevArray->ResetAndDestroy(); |
|
189 delete iRegDevArray; |
|
190 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
191 } |
|
192 |
|
193 |
|
194 // --------------------------------------------------------------------------- |
|
195 // Check what to do next. |
|
196 // This function should be called whenever we may be ready for the next |
|
197 // request/action, which is from any callback function i.e. |
|
198 // MBAORequestCompletedL, MBRNotificationClosed, HandleNotifierRequestL and |
|
199 // CancelNotifierRequestL. |
|
200 // --------------------------------------------------------------------------- |
|
201 // |
|
202 void CBTNotifConnection::CheckNextOperationL() |
|
203 { |
|
204 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
205 if( iCurrentOp == EIdle ) |
|
206 { |
|
207 // Check the link state, to see if it has gone down already. |
|
208 TUint32 linkState = 0; |
|
209 TInt err = iPhyLink.PhysicalLinkState( linkState ); |
|
210 TBool linkDown = linkState & ENotifyPhysicalLinkDown; |
|
211 if( ( !err && linkDown ) || err == KErrDisconnected ) |
|
212 { |
|
213 // The link state tells us that the link is down, |
|
214 // inform the connection tracker the we are done. |
|
215 iTracker->HandleLinkCountChangeL(); |
|
216 // Note that we may be deleted now! |
|
217 } |
|
218 else if( iMsgHandleQ.Count() ) |
|
219 { |
|
220 // Get the next request and handle it. |
|
221 // ToDo: differentiate between notifier and pairing message! |
|
222 const RMessage2* message = iTracker->Server()->FindMessageFromHandle( iMsgHandleQ[0] ); |
|
223 NOTIF_NOTHANDLED( message ) |
|
224 TInt opcode = message->Function(); |
|
225 if( opcode <= EBTNotifUpdateNotifier ) |
|
226 { |
|
227 TBuf8<0x250> paramsBuf; // Size needs to be long enough to read all possible parameter sizes. |
|
228 message->ReadL( EBTNotifSrvParamSlot, paramsBuf ); |
|
229 HandleNotifierRequestL( paramsBuf, *message ); |
|
230 } |
|
231 else |
|
232 { |
|
233 iMsgHandleQ.Remove( 0 ); |
|
234 StartBondingL( *message ); |
|
235 } |
|
236 } |
|
237 } |
|
238 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
239 } |
|
240 |
|
241 |
|
242 // --------------------------------------------------------------------------- |
|
243 // Complete the first outstanding client request and removes it from the queue. |
|
244 // --------------------------------------------------------------------------- |
|
245 // |
|
246 void CBTNotifConnection::CompleteClientRequest( TInt aReason, const TDesC8& aReply ) |
|
247 { |
|
248 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
249 NOTIF_NOTHANDLED( iMsgHandleQ.Count() ) |
|
250 TInt err = iTracker->Server()->CompleteMessage( iMsgHandleQ[0], aReason, aReply ); |
|
251 NOTIF_NOTHANDLED( !err ) |
|
252 iMsgHandleQ.Remove( 0 ); |
|
253 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
254 } |
|
255 |
|
256 |
|
257 // --------------------------------------------------------------------------- |
|
258 // Distinguish a request and pass to corresponding handle. |
|
259 // --------------------------------------------------------------------------- |
|
260 // |
|
261 void CBTNotifConnection::HandleNotifierRequestL( const TDesC8& aParams, |
|
262 const RMessage2& aMessage ) |
|
263 { |
|
264 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aMessage.Int0() ); |
|
265 if( !iMsgHandleQ.Count() || iMsgHandleQ[0] != aMessage.Handle() ) |
|
266 { |
|
267 // If we are processing a queued request, we of course don't queue |
|
268 // it again. In that case we are handling the first request from the queue. |
|
269 iMsgHandleQ.AppendL( aMessage.Handle() ); |
|
270 } |
|
271 if( iCurrentOp == EIdle || iCurrentOp == EBonding ) |
|
272 { |
|
273 // ToDo: check non-pairing operation when bonding |
|
274 TInt uid = aMessage.Int0(); |
|
275 if( uid == KBTManAuthNotifierUid.iUid ) |
|
276 { |
|
277 HandleAuthorizationReqL( aParams ); |
|
278 } |
|
279 else if( uid == KBTManPinNotifierUid.iUid || |
|
280 uid == KBTPinCodeEntryNotifierUid.iUid || |
|
281 uid == KBTNumericComparisonNotifierUid.iUid || |
|
282 uid == KBTPasskeyDisplayNotifierUid.iUid ) |
|
283 { |
|
284 if( !iPairingHelper ) |
|
285 { |
|
286 BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, |
|
287 "[BTNOTIF]\t CBTNotifConnection::HandleNotifierRequestL: creating CBTNotifPairingHelper"); |
|
288 iPairingHelper = CBTNotifPairingHelper::NewL( this, iTracker ); |
|
289 } |
|
290 if( iCurrentOp != EBonding ) |
|
291 { |
|
292 iCurrentOp = EPairing; |
|
293 } |
|
294 iPairingHelper->StartPairingNotifierL( uid, aParams ); |
|
295 } |
|
296 // We may be done with the current request, proceed to the next one |
|
297 CheckNextOperationL(); |
|
298 } |
|
299 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
300 } |
|
301 |
|
302 |
|
303 // --------------------------------------------------------------------------- |
|
304 // Update a notifier, update the outstanding dialog if the notifier request |
|
305 // is currently being served. |
|
306 // --------------------------------------------------------------------------- |
|
307 // |
|
308 void CBTNotifConnection::HandleNotifierUpdateL( const TDesC8& aParams, |
|
309 const RMessage2& aMessage ) |
|
310 { |
|
311 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
312 NOTIF_NOTHANDLED( iCurrentOp != EIdle ) |
|
313 (void) aParams; |
|
314 TBuf8<0x250> paramsBuf; // Size needs to be long enough to read all possible sizes. |
|
315 aMessage.ReadL( EBTNotifSrvParamSlot, paramsBuf ); |
|
316 TInt uid = aMessage.Int0(); |
|
317 if( uid == KBTManAuthNotifierUid.iUid ) |
|
318 { |
|
319 TBTNotifierUpdateParams params; |
|
320 TPckgC<TBTNotifierUpdateParams> paramsPckg( params ); |
|
321 paramsPckg.Set( paramsBuf ); |
|
322 // The result means result of conversion to unicode |
|
323 if( !paramsPckg().iResult ) |
|
324 { |
|
325 // Only update locally, registry will update us with the same info later on. |
|
326 iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( paramsPckg().iName ) ); |
|
327 if( iNotification ) |
|
328 { |
|
329 // Update the dialog with the new name. It is up to the dialog to |
|
330 // determine the validity (in case another dialog is shown). |
|
331 //iNotification->Update( ) |
|
332 } |
|
333 } |
|
334 } |
|
335 else if( iPairingHelper && ( uid == KBTPinCodeEntryNotifierUid.iUid || |
|
336 uid == KBTNumericComparisonNotifierUid.iUid || |
|
337 uid == KBTPasskeyDisplayNotifierUid.iUid ) ) |
|
338 { |
|
339 // Just forward to pairing helper |
|
340 iPairingHelper->UpdatePairingNotifierL( uid, paramsBuf ); |
|
341 } |
|
342 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
343 } |
|
344 |
|
345 |
|
346 // --------------------------------------------------------------------------- |
|
347 // Cancel a request, dismiss the outstanding dialog if the notifier request |
|
348 // is currently being served. |
|
349 // --------------------------------------------------------------------------- |
|
350 // |
|
351 void CBTNotifConnection::CancelNotifierRequestL( const RMessage2& aMessage ) |
|
352 { |
|
353 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
354 NOTIF_NOTHANDLED( iCurrentOp != EIdle ) |
|
355 TInt pos = iMsgHandleQ.Find( aMessage.Handle() ); |
|
356 if( pos > KErrNotFound ) |
|
357 { |
|
358 // We have queued the message, remove it from the queue. |
|
359 iMsgHandleQ.Remove( pos ); |
|
360 // We use the supplied handle to remove it, as it may not be |
|
361 // the first in the queue. |
|
362 TInt err = iTracker->Server()->CompleteMessage( aMessage.Handle(), KErrCancel, KNullDesC8 ); |
|
363 NOTIF_NOTHANDLED( !err ) |
|
364 if( pos == 0 ) |
|
365 { |
|
366 // There could be the case that we are still post-processing |
|
367 // the previous request (e.g. blocking query), then the next |
|
368 // notification is not yet started but the first in the queue. |
|
369 // We can see that from the current operation type. |
|
370 if( iNotification && iCurrentOp < EAdditionalNotes ) |
|
371 { |
|
372 // Cancel the user query |
|
373 // This will also unregister us from the notification. |
|
374 TInt err = iNotification->Close(); |
|
375 NOTIF_NOTHANDLED( !err ) |
|
376 iNotification = NULL; |
|
377 iCurrentOp = EIdle; |
|
378 } |
|
379 if( iPairingHelper ) |
|
380 { |
|
381 // The pairing helper calls back PairingCompleted and sets state. |
|
382 iPairingHelper->CancelPairingNotifierL( aMessage.Int0() ); |
|
383 // The pairing helper may have now been deleted. |
|
384 } |
|
385 } |
|
386 } |
|
387 // We may be done with the current request, proceed to the next one |
|
388 CheckNextOperationL(); |
|
389 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
390 } |
|
391 |
|
392 |
|
393 // --------------------------------------------------------------------------- |
|
394 // Start a bonding operation with the remote device. |
|
395 // --------------------------------------------------------------------------- |
|
396 // |
|
397 void CBTNotifConnection::StartBondingL( const RMessage2& aMessage ) |
|
398 { |
|
399 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aMessage.Function() ); |
|
400 if( iCurrentOp == EIdle || iCurrentOp > EInternalOperations ) |
|
401 { |
|
402 __ASSERT_ALWAYS( !iPairingHelper, PanicServer( EBTNotifPanicBadState ) ); |
|
403 iPairingHelper = CBTNotifPairingHelper::NewL( this, iTracker ); |
|
404 // The pairingg helper stored the handle, not in our queue here. |
|
405 // This is because bonding will generate a pairing notifier request, which |
|
406 // will be completed first. The bookkeeping gets complicated if we have to |
|
407 // re-order the queue here. |
|
408 iPairingHelper->StartBondingL( aMessage.Handle() ); |
|
409 iCurrentOp = EBonding; |
|
410 } |
|
411 else if( iCurrentOp == EPairing || iCurrentOp == EBonding ) |
|
412 { |
|
413 // We only do one pairing at the time. |
|
414 User::Leave( KErrInUse ); |
|
415 } |
|
416 else |
|
417 { |
|
418 // We only store it here if it is not handled immediately. |
|
419 iMsgHandleQ.AppendL( aMessage.Handle() ); |
|
420 } |
|
421 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
422 } |
|
423 |
|
424 |
|
425 // --------------------------------------------------------------------------- |
|
426 // Cancel an ongoing bonding operation with the remote device. |
|
427 // --------------------------------------------------------------------------- |
|
428 // |
|
429 void CBTNotifConnection::CancelBondingL() |
|
430 { |
|
431 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
432 if( iPairingHelper ) |
|
433 { |
|
434 iPairingHelper->CancelBondingL(); |
|
435 } |
|
436 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
437 } |
|
438 |
|
439 |
|
440 // --------------------------------------------------------------------------- |
|
441 // The pairing handler has completed a pairing operation. |
|
442 // --------------------------------------------------------------------------- |
|
443 // |
|
444 void CBTNotifConnection::PairingCompleted() |
|
445 { |
|
446 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
447 __ASSERT_ALWAYS( iPairingHelper, PanicServer( EBTNotifPanicNullMember ) ); |
|
448 if( iPairingHelper->CurrentOperation() == CBTNotifPairingHelper::EIdle ) |
|
449 { |
|
450 // We are still idle. Remove the pairing helper |
|
451 delete iPairingHelper; |
|
452 iPairingHelper = NULL; |
|
453 } |
|
454 if( iCurrentOp == EPairing || iCurrentOp == EBonding ) |
|
455 { |
|
456 iCurrentOp = EIdle; |
|
457 TRAP_IGNORE( CheckNextOperationL() ); |
|
458 } |
|
459 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
460 } |
|
461 |
|
462 |
|
463 // --------------------------------------------------------------------------- |
|
464 // Process a new pairing result, and determine if we need to show |
|
465 // anything to the user. |
|
466 // --------------------------------------------------------------------------- |
|
467 // |
|
468 void CBTNotifConnection::PairingResult( TInt aError ) |
|
469 { |
|
470 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
471 if( !iPairingHelper ) |
|
472 { |
|
473 TRAP_IGNORE( iPairingHelper = CBTNotifPairingHelper::NewL( this, iTracker ) ); |
|
474 } |
|
475 if( iPairingHelper ) |
|
476 { |
|
477 iPairingHelper->HandleAuthenticationCompleteL( aError ); |
|
478 } |
|
479 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
480 } |
|
481 |
|
482 |
|
483 // --------------------------------------------------------------------------- |
|
484 // Process the new service-level connection, and determine if we need to |
|
485 // show anything to the user. |
|
486 // --------------------------------------------------------------------------- |
|
487 // |
|
488 void CBTNotifConnection::ServiceConnectedL( TBTProfile aProfile ) |
|
489 { |
|
490 (void) aProfile; |
|
491 } |
|
492 |
|
493 |
|
494 // --------------------------------------------------------------------------- |
|
495 // Process the new service-level disconnection, and determine if we need to |
|
496 // show anything to the user. |
|
497 // --------------------------------------------------------------------------- |
|
498 // |
|
499 void CBTNotifConnection::ServiceDisconnectedL( TBTProfile aProfile ) |
|
500 { |
|
501 (void) aProfile; |
|
502 } |
|
503 |
|
504 |
|
505 // --------------------------------------------------------------------------- |
|
506 // Ask the user if he/she wants to block future connection requests. |
|
507 // --------------------------------------------------------------------------- |
|
508 // |
|
509 void CBTNotifConnection::LaunchBlockingQueryL() |
|
510 { |
|
511 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
512 iCurrentOp = EBlocking; |
|
513 TBTDialogResourceId resourceId = EBlockUnpairedDevice; |
|
514 if( iDevice->IsValidPaired() && iDevice->IsPaired() && |
|
515 iDevice->LinkKeyType() != ELinkKeyUnauthenticatedUpgradable ) |
|
516 { |
|
517 resourceId = EBlockPairedDevice; |
|
518 } |
|
519 PrepareNotificationL( TBluetoothDialogParams::EQuery, resourceId ); |
|
520 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
521 } |
|
522 |
|
523 |
|
524 // --------------------------------------------------------------------------- |
|
525 // Modify the record for the remote device in BTRegistry, with the changes |
|
526 // already made in the local record. |
|
527 // --------------------------------------------------------------------------- |
|
528 // |
|
529 void CBTNotifConnection::UpdateRegistryEntryL() |
|
530 { |
|
531 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
532 // We use CBTEngDevMan here. We could use the registry API directly, however, |
|
533 // using this convenience API makes the registry processing much simpler. |
|
534 if( !iDevMan ) |
|
535 { |
|
536 iDevMan = CBTEngDevMan::NewL( this ); |
|
537 } |
|
538 iDevMan->ModifyDevice( *iDevice ); |
|
539 if( iCurrentOp == EIdle || |
|
540 ( ( iCurrentOp == EPairing || iCurrentOp == EBonding ) && |
|
541 iPairingHelper->CurrentOperation() == CBTNotifPairingHelper::EIdle ) ) |
|
542 { |
|
543 // To make sure that we don't get deleted while updating. |
|
544 iCurrentOp = EUpdatingRegistry; |
|
545 } |
|
546 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
547 } |
|
548 |
|
549 // --------------------------------------------------------------------------- |
|
550 // Modify the record for the remote device in BTRegistry, if aTrusted == true, then |
|
551 // update trusted status after reading device info from registry |
|
552 // |
|
553 // --------------------------------------------------------------------------- |
|
554 |
|
555 void CBTNotifConnection::UpdateRegistryEntryL( TBool aTrusted ) |
|
556 { |
|
557 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aTrusted ); |
|
558 if (!aTrusted) { |
|
559 UpdateRegistryEntryL(); |
|
560 return; |
|
561 } |
|
562 // We use CBTEngDevMan here. We could use the registry API directly, however, |
|
563 // using this convenience API makes the registry processing much simpler. |
|
564 if( !iDevMan ) |
|
565 { |
|
566 iDevMan = CBTEngDevMan::NewL( this ); |
|
567 } |
|
568 // first read device info from registry, to make sure we have up-to-date local info |
|
569 iCurrentOp = EReadingRegistry; |
|
570 GetDeviceFromRegistry( iDevice->BDAddr() ); |
|
571 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
572 } |
|
573 |
|
574 // --------------------------------------------------------------------------- |
|
575 // From class MBTNotificationResult. |
|
576 // Handle a result from a user query. |
|
577 // --------------------------------------------------------------------------- |
|
578 // |
|
579 void CBTNotifConnection::MBRDataReceived( CHbSymbianVariantMap & aData ) |
|
580 { |
|
581 (void) aData; |
|
582 NOTIF_NOTIMPL |
|
583 } |
|
584 |
|
585 |
|
586 // --------------------------------------------------------------------------- |
|
587 // From class MBTNotificationResult. |
|
588 // The notification is finished. |
|
589 // --------------------------------------------------------------------------- |
|
590 // |
|
591 void CBTNotifConnection::MBRNotificationClosed( TInt aError, const TDesC8& aData ) |
|
592 { |
|
593 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
594 // ToDo: call leaving function from here! |
|
595 __ASSERT_ALWAYS( iCurrentOp != EIdle, PanicServer( EBTNotifPanicBadState ) ); |
|
596 // First unregister from the notification, so we can already get the next one. |
|
597 iNotification->RemoveObserver(); |
|
598 iNotification = NULL; |
|
599 TRAP_IGNORE( NotificationClosedL( aError, aData ) ); |
|
600 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
601 } |
|
602 |
|
603 |
|
604 // --------------------------------------------------------------------------- |
|
605 // From class MBtSimpleActiveObserver. |
|
606 // Handle the active object completion. |
|
607 // --------------------------------------------------------------------------- |
|
608 // |
|
609 void CBTNotifConnection::RequestCompletedL( CBtSimpleActive* aActive, |
|
610 TInt aStatus ) |
|
611 { |
|
612 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aActive->RequestId() ); |
|
613 switch( aActive->RequestId() ) |
|
614 { |
|
615 case KRegistryRetriever: |
|
616 { |
|
617 BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, |
|
618 "[BTNOTIF]\t CBTNotifConnection::MBAORequestCompletedL: KRegistryRetriever" ); |
|
619 if( !iRegistryResponse ) |
|
620 { |
|
621 // We have just created the view, now get the results. |
|
622 // There can only be one result, as the address is unique. |
|
623 // (note: how about LE random addresses?) |
|
624 // Or then we have tried to re-open an existing view, so we get KErrInuse. |
|
625 // We anyway just get the results. |
|
626 __ASSERT_ALWAYS( aStatus < 2, PanicServer( EBTNotifPanicCorrupt ) ); |
|
627 iRegistryResponse = CBTRegistryResponse::NewL( iRegistry ); |
|
628 iRegistryResponse->Start( iRegActive->RequestStatus() ); |
|
629 iRegActive->GoActive(); |
|
630 } |
|
631 else |
|
632 { |
|
633 if( !aStatus ) |
|
634 { |
|
635 // There can be only one result. |
|
636 __ASSERT_ALWAYS( iRegistryResponse->Results().Count() == 1, PanicServer( EBTNotifPanicCorrupt ) ); |
|
637 CBTDevice* regDevice = iRegistryResponse->Results()[0]; |
|
638 TBool paired = CheckRegistryPairedStatus( iDevice, regDevice ); |
|
639 iDevice->UpdateL( *regDevice ); |
|
640 if( paired ) |
|
641 { |
|
642 __ASSERT_ALWAYS( iPairingHelper, PanicServer( EBTNotifPanicNullMember ) ); |
|
643 iPairingHelper->HandleAuthenticationCompleteL( KErrNone ); |
|
644 } |
|
645 } |
|
646 // ToDo: error handling of registry response result? |
|
647 delete iRegistryResponse; |
|
648 iRegistryResponse = NULL; |
|
649 } |
|
650 if( iCurrentOp == EReadingRegistry && !iRegActive->IsActive() ) |
|
651 { |
|
652 // If this is part of the sequence of operations, we are done. |
|
653 // Otherwise we just update with the latest info from registry, |
|
654 // and then we don't interrupt or change the state. |
|
655 iCurrentOp = EIdle; |
|
656 } |
|
657 } |
|
658 // ToDo: start registry watching (preferably using registry API when this is available) |
|
659 break; |
|
660 case KRegistryWatcher: |
|
661 { |
|
662 BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, |
|
663 "[BTNOTIF]\t CBTNotifConnection::MBAORequestCompletedL: KRegistryWatcher" ); |
|
664 NOTIF_NOTHANDLED( !aStatus ) |
|
665 // Ignore updates while we are already retrieving. |
|
666 if( !iRegActive->IsActive() ) |
|
667 { |
|
668 // Refresh our information with the latest from registry |
|
669 iRegActive->SetRequestId( KRegistryRetriever ); |
|
670 TBTRegistrySearch pattern; |
|
671 pattern.FindAddress( iAddr ); |
|
672 iRegistry.CreateView( pattern, iRegActive->RequestStatus() ); |
|
673 iRegActive->GoActive(); |
|
674 } |
|
675 } |
|
676 break; |
|
677 case KConnectionWatcher: |
|
678 { |
|
679 BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, |
|
680 "[BTNOTIF]\t CBTNotifConnection::MBAORequestCompletedL: KConnectionWatcher" ); |
|
681 TUint32 event = iBasebandEvent().EventType(); |
|
682 // First subscribe to the next event notification. |
|
683 // This will overwrite iBasebandEvent().EventType() with KBbEventMask |
|
684 iPhyLink.NotifyNextBasebandChangeEvent( iBasebandEvent, |
|
685 iPhyActive->RequestStatus(), KBbEventMask ); |
|
686 iPhyActive->GoActive(); |
|
687 // Link down and link error are handled in CheckNextOperationL below. |
|
688 // ToDo: handle events! |
|
689 if( event & ( ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError ) ) |
|
690 { |
|
691 // We re-use the error code to store the indication that the |
|
692 // link has disconnected. This will only be overridden by next |
|
693 // event, which can only be a connection up event. |
|
694 iBasebandEvent().SetErrorCode( KErrDisconnected ); |
|
695 } |
|
696 if( iPairingHelper ) |
|
697 { |
|
698 if( event & ( ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError | |
|
699 ENotifyAuthenticationComplete ) ) |
|
700 { |
|
701 // Results interesting for pairing result processing. |
|
702 iPairingHelper->HandleAuthenticationCompleteL( iBasebandEvent().SymbianErrorCode() ); |
|
703 } |
|
704 else if( event & ENotifyPhysicalLinkUp && |
|
705 iPairingHelper->CurrentOperation() == CBTNotifPairingHelper::EDedicatedBonding ) |
|
706 { |
|
707 iPairingHelper->StartBondingL( 0 ); |
|
708 } |
|
709 } |
|
710 } |
|
711 break; |
|
712 default: |
|
713 PanicServer( EBTNotifPanicBadState ); |
|
714 break; |
|
715 } |
|
716 // We may be done with the current request, proceed to the next one |
|
717 CheckNextOperationL(); |
|
718 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
719 } |
|
720 |
|
721 |
|
722 // --------------------------------------------------------------------------- |
|
723 // From class MBtSimpleActiveObserver. |
|
724 // Cancel and clean up all requests related to the active object. |
|
725 // --------------------------------------------------------------------------- |
|
726 // |
|
727 void CBTNotifConnection::CancelRequest( TInt aRequestId ) |
|
728 { |
|
729 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
730 if ( aRequestId == KConnectionWatcher ) |
|
731 { |
|
732 iPhyLink.CancelNextBasebandChangeEventNotifier(); |
|
733 } |
|
734 else if ( aRequestId == KRegistryWatcher && iRegistryResponse ) |
|
735 { |
|
736 iRegistryResponse->Cancel(); |
|
737 } |
|
738 else if ( aRequestId == KRegistryRetriever ) |
|
739 { |
|
740 iRegistry.CancelRequest( iRegActive->RequestStatus()); |
|
741 } |
|
742 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
743 } |
|
744 |
|
745 // --------------------------------------------------------------------------- |
|
746 // From class MBtSimpleActiveObserver. |
|
747 // |
|
748 // --------------------------------------------------------------------------- |
|
749 // |
|
750 void CBTNotifConnection::HandleError( CBtSimpleActive* aActive, |
|
751 TInt aError ) |
|
752 { |
|
753 (void) aActive; |
|
754 (void) aError; |
|
755 } |
|
756 |
|
757 // --------------------------------------------------------------------------- |
|
758 // From class MBTEngDevmanObserver. |
|
759 // Registry modification has completed. |
|
760 // --------------------------------------------------------------------------- |
|
761 // |
|
762 void CBTNotifConnection::HandleDevManComplete( TInt aErr ) |
|
763 { |
|
764 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
765 (void) aErr; |
|
766 NOTIF_NOTHANDLED( !aErr ) |
|
767 if( iCurrentOp == EUpdatingRegistry ) |
|
768 { |
|
769 // To make sure that we don't get deleted while updating. |
|
770 iCurrentOp = EIdle; |
|
771 } |
|
772 // Refresh is done separately, we will get notified through |
|
773 // the registry watcher of the change. |
|
774 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
775 } |
|
776 |
|
777 |
|
778 // --------------------------------------------------------------------------- |
|
779 // From class MBTEngDevmanObserver. |
|
780 // Callback for getting a device from the registry |
|
781 // |
|
782 // Currently only used in context of setting device to trusted |
|
783 // --------------------------------------------------------------------------- |
|
784 // |
|
785 void CBTNotifConnection::HandleGetDevicesComplete( |
|
786 TInt err, CBTDeviceArray* deviceArray ) |
|
787 { |
|
788 BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, err ); |
|
789 // err is not used here very much, -1 could be returned if there is no device in registry, |
|
790 // but this case is covered by examing mRegDevArray. |
|
791 if (!err && (iCurrentOp == EReadingRegistry) ) { |
|
792 CBTDevice* dev (0); |
|
793 if ( deviceArray->Count() ) { |
|
794 dev = deviceArray->At( 0 ); |
|
795 } |
|
796 if ( dev ) { |
|
797 iDevice = dev->CopyL(); |
|
798 } |
|
799 // Set device to trusted |
|
800 // Copy the existing security settings. |
|
801 TBTDeviceSecurity sec( iDevice->GlobalSecurity().SecurityValue(), |
|
802 iDevice->GlobalSecurity().PasskeyMinLength() ); |
|
803 sec.SetNoAuthorise( ETrue ); // new value: set device as trusted |
|
804 iDevice->SetGlobalSecurity( sec ); |
|
805 iDevMan->ModifyDevice( *iDevice ); // write trusted (& paired) status to registry |
|
806 // To make sure that we don't get deleted while updating. |
|
807 iCurrentOp = EUpdatingRegistry; |
|
808 } |
|
809 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
810 } |
|
811 |
|
812 // --------------------------------------------------------------------------- |
|
813 // Retrieves device from registry based on BT address parameter |
|
814 // --------------------------------------------------------------------------- |
|
815 // |
|
816 void CBTNotifConnection::GetDeviceFromRegistry( const TBTDevAddr &addr ) |
|
817 { |
|
818 BOstraceFunctionEntry1( DUMMY_DEVLIST, this ); |
|
819 TBTRegistrySearch searchPattern; |
|
820 searchPattern.FindAddress( addr ); |
|
821 // and get this device from registry |
|
822 iRegDevArray->ResetAndDestroy(); |
|
823 iDevMan->GetDevices(searchPattern, iRegDevArray); |
|
824 BOstraceFunctionExit1( DUMMY_DEVLIST, this ); |
|
825 } |
|
826 |
|
827 // --------------------------------------------------------------------------- |
|
828 // Get and configure a notification. |
|
829 // --------------------------------------------------------------------------- |
|
830 // |
|
831 void CBTNotifConnection::PrepareNotificationL( TBluetoothDialogParams::TBTDialogType aType, |
|
832 TBTDialogResourceId aResourceId ) |
|
833 { |
|
834 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
835 iNotification = iTracker->NotificationManager()->GetNotification(); |
|
836 User::LeaveIfNull( iNotification ); // For OOM exception, leaves with KErrNoMemory |
|
837 iNotification->SetObserver( this ); |
|
838 iNotification->SetNotificationType( aType, aResourceId ); |
|
839 // Set the address of the remote device |
|
840 TBuf<KBTDevAddrSize> addr; |
|
841 addr.Copy( iAddr.Des() ); |
|
842 TInt err = iNotification->SetData( TBluetoothDialogParams::EAddress, addr ); |
|
843 NOTIF_NOTHANDLED( !err ) |
|
844 // Set the name of the remote device |
|
845 TBTDeviceName name; |
|
846 GetDeviceNameL( name, *iDevice ); |
|
847 // ToDo: handle leave in name conversion! |
|
848 err = iNotification->SetData( (TInt) TBluetoothDeviceDialog::EDeviceName, name ); |
|
849 NOTIF_NOTHANDLED( !err ) |
|
850 // Queue the notification for displaying to the user |
|
851 err = iTracker->NotificationManager()->QueueNotification( iNotification ); |
|
852 NOTIF_NOTHANDLED( !err ) |
|
853 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
854 } |
|
855 |
|
856 |
|
857 // --------------------------------------------------------------------------- |
|
858 // The notification is finished, handle the result. |
|
859 // --------------------------------------------------------------------------- |
|
860 // |
|
861 void CBTNotifConnection::NotificationClosedL( TInt aError, const TDesC8& aData ) |
|
862 { |
|
863 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
864 switch( iCurrentOp ) |
|
865 { |
|
866 case EAuthorizing: |
|
867 CompleteAuthorizationReqL( aError, aData ); |
|
868 break; |
|
869 case EBlocking: |
|
870 CompleteBlockingReqL( aError, aData ); |
|
871 break; |
|
872 default: |
|
873 NOTIF_NOTIMPL |
|
874 break; |
|
875 } |
|
876 // We may be done with the current request, proceed to the next one |
|
877 CheckNextOperationL(); |
|
878 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
879 } |
|
880 |
|
881 |
|
882 // --------------------------------------------------------------------------- |
|
883 // Handle a request for authorization of this connection. |
|
884 // --------------------------------------------------------------------------- |
|
885 // |
|
886 void CBTNotifConnection::HandleAuthorizationReqL( const TDesC8& aParams ) |
|
887 { |
|
888 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
889 __ASSERT_ALWAYS( iCurrentOp == EIdle, PanicServer( EBTNotifPanicBadState ) ); |
|
890 __ASSERT_ALWAYS( !iNotification, PanicServer( EBTNotifPanicCorrupt ) ); |
|
891 TBTAuthorisationParams params; |
|
892 TPckgC<TBTAuthorisationParams> paramsPckg( params ); |
|
893 paramsPckg.Set( aParams ); |
|
894 iCurrentOp = EAuthorizing; |
|
895 // The name in the parameter package is the latest one, retrieved from |
|
896 // the remote device during this connection. |
|
897 if( paramsPckg().iName.Length() ) |
|
898 { |
|
899 // Update the local device record. No need to update the registry, |
|
900 // that will be done by the stack, and we will receive the update |
|
901 // information when that has completed. |
|
902 iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( paramsPckg().iName ) ); |
|
903 } |
|
904 PrepareNotificationL( TBluetoothDialogParams::EQuery, EAuthorization ); |
|
905 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
906 } |
|
907 |
|
908 |
|
909 // --------------------------------------------------------------------------- |
|
910 // Process the user input and complete the outstanding authorization request. |
|
911 // --------------------------------------------------------------------------- |
|
912 // |
|
913 void CBTNotifConnection::CompleteAuthorizationReqL( TInt aError, const TDesC8& aData ) |
|
914 { |
|
915 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
916 // Set our state to idle for now. This may get changed if the user just chose |
|
917 // to block, or if we have a pending request. |
|
918 iCurrentOp = EIdle; |
|
919 if( !aError ) |
|
920 { |
|
921 TPckgC<TBool> result( EFalse ); |
|
922 result.Set( aData ); |
|
923 TBool proceed = iTracker->UpdateBlockingHistoryL( iDevice, result() ); |
|
924 if( result() == EFalse && proceed ) |
|
925 { |
|
926 // The user denied the connection, ask to block the device. |
|
927 LaunchBlockingQueryL(); |
|
928 } |
|
929 CompleteClientRequest( KErrNone, aData ); |
|
930 } |
|
931 else |
|
932 { |
|
933 CompleteClientRequest( aError, KNullDesC8 ); |
|
934 } |
|
935 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
936 } |
|
937 |
|
938 |
|
939 // --------------------------------------------------------------------------- |
|
940 // Process the user input for blocking a device. |
|
941 // --------------------------------------------------------------------------- |
|
942 // |
|
943 void CBTNotifConnection::CompleteBlockingReqL( TInt aError, const TDesC8& aData ) |
|
944 { |
|
945 BOstraceFunctionEntry0( DUMMY_DEVLIST ); |
|
946 TPckgC<TBool> result( EFalse ); |
|
947 result.Set( KNullDesC8 ); // to test! |
|
948 result.Set( aData ); |
|
949 iCurrentOp = EIdle; // May get changed if we have a pending request. |
|
950 if( !aError && result() ) |
|
951 { |
|
952 // The user accepted to block this device. |
|
953 TBTDeviceSecurity sec; // use default values when setting as banned. |
|
954 sec.SetBanned( ETrue ); |
|
955 iDevice->SetGlobalSecurity( sec ); |
|
956 if( iDevice->IsValidPaired() && iDevice->IsPaired() ) |
|
957 { |
|
958 // Deleting the link key will also set the device as unpaired. |
|
959 iDevice->DeleteLinkKey(); |
|
960 } |
|
961 UpdateRegistryEntryL(); |
|
962 } |
|
963 BOstraceFunctionExit0( DUMMY_DEVLIST ); |
|
964 } |