|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implementation of physical links |
|
15 // |
|
16 // |
|
17 |
|
18 #include <bluetooth/logger.h> |
|
19 #include "physicallinksmanager.h" |
|
20 #include "physicallinks.h" |
|
21 #include "AclDataQController.h" |
|
22 #include "ACLSAP.h" |
|
23 #include "SCOSAP.h" |
|
24 #include "ProxySAP.h" |
|
25 #include "linkconsts.h" |
|
26 #include "hcifacade.h" |
|
27 #include "hostresolver.h" |
|
28 #include "PhysicalLinkHelper.h" |
|
29 #include "pairingscache.h" |
|
30 #include "oobdata.h" |
|
31 #include "pairingserver.h" |
|
32 |
|
33 #include <bt_sock.h> |
|
34 |
|
35 #include <bluetooth/hci/commandstatusevent.h> |
|
36 #include <bluetooth/hci/sniffmodecommand.h> |
|
37 #include <bluetooth/hci/exitsniffmodecommand.h> |
|
38 #include <bluetooth/hci/holdmodecommand.h> |
|
39 #include <bluetooth/hci/parkmodecommand.h> |
|
40 #include <bluetooth/hci/exitparkmodecommand.h> |
|
41 #include <bluetooth/hci/modechangeevent.h> |
|
42 #include <bluetooth/hci/disconnectcommand.h> |
|
43 #include <bluetooth/hci/disconnectioncompleteevent.h> |
|
44 #include <bluetooth/hci/hciconsts.h> |
|
45 |
|
46 #include <bluetooth/hci/linkkeyrequestreplycommand.h> |
|
47 #include <bluetooth/hci/linkkeyrequestreplynegativecommand.h> |
|
48 #include <btextnotifierspartner.h> |
|
49 |
|
50 #ifdef __FLOG_ACTIVE |
|
51 _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR); |
|
52 #endif |
|
53 |
|
54 #ifdef _DEBUG |
|
55 PANICCATEGORY("plink"); |
|
56 #endif |
|
57 |
|
58 static const THCIErrorCode KDefaultRejectReason = EHostSecurityRejection; // see spec Error Codes |
|
59 |
|
60 #ifdef _DEBUG |
|
61 #define __CHECK_CONNECTION_HANDLE(aHandle) __ASSERT_DEBUG(aHandle==iHandle, Panic(EBTLinkMgrConnectionEventInWrongSAP)); |
|
62 #else |
|
63 #define __CHECK_CONNECTION_HANDLE(aHandle) aHandle=aHandle; // to suppress warnings |
|
64 #endif |
|
65 |
|
66 CPhysicalLink* CPhysicalLink::NewLC(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice) |
|
67 { |
|
68 LOG_STATIC_FUNC |
|
69 CPhysicalLink* s = new(ELeave) CPhysicalLink(aConnectionMan, aRegSess, aDevice); |
|
70 CleanupStack::PushL(s); |
|
71 s->ConstructL(); |
|
72 return s; |
|
73 } |
|
74 |
|
75 CPhysicalLink* CPhysicalLink::NewL(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice) |
|
76 { |
|
77 LOG_STATIC_FUNC |
|
78 CPhysicalLink* s = NewLC(aConnectionMan, aRegSess, aDevice); |
|
79 CleanupStack::Pop(s); |
|
80 return s; |
|
81 } |
|
82 |
|
83 CPhysicalLink::CPhysicalLink(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice) |
|
84 : iLinksMan(aConnectionMan) |
|
85 , iRegSess(aRegSess) |
|
86 , iDevice(aDevice) |
|
87 , iHandle(KHCIBroadcastHandle) |
|
88 , iRemoteFeatures(KInvalidRemoteFeatures) |
|
89 , iDeviceResult(KDeviceNotObtained) |
|
90 , iRegistryHelpers(_FOFF(CBTRegistryHelperBase,iLink)) |
|
91 , iProxySAPs(_FOFF(CBTProxySAP, iQueueLink)) |
|
92 , iOverrideParkRequests(EFalse) |
|
93 , iOverrideLPMRequests(EFalse) |
|
94 , iLPMOverrideTimerQueued(EFalse) |
|
95 , iConnectionPacketTypeChanged(EFalse) |
|
96 , iLowPowModeCtrl(*this, iLinksMan.HCIFacade().CommandQController()) |
|
97 , iDisconnectCtrl(*this, iLinksMan.HCIFacade().CommandQController()) |
|
98 , iAuthenticationCtrl(*this, iLinksMan.HCIFacade().CommandQController()) |
|
99 , iLSTO(0) |
|
100 , iAutoKeyRefreshQue(_FOFF(XAutoKeyRefreshToken, iQueLink)) |
|
101 , iRemoteDeviceRecordedByStack(ENull) |
|
102 { |
|
103 LOG_FUNC |
|
104 // don't initialise physical link policy just yet - wait until connection completes |
|
105 // by then we'll have best information to go on |
|
106 LOG1(_L("New CPhysicalLink [0x%08x]"), this); |
|
107 } |
|
108 |
|
109 CPhysicalLink::~CPhysicalLink() |
|
110 { |
|
111 LOG_FUNC |
|
112 __ASSERT_DEBUG(iACLLogicalLinks.Count()==0, Panic(EBTACLLogicalLinkBadDebind)); |
|
113 __ASSERT_DEBUG(iSyncLogicalLink == NULL, Panic(EBTSCOLogicalLinkBadDebind)); |
|
114 |
|
115 LOG1(_L("CPhysicalLink Destructing this = 0x%08x"), this); |
|
116 |
|
117 // tell ConnectionsManager... |
|
118 iLinksMan.RemovePhysicalLink(*this); |
|
119 iACLLogicalLinks.Close(); |
|
120 |
|
121 RemoveIdleTimer(); |
|
122 if (iLPMOverrideTimerQueued) |
|
123 { |
|
124 BTSocketTimer::Remove(iOverrideLPMTimerEntry); |
|
125 iLPMOverrideTimerQueued = EFalse; |
|
126 } |
|
127 |
|
128 LOG(_L("sec\tClosing subscribers...")) |
|
129 |
|
130 LOG(_L("sec\tClosing helpers...")) |
|
131 TSglQueIter<CBTRegistryHelperBase> iter(iRegistryHelpers); |
|
132 CBTRegistryHelperBase* helper; |
|
133 // Detach from any Registry Helpers for which this object |
|
134 // is the parent. |
|
135 while(iter) |
|
136 { |
|
137 helper = iter++; |
|
138 helper->DetachParent(); |
|
139 } |
|
140 |
|
141 iLowPowModeCtrl.Abort(); |
|
142 iDisconnectCtrl.Abort(); |
|
143 iAuthenticationCtrl.Abort(); |
|
144 |
|
145 delete iPhysicalLinkMetrics; |
|
146 delete iPinRequester; |
|
147 delete iNumericComparator; |
|
148 delete iPasskeyEntry; |
|
149 delete iArbitrationDelay; |
|
150 delete iRoleSwitchCompleteCallBack; |
|
151 delete iEncryptionEnforcer; |
|
152 |
|
153 DeleteRoleSwitcher(); |
|
154 } |
|
155 |
|
156 void CPhysicalLink::ConstructL() |
|
157 { |
|
158 LOG_FUNC |
|
159 LOG1(_L("CPhysicalLink::ConstructL() this = 0x%08x"), this); |
|
160 GetDeviceFromRegistryL(); |
|
161 iArbitrationDelay = CArbitrationDelayTimer::NewL(this); |
|
162 |
|
163 TCallBack cb1(RoleSwitchCompleteCallBack, this); |
|
164 iRoleSwitchCompleteCallBack = new (ELeave)CAsyncCallBack(cb1, EActiveHighPriority); |
|
165 |
|
166 TCallBack cb2(OverrideLPMTimeoutCallback, this); |
|
167 iOverrideLPMTimerEntry.Set(cb2); |
|
168 |
|
169 iPhysicalLinkMetrics = CPhysicalLinkMetrics::NewL(*this, iLinksMan.HCIFacade().CommandQController()); |
|
170 } |
|
171 |
|
172 TBool CPhysicalLink::HasHandle(THCIConnHandle aHandle) const |
|
173 { |
|
174 LOG_FUNC |
|
175 if (iHandle == aHandle) |
|
176 return ETrue; // Only one ACL handle is available. |
|
177 if (iSyncLogicalLink && iSyncLogicalLink->Handle() == aHandle) |
|
178 return ETrue; |
|
179 return EFalse; |
|
180 } |
|
181 |
|
182 TBool CPhysicalLink::HasSyncLink() const |
|
183 { |
|
184 LOG_FUNC |
|
185 return (iSyncLogicalLink != NULL); |
|
186 } |
|
187 |
|
188 void CPhysicalLink::SubscribeLinkObserver(MPhysicalLinkObserver& aObserver) |
|
189 /** |
|
190 The subscribed object will be notified whenever a link state change occurs. |
|
191 **/ |
|
192 { |
|
193 LOG_FUNC |
|
194 #ifdef _DEBUG |
|
195 //ensure the subscriber isn't already subscribed... |
|
196 TInt found = 0; |
|
197 TDblQueIter<MPhysicalLinkObserver> iter(iBasebandSubscribers); |
|
198 while (iter) |
|
199 { |
|
200 if (iter++ == &aObserver) |
|
201 { |
|
202 found++; |
|
203 } |
|
204 } |
|
205 |
|
206 __ASSERT_DEBUG(found==0, Panic(ELinkMgrBadBasebandArray)); |
|
207 #endif //_DEBUG |
|
208 |
|
209 iBasebandSubscribers.AddFirst(aObserver.ObserverQLink()); |
|
210 } |
|
211 |
|
212 void CPhysicalLink::UnsubscribeLinkObserver(MPhysicalLinkObserver& aObserver) |
|
213 /** |
|
214 aSubscriber will no longer be notified of state changes. |
|
215 **/ |
|
216 { |
|
217 LOG_FUNC |
|
218 aObserver.ObserverQLink().Deque(); |
|
219 } |
|
220 |
|
221 TInt CPhysicalLink::TryToAndThenPreventHostEncryptionKeyRefresh(TAny* aOutToken) |
|
222 { |
|
223 LOG_FUNC |
|
224 TInt err = KErrNone; |
|
225 // The handling of the TAny* parameter seems a bit wacky - but it makes sense as follows |
|
226 // this call handles a call from the bluetooth control plane (which passes |
|
227 // only a TAny* as a parameter). We need to return a value back through as well, so we need |
|
228 // a pointer to a pointer (so after using the input it can be modified to point to the |
|
229 // output). We need a Bluetooth device address so a pointer to a pointer to a TBTDevAddr |
|
230 // is passed down. Then the pointer to a pointer is used to update the pointer to a control |
|
231 // plane token (which represents a handle preventing host encryption key refreshes). |
|
232 if (!IsEncryptionPauseResumeSupported()) |
|
233 { |
|
234 err = KErrNotSupported; |
|
235 *reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = NULL; |
|
236 } |
|
237 else |
|
238 { |
|
239 if (iAutoKeyRefreshQue.IsEmpty()) |
|
240 { |
|
241 TRAP_IGNORE(iLinksMan.HCIFacade().RefreshEncryptionKeyL(iHandle)); |
|
242 // If we can't refresh the encryption key, there's not much we can do |
|
243 } |
|
244 XAutoKeyRefreshToken* token = new XAutoKeyRefreshToken(); |
|
245 if (token) |
|
246 { |
|
247 iAutoKeyRefreshQue.AddLast(*token); |
|
248 } |
|
249 else |
|
250 { |
|
251 err = KErrNoMemory; |
|
252 } |
|
253 *reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = token; |
|
254 } |
|
255 return err; |
|
256 } |
|
257 |
|
258 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, TInt /*aResult*/) |
|
259 /** |
|
260 A task has completed where we don't expect a response - just cleanup helper |
|
261 **/ |
|
262 { |
|
263 LOG_FUNC |
|
264 // remove from array |
|
265 iRegistryHelpers.Remove(*aHelper); |
|
266 // delete |
|
267 delete aHelper; |
|
268 } |
|
269 |
|
270 /** |
|
271 The completion function of a registry helper returning a remote device entry. |
|
272 */ |
|
273 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, |
|
274 const TBTNamelessDevice& aDevice, |
|
275 TInt aResult) |
|
276 /** |
|
277 A registry task has completed where we expect a device to be returned |
|
278 **/ |
|
279 { |
|
280 LOG_FUNC |
|
281 LOG1(_L("CPhysicalLink: Registry task complete; result %d"), aResult); |
|
282 |
|
283 // The TBTNamelessDevice assignment operator only performs an update on valid |
|
284 // entries, as we need a bitwise copy (since we want to mirror what is in the registry) |
|
285 // we need to go to these extras steps. |
|
286 TPckg<TBTNamelessDevice> cachedVersion(iRegistryDevice); |
|
287 cachedVersion.Copy(TPckg<TBTNamelessDevice>(aDevice)); |
|
288 |
|
289 // We have to be careful about information flow from the registry to the actual representation (iDevice). |
|
290 // Although the values in the returned entry are useful if the stack has not yet got the information, |
|
291 // if the stack has already gathered values then they will be more up-to-date. Therefore we need to |
|
292 // assign the current values first if they are valid to build up the latest representation. |
|
293 TBTNamelessDevice device = aDevice; // Take a local copy to work on. |
|
294 if(iDevice.IsValidDeviceClass()) |
|
295 { |
|
296 device.SetDeviceClass(iDevice.DeviceClass()); |
|
297 } |
|
298 if(iDevice.IsValidPageScanRepMode()) |
|
299 { |
|
300 device.SetPageScanRepMode(iDevice.PageScanRepMode()); |
|
301 } |
|
302 if(iDevice.IsValidPageScanPeriodMode()) |
|
303 { |
|
304 device.SetPageScanPeriodMode(iDevice.PageScanPeriodMode()); |
|
305 } |
|
306 if(iDevice.IsValidPageScanMode()) |
|
307 { |
|
308 device.SetPageScanMode(iDevice.PageScanMode()); |
|
309 } |
|
310 if(iDevice.IsValidClockOffset()) |
|
311 { |
|
312 device.SetClockOffset(iDevice.ClockOffset()); |
|
313 } |
|
314 if(iDevice.IsValidUsed()) |
|
315 { |
|
316 device.SetUsed(iDevice.Used()); |
|
317 } |
|
318 if(iDevice.IsValidSeen()) |
|
319 { |
|
320 device.SetSeen(iDevice.Seen()); |
|
321 } |
|
322 |
|
323 // With the link key (and friends) we need to be even more careful, as there is effectively |
|
324 // two-way flow of information: |
|
325 // 1) Link key storage from the stack. |
|
326 // 2) Unbonding from the clients of the registry. |
|
327 // Further to this, if the registry entry does not have a link key, it can mean one of several |
|
328 // things: |
|
329 // a) No link key has been generated with the remote device yet. |
|
330 // b) A client of the registry has unbonded the remote device. |
|
331 // c) The current link key is not to form a bond. |
|
332 // Taking this into account we make a suitable choice about what to do. |
|
333 if(!iDevice.IsValidLinkKey()) |
|
334 { |
|
335 // If there isn't any link key in the system yet - and so it is safe to update the representation |
|
336 // to use the value from the registry. |
|
337 // <NOP> - see the global update below. |
|
338 } |
|
339 else |
|
340 { |
|
341 // We currently have a link key.... |
|
342 if(device.IsValidLinkKey() || iRegistryDevBeingMod.InUse()) |
|
343 { |
|
344 // Even if the linkkey in registry is valid, it must be older or same as the current |
|
345 // link key (as the stack is the only one who should be adding keys). Also, if we are in the |
|
346 // middle of updating the registry (for any purpose) then we can ignore the registry value as it |
|
347 // may not be up-to date. So, for both the cases just update with the latest. |
|
348 // There is an interesting case if client modifies the registry by unpairing/or deleting the device |
|
349 // and stack also tries to updates the link key in registry at the same time. We will give priority |
|
350 // to stack's updations by keeping the latest copy as it is. |
|
351 device.SetLinkKey(iDevice.LinkKey(), iDevice.LinkKeyType()); |
|
352 if(iDevice.IsValidPassKey()) |
|
353 { |
|
354 device.SetPassKey(iDevice.PassKey()); |
|
355 } |
|
356 } |
|
357 else |
|
358 { |
|
359 // This is the interesting case where a client has unbonded, but we already have a link |
|
360 // key. What we do here is interesting. |
|
361 if(IsAuthenticationPending() || LinkState().Authenticated() || SimplePairingMode() == EPhySimplePairingEnabled) |
|
362 |
|
363 { |
|
364 // If we're already authenticated / authenticating then we're already using our link |
|
365 // key. As such we need to continue using it, but we don't want to update |
|
366 // Also if the link is SSP enabled then we can re-authenticate - this removes any chance of a |
|
367 // race condition with the registry. |
|
368 iPreventLinkKeyUpdateReg = ETrue; // prevent locally cached link key being given back to the registry |
|
369 } |
|
370 else |
|
371 { |
|
372 // The link key hasn't been used yet - so we can update the representation to not |
|
373 // have a link key (as requested by the user). |
|
374 // Currently there is no chance of a race with the registry as combination link keys are |
|
375 // always form a bond. |
|
376 iDevice.DeleteLinkKey(); // delete locally cached link key |
|
377 } |
|
378 } |
|
379 } |
|
380 |
|
381 // Finally update the representation - we should have manipulated it correctly. |
|
382 iDevice = device; |
|
383 |
|
384 // Store the result of the retrieval for usage later. |
|
385 iDeviceResult = aResult; |
|
386 |
|
387 // the HW asked earlier for a link key - we can respond now |
|
388 __ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress)); |
|
389 if(iWaitingForLinkKeyFromRegistry) |
|
390 { |
|
391 if (aResult == KErrNone && iDevice.IsValidLinkKey()) |
|
392 { |
|
393 if ( iDevice.LinkKeyType() != ELinkKeyCombination) |
|
394 { |
|
395 if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) |
|
396 { |
|
397 LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) |
|
398 iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); |
|
399 } |
|
400 else |
|
401 if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) |
|
402 { |
|
403 LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) |
|
404 iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); |
|
405 } |
|
406 else |
|
407 { |
|
408 LOG(_L("CPhysicalLink: Issuing link key to HC now")) |
|
409 iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); |
|
410 } |
|
411 } |
|
412 else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled) |
|
413 { |
|
414 LOG(_L("CPhysicalLink: Issuing link key to HC now")) |
|
415 iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); |
|
416 } |
|
417 else |
|
418 { |
|
419 LOG(_L("CPhysicalLink: Current PIN code too short!")) |
|
420 iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); |
|
421 } |
|
422 } |
|
423 else |
|
424 { |
|
425 iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); |
|
426 } |
|
427 } |
|
428 iRequireAuthenticatedLinkKey = EFalse; |
|
429 iWaitingForLinkKeyFromRegistry = EFalse; |
|
430 |
|
431 RegistryTaskComplete(aHelper, aResult); // cleans up our helper |
|
432 } |
|
433 |
|
434 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, TRegistryUpdateStatus aRegUpdateStatus, TInt aResult) |
|
435 { |
|
436 /** |
|
437 This method allows the RegistryHelpers to indicate the registry action taking place |
|
438 |
|
439 **/ |
|
440 LOG_FUNC |
|
441 if(iRemoteDeviceRecordedByStack == EPending && aRegUpdateStatus != ENoChange) |
|
442 { |
|
443 if (aResult == KErrNone) |
|
444 { |
|
445 iRemoteDeviceRecordedByStack = EComplete; |
|
446 } |
|
447 else |
|
448 { |
|
449 iRemoteDeviceRecordedByStack = ENull; |
|
450 } |
|
451 } |
|
452 |
|
453 iRegistryDevBeingMod.RequestCompleted(); |
|
454 RegistryTaskComplete(aHelper, aResult); // cleans up our helper |
|
455 } |
|
456 |
|
457 void CPhysicalLink::CompletedPackets(THCIConnHandle aConnH, TUint16 aNumPackets) |
|
458 /** |
|
459 In this domain we are happy that a valid event has come in telling us that |
|
460 the buffers in the local controller have been freed |
|
461 |
|
462 Since this reflects both local hardware features (buffers) and flow control |
|
463 we treat them separately |
|
464 |
|
465 **/ |
|
466 { |
|
467 LOG_FUNC |
|
468 // firstly report that local hardware buffers free (via inlines!) |
|
469 iLinksMan.LinkManagerProtocol().LinkMuxer().DataQController().CompletedPackets(aConnH, aNumPackets); |
|
470 |
|
471 // we forward this to the thing that sends the packets so that they can do Flow Control |
|
472 |
|
473 // could speed up - already done this handle test to get into *this* object |
|
474 if (iSyncLogicalLink && iSyncLogicalLink->Handle() == aConnH) |
|
475 { |
|
476 iSyncLogicalLink->PacketsSent(aConnH, aNumPackets); |
|
477 } |
|
478 else |
|
479 { |
|
480 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
481 { |
|
482 iACLLogicalLinks[i]->PacketsSent(aConnH, aNumPackets); |
|
483 } |
|
484 } |
|
485 } |
|
486 |
|
487 void CPhysicalLink::TryToSend() |
|
488 { |
|
489 LOG_FUNC |
|
490 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
491 { |
|
492 iACLLogicalLinks[i]->TryToSend(); |
|
493 } |
|
494 } |
|
495 |
|
496 void CPhysicalLink::NewLinkKey(const TBTDevAddr& /*aAddr*/, const TBTLinkKey& aLinkKey, THCILinkKeyType aLinkKeyType) |
|
497 { |
|
498 LOG_FUNC |
|
499 if(iLinkKeyPending) |
|
500 //user has entered a PIN and a new link key has come in. |
|
501 { |
|
502 iLinkKeyPending = EFalse; |
|
503 iPreventLinkKeyUpdateReg = EFalse; //override previous unpair so that link key will be stored in the registry. |
|
504 } |
|
505 |
|
506 TBTLinkKeyType linkKeyType = ELinkKeyCombination; |
|
507 |
|
508 switch (aLinkKeyType) |
|
509 { |
|
510 case ECombinationKey: |
|
511 linkKeyType = ELinkKeyCombination; |
|
512 break; |
|
513 case EDebugCombinationKey: |
|
514 linkKeyType = ELinkKeyDebug; |
|
515 break; |
|
516 case EAuthenticatedCombinationKey: |
|
517 linkKeyType = ELinkKeyAuthenticated; |
|
518 break; |
|
519 case EUnauthenticatedCombinationKey: |
|
520 if (iLocalMITM || (iAuthenticationRequirement & KAuthenticationMitmReqMask) || |
|
521 (iIOCapability == EIOCapsDisplayOnly) || (iIOCapability == EIOCapsNoInputNoOutput)) |
|
522 { |
|
523 linkKeyType = ELinkKeyUnauthenticatedNonUpgradable; |
|
524 } |
|
525 else |
|
526 { |
|
527 linkKeyType = ELinkKeyUnauthenticatedUpgradable; |
|
528 } |
|
529 break; |
|
530 case EChangedCombinationKey: |
|
531 linkKeyType = iDevice.LinkKeyType(); // The link key type hasn't changed |
|
532 break; |
|
533 |
|
534 case ELocalUnitKey: |
|
535 case ERemoteUnitKey: |
|
536 default: |
|
537 LOG1(_L("CPhysicalLink: Unexpected link key type (%d)"), aLinkKeyType); |
|
538 __ASSERT_DEBUG(EFalse, Panic(EBTUnexpectedLinkKeyType)); |
|
539 break; |
|
540 } |
|
541 |
|
542 if (linkKeyType == ELinkKeyCombination && iNewPinCodeValid) |
|
543 { |
|
544 // Only bind a PIN code to the device if we receive a link key based on it. |
|
545 iNewPinCodeValid = EFalse; |
|
546 iDevice.SetPassKey(iNewPinCode); |
|
547 } |
|
548 |
|
549 |
|
550 SetLinkKey(aLinkKey, linkKeyType); // keeps a copy in our 'cache', updates paired list in PHYs mananger |
|
551 |
|
552 TRAP_IGNORE(StoreDeviceL(EFalse)); //EFalse: new meaning - do not prevent addition |
|
553 // if that errored we just have to keep it here - but it won't be in registry |
|
554 // so it'll be a transient pairing |
|
555 } |
|
556 |
|
557 void CPhysicalLink::UpdateFromInquiryCache() |
|
558 { |
|
559 LOG_FUNC |
|
560 CBTInqResultRecord* juice = NULL; //juice is data from remote which can help/speed up a connection |
|
561 // see if we can speed up the connection - the inquiry cache may have some juice |
|
562 juice = iLinksMan.LinkManagerProtocol().InquiryMgr().BasebandParametersFromCache(iDevice.Address()); |
|
563 if(!juice) |
|
564 //no juice in inquiry manager |
|
565 { |
|
566 return; |
|
567 } |
|
568 |
|
569 TInquiryLogEntry& jle = juice->LogEntry(); |
|
570 // Inquiry cache may have useful info we can use: put them in our device |
|
571 // so that we can use this, and update this into the Registry later. |
|
572 // This will allow Apps to get this to initiate faster connections. |
|
573 // The update to the Registry doesn't happen here, but at other interesting times |
|
574 ASSERT_DEBUG(jle.iBdaddr == iDevice.Address()); |
|
575 //Only update with juice values from inquiry manager if they are have come from HCI |
|
576 //(i.e. from remote) - records in the inquiry manager are filled with default |
|
577 //values and then fields are updated as relevant HCI events occur. |
|
578 // - iDevice may already contain values found in the registry which are |
|
579 //not default and therefore should have come themselves from the HCI |
|
580 if(juice->IsPageScanModeFromHCI()) |
|
581 { |
|
582 iDevice.SetPageScanMode(jle.iPageScanMode); |
|
583 } |
|
584 if(juice->IsPageScanRepModeFromHCI()) |
|
585 { |
|
586 iDevice.SetPageScanRepMode(jle.iPageScanRepetitionMode); |
|
587 } |
|
588 if(juice->IsClockOffsetFromHCI()) |
|
589 { |
|
590 iDevice.SetClockOffset(jle.iClockOffset); |
|
591 } |
|
592 } |
|
593 |
|
594 void CPhysicalLink::StoreDeviceL( TBool aPreventDeviceAddition ) |
|
595 { |
|
596 LOG_FUNC |
|
597 |
|
598 UpdateFromInquiryCache(); //check juice has not just come in - update iDevice if so |
|
599 |
|
600 //only write back the necessary attributes |
|
601 TBTNamelessDevice device; |
|
602 if(iDevice.IsValidAddress()) |
|
603 { |
|
604 device.SetAddress(iDevice.Address()); |
|
605 } |
|
606 if(iDevice.IsValidDeviceClass()) |
|
607 { |
|
608 device.SetDeviceClass(iDevice.DeviceClass()); |
|
609 } |
|
610 if(iDevice.IsValidLinkKey() && !iPreventLinkKeyUpdateReg) |
|
611 { |
|
612 if(!(iIOCapsReceived && (iAuthenticationRequirement == EMitmNotReqNoBonding || iAuthenticationRequirement == EMitmReqNoBonding))) |
|
613 { |
|
614 LOG(_L("!!! Storing Link Key in Registry")); |
|
615 device.SetLinkKey(iDevice.LinkKey(), iDevice.LinkKeyType()); |
|
616 } |
|
617 } |
|
618 if(iDevice.IsValidPageScanRepMode()) |
|
619 { |
|
620 device.SetPageScanRepMode(iDevice.PageScanRepMode()); |
|
621 } |
|
622 if(iDevice.IsValidPageScanPeriodMode()) |
|
623 { |
|
624 device.SetPageScanPeriodMode(iDevice.PageScanPeriodMode()); |
|
625 } |
|
626 if(iDevice.IsValidPageScanMode()) |
|
627 { |
|
628 device.SetPageScanMode(iDevice.PageScanMode()); |
|
629 } |
|
630 if(iDevice.IsValidClockOffset()) |
|
631 { |
|
632 device.SetClockOffset(iDevice.ClockOffset()); |
|
633 } |
|
634 if(iDevice.IsValidUsed()) |
|
635 { |
|
636 device.SetUsed(iDevice.Used()); |
|
637 } |
|
638 if(iDevice.IsValidSeen()) |
|
639 { |
|
640 device.SetSeen(iDevice.Seen()); |
|
641 } |
|
642 if(iDevice.IsValidPassKey()) |
|
643 { |
|
644 device.SetPassKey(iDevice.PassKey()); |
|
645 } |
|
646 |
|
647 // if already exists an outstanding request with the same device info |
|
648 // is useless to store it again. Just return doing nothing. |
|
649 if (iRegistryDevBeingMod.InUse() && iRegistryDevBeingMod.IsEqual(device)) |
|
650 { |
|
651 return; // do nothing |
|
652 } |
|
653 |
|
654 CBTDeviceModifier* modifier = CBTDeviceModifier::NewL(iRegSess, *this, iLinksMan.LinkManagerProtocol().InquiryMgr()); |
|
655 iRegistryHelpers.AddLast(*modifier); |
|
656 TBool allowAdd = EFalse; |
|
657 |
|
658 if(!aPreventDeviceAddition && iRemoteDeviceRecordedByStack == ENull) |
|
659 //Only allow the device to be added to the registry if |
|
660 // 1) this StoreDeviceL function has not been called |
|
661 // with its "prevent device addition" parameter set to true |
|
662 // 2) we believe the cached remote device details have not yet |
|
663 // been recorded in the registry. |
|
664 // (If they have and if they are no longer there it is |
|
665 // because an app has deleted them from the registry... |
|
666 // so we should not re-add them ) |
|
667 { |
|
668 allowAdd = ETrue; |
|
669 } |
|
670 modifier->Start(device, allowAdd); |
|
671 iRegistryDevBeingMod.Begin(device); |
|
672 |
|
673 if(allowAdd) |
|
674 //The physical link object has now made its attempt to add its cached |
|
675 //remote device details to the registry. |
|
676 { |
|
677 iRemoteDeviceRecordedByStack = EPending; |
|
678 } |
|
679 |
|
680 } |
|
681 |
|
682 void CPhysicalLink::SetLinkKey(const TBTLinkKey& aLinkKey, TBTLinkKeyType aLinkKeyType) |
|
683 { |
|
684 LOG_FUNC |
|
685 iDevice.SetLinkKey(aLinkKey, aLinkKeyType); // keeps a copy in our 'cache' |
|
686 } |
|
687 |
|
688 void CPhysicalLink::ReadRemoteSupportedFeaturesComplete(THCIErrorCode aErr, THCIConnHandle aConnH, const TBTFeatures& aBitMask) |
|
689 { |
|
690 LOG_FUNC |
|
691 __CHECK_CONNECTION_HANDLE(aConnH); |
|
692 |
|
693 if (aErr == KErrNone) |
|
694 { |
|
695 iRemoteFeatures = aBitMask; |
|
696 |
|
697 if(!iConnectionPacketTypeChanged) |
|
698 { |
|
699 //Send change connection packet type HCI command if application hasn't, we have to do this |
|
700 //because some hardware defaults to using 1-slot packets unless told otherwise by the host. |
|
701 ChangeConnectionPacketType(EAnyACLPacket); |
|
702 } |
|
703 |
|
704 //If remote host supports extended features, then send request to read these. |
|
705 if (iRemoteFeatures[ESupportedExtendedFeaturesBit]) |
|
706 { |
|
707 TRAP_IGNORE(iLinksMan.HCIFacade().ReadRemoteExtendedFeaturesL(iHandle, KRemoteExtendedFeaturesPage1)); |
|
708 } |
|
709 else |
|
710 { |
|
711 // If the remote doesn't support extended features, then neither they support SSP |
|
712 // (no way to indicate the host supported bit). So set it as disabled. |
|
713 TPhysicalLinkSimplePairingMode previousSetting = SimplePairingMode(); |
|
714 __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); |
|
715 iSimplePairingMode = EPhySimplePairingDisabled; |
|
716 if(SimplePairingMode() != previousSetting) |
|
717 { |
|
718 iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); |
|
719 } |
|
720 } |
|
721 } |
|
722 else |
|
723 { |
|
724 iRemoteFeatures = TBTFeatures(KInvalidRemoteFeatures); |
|
725 } |
|
726 } |
|
727 |
|
728 void CPhysicalLink::ReadRemoteExtendedFeaturesComplete(THCIErrorCode aErr, THCIConnHandle aConnH, TUint64 aBitMask, TUint8 aPageNumber, TUint8 /* aMaximumPageNumber */) |
|
729 { |
|
730 LOG_FUNC |
|
731 __CHECK_CONNECTION_HANDLE(aConnH); |
|
732 |
|
733 LOG1(_L("CPhysicalLink: ReadRemoteExtendedFeaturesComplete; result %d"), aErr); |
|
734 |
|
735 switch (aPageNumber) |
|
736 { |
|
737 case KRemoteExtendedFeaturesPage1: |
|
738 { |
|
739 TPhysicalLinkSimplePairingMode currentSetting = SimplePairingMode(); |
|
740 |
|
741 if (aErr == EOK && aBitMask & (1 << ESecureSimplePairingHostSupportBit) && iLinksMan.SecMan().LocalSimplePairingMode()) |
|
742 { |
|
743 __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); |
|
744 iSimplePairingMode = EPhySimplePairingEnabled; |
|
745 } |
|
746 else |
|
747 { |
|
748 __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); |
|
749 iSimplePairingMode = EPhySimplePairingDisabled; |
|
750 } |
|
751 if(SimplePairingMode()!=currentSetting) |
|
752 { |
|
753 iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); |
|
754 } |
|
755 break; |
|
756 } |
|
757 default: |
|
758 { |
|
759 // Ignore |
|
760 } |
|
761 } |
|
762 } |
|
763 |
|
764 void CPhysicalLink::ReadRemoteVersionInfoComplete(THCIErrorCode aErr, THCIConnHandle aConnH, const TBTDevRemoteHwVersion& aVer) |
|
765 { |
|
766 LOG_FUNC |
|
767 __CHECK_CONNECTION_HANDLE(aConnH); |
|
768 if (aErr == KErrNone) |
|
769 { |
|
770 iRemoteVersion = aVer; |
|
771 } |
|
772 else |
|
773 { |
|
774 iRemoteVersion = KInvalidRemoteHwVersion; |
|
775 } |
|
776 } |
|
777 |
|
778 void CPhysicalLink::AuthenticationComplete(THCIErrorCode aErr, THCIConnHandle aConnH) |
|
779 { |
|
780 LOG_FUNC |
|
781 __CHECK_CONNECTION_HANDLE(aConnH); |
|
782 iLinkState.SetAuthenticated(aErr == EOK); |
|
783 //__ASSERT_DEBUG(iAuthStateMask == EAuthenticationRequestPending,Panic(EUnexpectedAuthenticationState)); |
|
784 AuthenticationComplete(EAuthenticationRequestPending); |
|
785 |
|
786 if (aErr!=EOK) |
|
787 { |
|
788 if(aErr == ERemoteUserEndedConnection) |
|
789 { |
|
790 HandlePrefetch(); |
|
791 } |
|
792 iNewPinCodeValid = EFalse; |
|
793 delete iPinRequester; |
|
794 iPinRequester = NULL; |
|
795 iPinHandler = NULL; |
|
796 } |
|
797 else |
|
798 { |
|
799 __ASSERT_DEBUG(!iPinHandler, Panic(EBTPhysicalLinkPinHandlerStillPresent)); |
|
800 } |
|
801 |
|
802 iLinksMan.SecMan().AuthenticationComplete(BDAddr(), aErr); |
|
803 |
|
804 TBTBasebandEventNotification event(ENotifyAuthenticationComplete, aErr); |
|
805 NotifyStateChange(event); |
|
806 } |
|
807 |
|
808 void CPhysicalLink::HandlePrefetch() |
|
809 { |
|
810 // Here we determine whether we need to handle a pre-fetch case. If there is an |
|
811 // outbound authentication attempt and we have a PIN notifier we need to hand it |
|
812 // over to the pre-fetch manager. |
|
813 // We also note the fact that we've done this for any access requester to know whether |
|
814 // it should indicate to defer. |
|
815 if(iPinRequester && iLinksMan.SecMan().IsOutboundAccessRequest(BDAddr()) && iSimplePairingMode != EPhySimplePairingEnabled) |
|
816 { |
|
817 TInt err = iLinksMan.PrefetchMan().HandleOverPinRequester(BDAddr(), iPinRequester); |
|
818 if(err == KErrNone) |
|
819 { |
|
820 iPinRequester = NULL; // As far as phys links is concerned the pin requester doesn't exist anymore. |
|
821 iPinHandler = NULL; // So the handler is also not needed. |
|
822 } |
|
823 } |
|
824 } |
|
825 |
|
826 void CPhysicalLink::EncryptionChange(THCIErrorCode aErr, THCIConnHandle aConnH, TBool aEncrypted) |
|
827 { |
|
828 LOG_FUNC |
|
829 __CHECK_CONNECTION_HANDLE(aConnH); |
|
830 |
|
831 if(aErr == EOK) |
|
832 { |
|
833 // Only change state if it's an actual encryption change - not an error (because if an error |
|
834 // we should presumably stay the same). |
|
835 if(aEncrypted) |
|
836 { |
|
837 iLinkState.SetEncrypted(ETrue); |
|
838 if(!iLinkState.Authenticated()) |
|
839 { |
|
840 // If a link is encrypted then we know that the link is also authenticated. |
|
841 iLinkState.SetAuthenticated(ETrue); |
|
842 } |
|
843 } |
|
844 else |
|
845 { |
|
846 iLinkState.SetEncrypted(EFalse); |
|
847 } |
|
848 } |
|
849 |
|
850 TBTBasebandEventNotification event(aEncrypted ? ENotifyEncryptionChangeOn : ENotifyEncryptionChangeOff, aErr); |
|
851 NotifyStateChange(event); |
|
852 |
|
853 // Having the encryption enforcer present means that we have asked for encryption. |
|
854 // But we should only act if this is a valid encryption change event. |
|
855 if (iEncryptionEnforcer && aErr == EOK) |
|
856 { |
|
857 // if the roleswitch has been requested by us then CRoleSwitcher has already parked / unparked |
|
858 // the ACL controller. That means that the request is submitted twice. |
|
859 // This is not supposed to be a problem, but we need to be aware of it. |
|
860 if (!aEncrypted) |
|
861 { |
|
862 iLinksMan.LinkManagerProtocol().ACLController().SetParked(iHandle, ETrue); |
|
863 iEncryptionEnforcer->EncryptionDisabled(SimplePairingMode()== EPhySimplePairingEnabled); |
|
864 } |
|
865 else |
|
866 { |
|
867 iLinksMan.LinkManagerProtocol().ACLController().SetParked(iHandle, EFalse); |
|
868 iEncryptionEnforcer->EncryptionEnabled(); |
|
869 } |
|
870 } |
|
871 } |
|
872 |
|
873 TInt CPhysicalLink::ChangeEncryption(THCIEncryptModeFlag aEnable) |
|
874 { |
|
875 LOG_FUNC |
|
876 // no policy to adjust, but test local & remote features |
|
877 if (!IsEncryptionSupported()) |
|
878 { |
|
879 return KErrNotSupported; |
|
880 } |
|
881 |
|
882 TRAPD(err, iLinksMan.HCIFacade().SetEncryptL(Handle(), aEnable)); |
|
883 if (err == KErrNone) |
|
884 { |
|
885 err = ManageEncryptionEnforcement(aEnable); |
|
886 } |
|
887 |
|
888 return err; |
|
889 } |
|
890 |
|
891 TInt CPhysicalLink::Authenticate(TBool aRequireAuthenticatedLinkKey) |
|
892 { |
|
893 LOG_FUNC |
|
894 // no policy to adjust, just check to see if the link is already authenticated |
|
895 TInt err = KErrNone; |
|
896 __ASSERT_DEBUG(iSimplePairingMode != EPhySimplePairingUndefined, Panic(EBTPhysicalLinksInvalidArgument)); |
|
897 |
|
898 /* If its a dedicated bonding attempt, then we always want to authenticate again in order to generate |
|
899 * a stronger linkkey if possible |
|
900 */ |
|
901 if (!iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()) && iLinkState.Authenticated() && !iLinksMan.LinkManagerProtocol().IsSecureSimplePairingSupportedLocally()) |
|
902 { |
|
903 err = KErrAlreadyExists; |
|
904 } |
|
905 else |
|
906 { |
|
907 iRequireAuthenticatedLinkKey = aRequireAuthenticatedLinkKey; |
|
908 TRAP(err, iLinksMan.HCIFacade().AuthenticateL(Handle())); |
|
909 if(err == KErrNone) |
|
910 { |
|
911 SetAuthenticationPending(EAuthenticationRequestPending); |
|
912 } |
|
913 } |
|
914 return err; |
|
915 } |
|
916 |
|
917 TInt CPhysicalLink::ChangeLinkKey() |
|
918 { |
|
919 LOG_FUNC |
|
920 __ASSERT_DEBUG(iLinkState.Authenticated(), Panic(EBTPhysicalLinkNotAuthenticated)); |
|
921 |
|
922 // Check if the peer device can support the link key regeneration procedure. |
|
923 if(PeerSupportsLinkKeyRegeneration()) |
|
924 { |
|
925 return iLinksMan.HCIFacade().ChangeConnectionLinkKey(Handle()); |
|
926 } |
|
927 return KErrNone; |
|
928 } |
|
929 |
|
930 TBool CPhysicalLink::PeerSupportsLinkKeyRegeneration() const |
|
931 { |
|
932 LOG_FUNC |
|
933 // Any future manufacturers or manufacturer versions that do not support |
|
934 // link key re-generation should be added to this method. |
|
935 |
|
936 // See Bluetooth assigned numbers for an explanation of this value. |
|
937 return (iRemoteVersion.iManufacturerID != 0x000a); |
|
938 } |
|
939 |
|
940 void CPhysicalLink::ACLDataReceived(THCIConnHandle aConnH, TUint8 aFlag, const TDesC8& aData) |
|
941 { |
|
942 LOG_FUNC |
|
943 __CHECK_CONNECTION_HANDLE(aConnH); |
|
944 |
|
945 // there may be a race condition in that we have got ACL data but just started |
|
946 // shutdown procedures... |
|
947 |
|
948 // find the ACL wanting this type of data... |
|
949 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
950 { |
|
951 iACLLogicalLinks[i]->DataReceived(aConnH, aFlag, aData); |
|
952 } |
|
953 // else just dump |
|
954 } |
|
955 |
|
956 void CPhysicalLink::SCODataReceived(THCIConnHandle aConnH, const TDesC8& aData) |
|
957 { |
|
958 LOG_FUNC |
|
959 if (iSyncLogicalLink) |
|
960 iSyncLogicalLink->DataReceived(aConnH, 0, aData); // flags ignored |
|
961 |
|
962 } |
|
963 |
|
964 void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn) |
|
965 { |
|
966 LOG_FUNC |
|
967 if (aErr == KErrNone) |
|
968 { |
|
969 if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink) |
|
970 { |
|
971 LOG(_L("Got a ConnectionComplete for a non-existant SCO link")) |
|
972 //This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for |
|
973 //a remote device to respond to a connection request. |
|
974 iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); |
|
975 |
|
976 if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that |
|
977 { |
|
978 //The baseband might actually have established a SCO link, so send a Disconnect. |
|
979 //If no SCO link exists the command will fail gracefully. |
|
980 TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); |
|
981 } |
|
982 |
|
983 return; |
|
984 } |
|
985 |
|
986 // update bb model |
|
987 iLinksMan.Baseband().UpdateModel(aConn); |
|
988 if (aConn.iLinkType == EACLLink) |
|
989 { |
|
990 // we need to store the physical handle we're on - in BT1.2 this is also taken to be |
|
991 // the ACL Link handle too... |
|
992 // do the PHY stuff first |
|
993 LOG(_L("CPhysicalLink: PHY ready")) |
|
994 |
|
995 iHandle = aConn.iConnH; |
|
996 iDevice.SetAddress(aConn.iBdaddr); |
|
997 |
|
998 //Set Default Local Link Policy; |
|
999 //Get this in early to try and avoid conditions where remote requests |
|
1000 //something we haven't told the controller we allow yet. |
|
1001 SetModesAllowed(iLinksMan.LinkManagerProtocol().ModesSupportedLocally(), |
|
1002 iLinksMan.RoleSwitchAllowed()); |
|
1003 |
|
1004 // try to get details of remote device |
|
1005 TRAP_IGNORE(GetRemoteDetailsL(aConn)); |
|
1006 // ignore error - only optimisations |
|
1007 |
|
1008 // assume we are going with 1 slot packets until notified otherwise, and in activemode |
|
1009 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkUp); |
|
1010 iLinkState.SetMaxSlots(1); |
|
1011 iLinkState.SetLinkMode(EActiveMode); |
|
1012 |
|
1013 // If the peer is in security mode 3 then authenication has completed. |
|
1014 if(iPeerInSecurityMode3) |
|
1015 { |
|
1016 iLinkState.SetAuthenticated(ETrue); |
|
1017 AuthenticationComplete(EAuthenticationRequestPending); |
|
1018 } |
|
1019 |
|
1020 // update bb model for max slots |
|
1021 iLinksMan.Baseband().UpdateModel(aConn.iConnH, 1); |
|
1022 |
|
1023 TBTBasebandEventNotification event(ENotifyPhysicalLinkUp); |
|
1024 NotifyStateChange(event); |
|
1025 |
|
1026 if (aConn.iEncryptMode) |
|
1027 { |
|
1028 // pretend there's been an encryption event |
|
1029 EncryptionChange(aErr, aConn.iConnH, aConn.iEncryptMode); |
|
1030 } |
|
1031 } |
|
1032 |
|
1033 // This is assuming that our stack only allows one synchronous link per phy link. |
|
1034 // SCO (not eSCO) Link getting notified here. |
|
1035 else if(aConn.iLinkType == ESCOLink) |
|
1036 { |
|
1037 TBTBasebandEventNotification event(ENotifySynchronousLinkUp); |
|
1038 NotifyStateChange(event); |
|
1039 } |
|
1040 |
|
1041 // tell the logical links |
|
1042 NotifyLogicalLinkUp(aConn); |
|
1043 iLinksMan.ArbitrateAllPhysicalLinks(); |
|
1044 |
|
1045 // Check to see if we got a disconnect request during the period before the link was |
|
1046 // fully established. |
|
1047 if (iDisconnectRequested) |
|
1048 { |
|
1049 __ASSERT_DEBUG(aConn.iLinkType == EACLLink, Panic(EDisconnectRequestedNotOnACLLink)); |
|
1050 |
|
1051 // We allow the link to come up fully so that the link is not in a strange state between |
|
1052 // pending and up. This also means that the notifications to the logical links all work |
|
1053 // correctly, they just see a link come up and then go down again straight away. |
|
1054 TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); |
|
1055 } |
|
1056 else |
|
1057 { |
|
1058 TTime t; |
|
1059 t.UniversalTime(); |
|
1060 iDevice.SetUsed(t); |
|
1061 TRAP_IGNORE(StoreDeviceL(EFalse)); |
|
1062 } |
|
1063 } |
|
1064 else |
|
1065 { |
|
1066 // error occurred - need to see if it's PHY(and so ACL) or SCO that failed |
|
1067 // tell logical links |
|
1068 LOG2(_L("Physical link: connection complete returned an error on handle %d, type %d"), aConn.iConnH, aConn.iLinkType); |
|
1069 |
|
1070 if(((aConn.iLinkType == ESCOLink)||(aConn.iLinkType == EeSCOLink)) && iSyncLogicalLink && |
|
1071 iSyncLogicalLink->Handle() != KInvalidConnectionHandle && iSyncLogicalLink->Handle() != aConn.iConnH) |
|
1072 { |
|
1073 // This is a secondary SCO link we just rejected or something - don't mess with our own |
|
1074 // The KInvalidConnectionHandle test ensures that we ignore errored outgoing SCO connects. |
|
1075 return; |
|
1076 } |
|
1077 |
|
1078 iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); |
|
1079 NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr)); |
|
1080 if (aConn.iLinkType == EACLLink) |
|
1081 { |
|
1082 // BT 1.2 says that as the ACL Link goes up and down, so does the physical link |
|
1083 // so if the ACL Link has gone, so has this |
|
1084 // for SCO we remain in place. |
|
1085 TBTBasebandEventNotification event(ENotifyPhysicalLinkError, CHciUtil::SymbianErrorCode(aErr)); |
|
1086 NotifyStateChange(event); |
|
1087 delete this; |
|
1088 } |
|
1089 } |
|
1090 // ***Watchout*** delete this above: careful about code here |
|
1091 } |
|
1092 |
|
1093 |
|
1094 void CPhysicalLink::SynchronousConnectionComplete(THCIErrorCode aErr, |
|
1095 const TBTConnect& aConn, |
|
1096 const TBTSyncConnectOpts& aSyncOpts) |
|
1097 { |
|
1098 LOG_FUNC |
|
1099 __ASSERT_DEBUG(((aConn.iLinkType == ESCOLink) || (aConn.iLinkType == EeSCOLink)), Panic(EBTNonSyncConnectInSyncConnectFunc)); |
|
1100 |
|
1101 if(!iSyncLogicalLink) |
|
1102 { |
|
1103 LOG(_L("Got a SynchronousConnectionComplete when no SCO link is bound")) |
|
1104 //This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for |
|
1105 //a remote device to respond to a connection request. |
|
1106 iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); |
|
1107 |
|
1108 if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that |
|
1109 { |
|
1110 //The baseband might actually have established a SCO link, so send a Disconnect. |
|
1111 //If no SCO link exists the command will fail gracefully. |
|
1112 TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); |
|
1113 } |
|
1114 |
|
1115 return; |
|
1116 } |
|
1117 |
|
1118 if (aErr == KErrNone) |
|
1119 { |
|
1120 // update bb model |
|
1121 iLinksMan.Baseband().UpdateModel(aConn); |
|
1122 |
|
1123 // This is assuming that our stack only allows one synchronous link per phy link. |
|
1124 // eSCO (not SCO) Link getting notified here. |
|
1125 TBTBasebandEventNotification event(ENotifySynchronousLinkUp); |
|
1126 NotifyStateChange(event); |
|
1127 |
|
1128 // tell the logical links |
|
1129 NotifyLogicalSyncLinkUp(aConn, aSyncOpts); |
|
1130 iLinksMan.ArbitrateAllPhysicalLinks(); |
|
1131 } |
|
1132 else |
|
1133 { |
|
1134 // error occurred - need to see if it's PHY(and so ACL) or SCO that failed |
|
1135 // tell logical links |
|
1136 LOG2(_L("Physical link: connection complete returned an error on handle %d, type %d"), aConn.iConnH, aConn.iLinkType); |
|
1137 iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); |
|
1138 |
|
1139 // Before passing error around, check if it's actually for this link... |
|
1140 // A listening link will have a NULL handle, otherwise the handle should match. |
|
1141 // If the eSCO connection fails, the handle is KInvalidConnectionHandle (as initialised in CBTBasebandSAP) |
|
1142 // This avoids the situation where we get notified of a rejection. |
|
1143 if (iSyncLogicalLink && |
|
1144 (iSyncLogicalLink->Handle() == 0 || iSyncLogicalLink->Handle() == KInvalidConnectionHandle || iSyncLogicalLink->Handle() == aConn.iConnH)) |
|
1145 { |
|
1146 NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr)); |
|
1147 } |
|
1148 } |
|
1149 } |
|
1150 |
|
1151 |
|
1152 void CPhysicalLink::GetRemoteDetailsL(const TBTConnect& aConn) |
|
1153 { |
|
1154 LOG_FUNC |
|
1155 GetDeviceFromRegistryL(); |
|
1156 iLinksMan.HCIFacade().ReadClockOffsetL(aConn.iConnH); |
|
1157 iLinksMan.HCIFacade().ReadRemoteSupportedFeaturesL(aConn.iConnH); |
|
1158 iLinksMan.HCIFacade().ReadRemoteVersionL(aConn.iConnH); |
|
1159 iLinksMan.LinkManagerProtocol().InquiryMgr().ReadRemoteNameL(aConn.iBdaddr); |
|
1160 } |
|
1161 |
|
1162 void CPhysicalLink::LinkSupervisionTimeoutChange(THCIErrorCode aErr, THCIConnHandle aConnH, TUint16 aNewTimeout) |
|
1163 { |
|
1164 LOG_FUNC |
|
1165 __CHECK_CONNECTION_HANDLE(aConnH); |
|
1166 |
|
1167 if(aErr == EOK) |
|
1168 { |
|
1169 iLSTO = aNewTimeout; |
|
1170 } |
|
1171 } |
|
1172 |
|
1173 void CPhysicalLink::PacketTypeChange(THCIErrorCode aErr, THCIConnHandle aConnH, TUint16 aNewPacket) |
|
1174 { |
|
1175 LOG_FUNC |
|
1176 __CHECK_CONNECTION_HANDLE(aConnH); |
|
1177 |
|
1178 if(aErr==EOK) |
|
1179 { |
|
1180 iLinksMan.Baseband().UpdateModelIfRecordExists(aConnH, aNewPacket); |
|
1181 iLinkState.SetPacketTypes(aNewPacket); |
|
1182 } |
|
1183 |
|
1184 TUint32 eventType = 0; |
|
1185 |
|
1186 if(aNewPacket & EPacketsDM1) |
|
1187 eventType |= ENotifyPacketsDM1; |
|
1188 if(aNewPacket & EPacketsDH1) |
|
1189 eventType |= ENotifyPacketsDH1; |
|
1190 if(aNewPacket & EPacketsDM3) |
|
1191 eventType |= ENotifyPacketsDM3; |
|
1192 if(aNewPacket & EPacketsDH3) |
|
1193 eventType |= ENotifyPacketsDH3; |
|
1194 if(aNewPacket & EPacketsDM5) |
|
1195 eventType |= ENotifyPacketsDM5; |
|
1196 if(aNewPacket & EPacketsDH5) |
|
1197 eventType |= ENotifyPacketsDH5; |
|
1198 |
|
1199 if(aNewPacket & EPacketsHV1) |
|
1200 eventType |= ENotifyPacketsHV1; |
|
1201 if(aNewPacket & EPacketsHV2) |
|
1202 eventType |= ENotifyPacketsHV2; |
|
1203 if(aNewPacket & EPacketsHV3) |
|
1204 eventType |= ENotifyPacketsHV3; |
|
1205 |
|
1206 TBTBasebandEventNotification event(eventType, aErr); |
|
1207 NotifyStateChange(event); |
|
1208 } |
|
1209 |
|
1210 void CPhysicalLink::MaxSlotsChange(THCIConnHandle aConnH, TUint8 aSlots) |
|
1211 { |
|
1212 LOG_FUNC |
|
1213 __CHECK_CONNECTION_HANDLE(aConnH); |
|
1214 LOG2(_L("Connection Handle 0x%04x, using %d slots"), aConnH, aSlots); |
|
1215 iLinksMan.Baseband().UpdateModel(aConnH, aSlots); //event only for ACL |
|
1216 iLinkState.SetMaxSlots(aSlots); |
|
1217 |
|
1218 TBTBasebandEventNotification event; |
|
1219 switch(aSlots) |
|
1220 { |
|
1221 case 1: |
|
1222 event.SetEventType(ENotifyMaxSlots1); |
|
1223 break; |
|
1224 case 3: |
|
1225 event.SetEventType(ENotifyMaxSlots3); |
|
1226 break; |
|
1227 case 5: |
|
1228 event.SetEventType(ENotifyMaxSlots5); |
|
1229 break; |
|
1230 }; |
|
1231 NotifyStateChange(event); |
|
1232 } |
|
1233 |
|
1234 void CPhysicalLink::ModeChange(THCIErrorCode aErr, THCIConnHandle aConnH, TBTLinkMode aMode, TBasebandTime aInterval) |
|
1235 { |
|
1236 LOG_FUNC |
|
1237 __CHECK_CONNECTION_HANDLE(aConnH); |
|
1238 LOG3(_L("Connection Handle 0x%04x: ModeChange event %d->%d"), aConnH, iLinkState.LinkMode(), aMode); |
|
1239 |
|
1240 TBTLinkMode oldMode = iLinkState.LinkMode(); |
|
1241 |
|
1242 iLinkState.SetLinkMode(aMode); // remember the state for ourselves |
|
1243 |
|
1244 if (aErr == EOK) |
|
1245 { |
|
1246 if (aMode == EParkMode) |
|
1247 { |
|
1248 iLinksMan.Baseband().ParkLink(aConnH); //remove from model whilst parked |
|
1249 } |
|
1250 |
|
1251 if (aMode == EActiveMode && oldMode==EParkMode) |
|
1252 { |
|
1253 // unparking we must tell the DataQ - we could always get the dataQ to ask us before sending of course |
|
1254 // but that might be performance harming |
|
1255 iLinksMan.Baseband().UnParkLink(aConnH); //NB Max Slots = 1 default |
|
1256 } |
|
1257 |
|
1258 if (aMode == ESniffMode ) |
|
1259 { |
|
1260 // Store the Sniff Interval |
|
1261 iSniffInterval = aInterval; |
|
1262 } |
|
1263 |
|
1264 if (aMode == EActiveMode && iSniffInterval) |
|
1265 { |
|
1266 //Active mode enable and SniffInterval is set. |
|
1267 //Therefore must be leaving sniff mode. |
|
1268 __ASSERT_DEBUG(oldMode==ESniffMode, Panic(EBTPhysicalLinkModeChangeErrorLeavingSniffMode)); |
|
1269 |
|
1270 //When not in sniff mode, sniff interval is obviously 0! |
|
1271 iSniffInterval = 0; |
|
1272 } |
|
1273 } |
|
1274 |
|
1275 // Generate a baseband event, and offer it to the proxySAP's associated |
|
1276 // with this link. |
|
1277 TBTBasebandEventNotification event; |
|
1278 switch(aMode) |
|
1279 { |
|
1280 case EActiveMode: |
|
1281 event.SetEventType(ENotifyActiveMode); |
|
1282 break; |
|
1283 case ESniffMode: |
|
1284 event.SetEventType(ENotifySniffMode); |
|
1285 break; |
|
1286 case EHoldMode: |
|
1287 event.SetEventType(ENotifyHoldMode); |
|
1288 break; |
|
1289 case EParkMode: |
|
1290 event.SetEventType(ENotifyParkMode); |
|
1291 break; |
|
1292 case EScatterMode: |
|
1293 break; // shouldnt be seen yet - if so, ignore for now |
|
1294 }; |
|
1295 event.SetErrorCode(aErr); |
|
1296 NotifyStateChange(event); |
|
1297 } |
|
1298 |
|
1299 void CPhysicalLink::RoleChange(THCIErrorCode aErr, const TBTDevAddr& /*aAddr*/, TBTBasebandRole aRole) |
|
1300 { |
|
1301 LOG_FUNC |
|
1302 LOG1(_L("CPhysicalLink: Role change - new role %S"), aRole == EMaster ? _S("Master") : _S("Slave")); |
|
1303 |
|
1304 if (aErr == EOK) |
|
1305 { |
|
1306 iLinkState.SetLinkRole(aRole); |
|
1307 } |
|
1308 |
|
1309 // Generate a baseband event, and offer it to the proxySAP's associated |
|
1310 // with this link. |
|
1311 TBTBasebandEventNotification event; |
|
1312 if(aRole == EMaster) |
|
1313 { |
|
1314 event.SetEventType(ENotifyMaster); |
|
1315 } |
|
1316 else |
|
1317 { |
|
1318 event.SetEventType(ENotifySlave); |
|
1319 } |
|
1320 event.SetErrorCode(aErr); |
|
1321 NotifyStateChange(event); |
|
1322 |
|
1323 // if iEncryptionEnforcer is present it means we asked for encryption, so we inform it |
|
1324 // about the roleswitch |
|
1325 if (iEncryptionEnforcer) |
|
1326 { |
|
1327 iEncryptionEnforcer->RoleSwitchEvent(); |
|
1328 } |
|
1329 } |
|
1330 |
|
1331 void CPhysicalLink::WriteLinkPolicySettingsCompleteEvent(THCIErrorCode aErr, THCIConnHandle aConnH) |
|
1332 { |
|
1333 LOG_FUNC |
|
1334 __CHECK_CONNECTION_HANDLE(aConnH); |
|
1335 // we don't get the things back we set... |
|
1336 if (aErr != EOK) |
|
1337 { |
|
1338 // The command has failed. Clear the cached values and re-arbitrate. |
|
1339 iLinkPolicy.SetModesAllowed(0); |
|
1340 iLinkPolicy.SetSwitchAllowed(EFalse); |
|
1341 Arbitrate(); |
|
1342 } |
|
1343 } |
|
1344 |
|
1345 void CPhysicalLink::ClockOffset(THCIErrorCode aErr, THCIConnHandle aConnH, TBasebandTime aClockOffset) |
|
1346 { |
|
1347 LOG_FUNC |
|
1348 __CHECK_CONNECTION_HANDLE(aConnH); |
|
1349 if (aErr==EOK) |
|
1350 { |
|
1351 // tell inquiry manager - we found this information to help it |
|
1352 iLinksMan.LinkManagerProtocol().InquiryMgr().ClockOffsetResult(BDAddr(), aClockOffset); |
|
1353 } |
|
1354 // we don't do anything more useful knowing this information |
|
1355 } |
|
1356 |
|
1357 void CPhysicalLink::RemoteName(THCIErrorCode aErr, const TBTDevAddr& /*aAddr*/, const TBTDeviceName8& aName) |
|
1358 /** |
|
1359 We don't keep this, but we're interested in persisting it in el Reg |
|
1360 By receiving this we now our attempts have completed in getting name |
|
1361 */ |
|
1362 { |
|
1363 LOG_FUNC |
|
1364 if (aErr==EOK) |
|
1365 { |
|
1366 // slam it into the Registry - this will be useful to UIs if not us |
|
1367 TRAP_IGNORE(DoUpdateNameL(aName)); |
|
1368 } |
|
1369 } |
|
1370 |
|
1371 void CPhysicalLink::DoUpdateNameL(const TBTDeviceName8& aName) |
|
1372 { |
|
1373 LOG_FUNC |
|
1374 CBTDeviceNameChanger* nameChanger = CBTDeviceNameChanger::NewL(iRegSess, *this); |
|
1375 iRegistryHelpers.AddLast(*nameChanger); |
|
1376 nameChanger->Start(BDAddr(), aName); |
|
1377 } |
|
1378 |
|
1379 void CPhysicalLink::Disconnection(THCIErrorCode aErr, THCIConnHandle aConnH, THCIErrorCode aResult) |
|
1380 { |
|
1381 LOG_FUNC |
|
1382 // tell our socket if it's our handle - otherwise the SCO SAP |
|
1383 |
|
1384 LOG1(_L("Physical link: disconnection on handle %d"), aConnH); |
|
1385 LOG1(_L(" ACL link handle: %d"), Handle()); |
|
1386 #ifdef __FLOG_ACTIVE |
|
1387 if (iSyncLogicalLink) LOG1(_L(" Sync link handle: %d"), iSyncLogicalLink->Handle()); |
|
1388 #endif |
|
1389 |
|
1390 //no matter if it is the socket or SCO SAP the ui dialogs will be cancelled |
|
1391 if (iNumericComparator && iNumericComparator->IsActive()) |
|
1392 { |
|
1393 iNumericComparator->Cancel(); |
|
1394 } |
|
1395 if (iPasskeyEntry && iPasskeyEntry->IsActive()) |
|
1396 { |
|
1397 iPasskeyEntry->Cancel(); |
|
1398 } |
|
1399 |
|
1400 if (aConnH == Handle()) |
|
1401 { |
|
1402 TBTBasebandEventNotification event; |
|
1403 switch(aErr) |
|
1404 { |
|
1405 case EHardwareFail: |
|
1406 { |
|
1407 |
|
1408 if(iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp || |
|
1409 iLinkState.LinkState() == TBTBasebandLinkState::ELinkPending) |
|
1410 { |
|
1411 //Only propagate if link is up or pending, otherwise |
|
1412 //we may get disconnection in unexpected states |
|
1413 |
|
1414 //Fall through |
|
1415 } |
|
1416 else |
|
1417 { |
|
1418 // this object must go when no link |
|
1419 delete this; |
|
1420 break; |
|
1421 } |
|
1422 } |
|
1423 case EOK: |
|
1424 { |
|
1425 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkDown); |
|
1426 |
|
1427 // PHY went down - so have logical links then |
|
1428 NotifyLogicalLinkDown(EACLLink); |
|
1429 NotifyLogicalLinkDown(ESCOLink); |
|
1430 |
|
1431 event.SetEventType(ENotifyPhysicalLinkDown); |
|
1432 event.SetErrorCode(aResult); |
|
1433 iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, EACLLink); |
|
1434 HandlePrefetch(); |
|
1435 NotifyStateChange(event); |
|
1436 // this object must go when no link |
|
1437 delete this; |
|
1438 break; |
|
1439 } |
|
1440 case ECommandDisallowed: |
|
1441 { |
|
1442 // The connection is still up, so do nothing, and wait for the next idle timer to fire |
|
1443 break; |
|
1444 } |
|
1445 default: |
|
1446 { |
|
1447 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkDown); |
|
1448 |
|
1449 // there's an error |
|
1450 NotifyLogicalLinkError(EACLLink, aErr); |
|
1451 NotifyLogicalLinkError(ESCOLink, aErr); |
|
1452 event.SetEventType(ENotifyPhysicalLinkError); |
|
1453 event.SetErrorCode(aErr); |
|
1454 // baseband model needs to err on the side of least bandwidth usage - |
|
1455 // a link COULD have come down |
|
1456 iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, EACLLink); |
|
1457 HandlePrefetch(); |
|
1458 NotifyStateChange(event); |
|
1459 // this object must go when no link |
|
1460 delete this; |
|
1461 break; |
|
1462 } |
|
1463 } |
|
1464 } |
|
1465 |
|
1466 else if (iSyncLogicalLink && aConnH == iSyncLogicalLink->Handle()) |
|
1467 { |
|
1468 TBTBasebandEventNotification event; |
|
1469 // just the SCO link is down so we'd better notify |
|
1470 if (aErr) |
|
1471 { |
|
1472 LOG(_L("Physical link: error disconnection on sync link")); |
|
1473 TLinkType type = iSyncLogicalLink->LinkType(); |
|
1474 iSyncLogicalLink->Error(CHciUtil::SymbianErrorCode(aErr)); |
|
1475 event.SetEventType(ENotifySynchronousLinkError); |
|
1476 event.SetErrorCode(aErr); |
|
1477 // baseband model needs to err on the side of least bandwidth usage - |
|
1478 // a sync link COULD have come down |
|
1479 iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, type); |
|
1480 } |
|
1481 else |
|
1482 { |
|
1483 LOG(_L("Physical link: normal disconnection on sync link")); |
|
1484 TLinkType type = iSyncLogicalLink->LinkType(); |
|
1485 iSyncLogicalLink->Disconnection(); |
|
1486 event.SetEventType(ENotifySynchronousLinkDown); |
|
1487 event.SetErrorCode(aResult); |
|
1488 iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, type); |
|
1489 } |
|
1490 |
|
1491 NotifyStateChange(event); |
|
1492 } |
|
1493 // NOTE!! delete this above - careful about adding code |
|
1494 } |
|
1495 |
|
1496 void CPhysicalLink::ConnectionRequest(const TBTConnect& aConn) |
|
1497 { |
|
1498 LOG_FUNC |
|
1499 // we must be page scan enable for this to come in |
|
1500 // but still need to see if it got routed a listening SAP |
|
1501 TBool accept = EFalse; |
|
1502 TLogicalLinkListener* listener = NULL; |
|
1503 |
|
1504 __ASSERT_DEBUG(iPendingConnection == EFalse, Panic(EPendingConnectionNotCleared)); |
|
1505 |
|
1506 switch (aConn.iLinkType) |
|
1507 { |
|
1508 case ESCOLink: |
|
1509 case EeSCOLink: |
|
1510 if (!iSyncLogicalLink) |
|
1511 { |
|
1512 // If we already have a sync link active, reject request. |
|
1513 LOG(_L("No current link, checking for listener")); |
|
1514 listener = iLinksMan.FindListener(aConn.iLinkType); |
|
1515 } |
|
1516 break; |
|
1517 |
|
1518 default: |
|
1519 listener = iLinksMan.FindListener(aConn.iLinkType); |
|
1520 break; |
|
1521 } |
|
1522 |
|
1523 if (listener) |
|
1524 { |
|
1525 accept = ETrue; |
|
1526 if (iLinksMan.IsAcceptPairedOnlyMode()) |
|
1527 { |
|
1528 // do not accept if we are only accepting connection |
|
1529 // requests from paired devices and we are not already |
|
1530 // paired with the remote |
|
1531 CBTPairingsCache::TPairingState pairingState = iLinksMan.PairingsCache().IsPaired(aConn.iBdaddr); |
|
1532 |
|
1533 if(pairingState == CBTPairingsCache::EDeferred) |
|
1534 { |
|
1535 // We're still waiting for the Pairing Caches paired device list to be filled. |
|
1536 // We'll respond when this is complete, so store details away for then. |
|
1537 LOG(_L("CPhysicalLink: Waiting for physical link manager's paired device list from Registry!")) |
|
1538 iPendingConnection = ETrue; |
|
1539 iLastPendingConnection.iConnH = aConn.iConnH; |
|
1540 iLastPendingConnection.iBdaddr = aConn.iBdaddr; |
|
1541 iLastPendingConnection.iCoD = aConn.iCoD; |
|
1542 iLastPendingConnection.iLinkType = aConn.iLinkType; |
|
1543 iLastPendingConnection.iEncryptMode = aConn.iEncryptMode; |
|
1544 // Return now as we are waiting and don't want to 'RejectConnection' |
|
1545 return; |
|
1546 } |
|
1547 |
|
1548 // If here then the cache has either informed us that the device is paired |
|
1549 // or not. We only accept paired connections. |
|
1550 accept = (pairingState == CBTPairingsCache::EPaired) ? ETrue : EFalse; |
|
1551 } |
|
1552 if (accept) |
|
1553 { |
|
1554 // this may mean the physical link's acceptance is determined by the |
|
1555 // ACL Logical link - but that's what the spec implies :-) |
|
1556 accept = static_cast<MLogicalLink*>(listener->iObserver)->ConnectRequest(aConn, *this); |
|
1557 // since we only support one SCO listener at present we dont need to mark it as the acceptor |
|
1558 // or indeed find a specific one: later we could choose via CoD |
|
1559 } |
|
1560 } |
|
1561 |
|
1562 if (accept) |
|
1563 { |
|
1564 |
|
1565 // store CoD now, not told it ever again! if connection fails this object will go |
|
1566 // Don't update CoD if it is 0 (NULL) as this is the default. |
|
1567 // This also prevents a valid CoD being overwritten. |
|
1568 if (aConn.iCoD != 0) |
|
1569 { |
|
1570 iDevice.SetDeviceClass(aConn.iCoD); |
|
1571 } |
|
1572 |
|
1573 TUint8 roleSwitch = static_cast<TUint8>(iLinksMan.PassiveConnectBecomeMaster() ? 0x00 : 0x01); |
|
1574 |
|
1575 TInt err; |
|
1576 if (aConn.iLinkType == EeSCOLink) |
|
1577 { |
|
1578 TBTeSCOLinkParams options; |
|
1579 |
|
1580 CeSCOLink* eSCO = static_cast<CeSCOLink*>(listener->iObserver); |
|
1581 TUint16 packetMask = eSCO->GetPacketMask(); |
|
1582 eSCO->GetExtOptions(options); |
|
1583 |
|
1584 TRAP(err, iLinksMan.HCIFacade().AcceptSynchronousConnectionL(aConn.iBdaddr, |
|
1585 options.iBandwidth.iTransmit, options.iBandwidth.iReceive, |
|
1586 options.iLatency, options.iCoding, options.iRetransmissionEffort, |
|
1587 packetMask |
|
1588 )); |
|
1589 } |
|
1590 else |
|
1591 { |
|
1592 TRAP(err, iLinksMan.HCIFacade().AcceptConnectionRequestL(aConn.iBdaddr, roleSwitch)); |
|
1593 } |
|
1594 |
|
1595 if (err == KErrNone) |
|
1596 { |
|
1597 // assume we're slave until told otherwise on ACL(=PHY) links |
|
1598 if (aConn.iLinkType == EACLLink) |
|
1599 { |
|
1600 // this is a PHY connect request too, so we should store our role |
|
1601 //The handle in 'aConn' is bogus, so.. |
|
1602 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending); |
|
1603 iLinksMan.Baseband().UpdateModel(aConn.iBdaddr, KHCIDefaultPacketType, aConn.iLinkType); |
|
1604 iLinkState.SetLinkRole((roleSwitch == 0x01) ? ESlave : EMaster); |
|
1605 |
|
1606 // have to store it now, since the complete wont tell us anything! |
|
1607 } |
|
1608 else |
|
1609 { |
|
1610 //The handle in 'aConn' is bogus, so.. |
|
1611 iLinksMan.Baseband().UpdateModel(aConn.iBdaddr, KHCIDefaultSCOPacketType, aConn.iLinkType); |
|
1612 } |
|
1613 } |
|
1614 else |
|
1615 { |
|
1616 // Out of memory: |
|
1617 // Cause newly created spawned SAP (whether ACL or SCO) |
|
1618 // to die. |
|
1619 // Attempt to reject connection with newly freed memory... |
|
1620 // ...this of course may fail in which case we have |
|
1621 // to rely on supervison timeouts. |
|
1622 if (aConn.iLinkType == EACLLink) |
|
1623 { |
|
1624 TInt last = iACLLogicalLinks.Count() - 1; |
|
1625 if(last>=0) |
|
1626 { |
|
1627 iACLLogicalLinks[last]->Error(err); |
|
1628 } |
|
1629 } |
|
1630 else |
|
1631 { |
|
1632 if(iSyncLogicalLink) |
|
1633 { |
|
1634 iSyncLogicalLink->Error(err); |
|
1635 } |
|
1636 } |
|
1637 RejectConnection(aConn); |
|
1638 } |
|
1639 } |
|
1640 else |
|
1641 { |
|
1642 // reject |
|
1643 RejectConnection(aConn); |
|
1644 } |
|
1645 |
|
1646 // Tell inquiry manager - should have a valid CoD within 'aConn' |
|
1647 // Don't update CoD if it is 0 (NULL) as this is the default. |
|
1648 // This also prevents a valid CoD being overwritten. |
|
1649 if (aConn.iCoD != 0) |
|
1650 { |
|
1651 iLinksMan.LinkManagerProtocol().InquiryMgr().CoDResult(aConn.iBdaddr, aConn.iCoD); |
|
1652 } |
|
1653 } |
|
1654 |
|
1655 void CPhysicalLink::RejectConnection(const TBTConnect& aConn) |
|
1656 { |
|
1657 LOG_FUNC |
|
1658 if (aConn.iLinkType == EeSCOLink) |
|
1659 { |
|
1660 TRAP_IGNORE(iLinksMan.HCIFacade().RejectSynchronousConnectionL(aConn.iBdaddr, KDefaultRejectReason)); |
|
1661 } |
|
1662 else |
|
1663 { |
|
1664 TRAP_IGNORE(iLinksMan.HCIFacade().RejectConnectionRequestL(aConn, KDefaultRejectReason)); |
|
1665 } |
|
1666 } |
|
1667 |
|
1668 |
|
1669 void CPhysicalLink::GetDeviceFromRegistryL() |
|
1670 { |
|
1671 LOG_FUNC |
|
1672 CBTDeviceGetter* getter = CBTDeviceGetter::NewL(iRegSess, *this); |
|
1673 iRegistryHelpers.AddLast(*getter); |
|
1674 getter->Start(BDAddr()); // now get the rest of the details |
|
1675 // just BDAddr? |
|
1676 } |
|
1677 |
|
1678 TInt CPhysicalLink::GetOption(TUint aLevel,TUint aName,TDes8& aOption) const |
|
1679 { |
|
1680 LOG_FUNC |
|
1681 // good stuff here! |
|
1682 if (aLevel == KSolBtLM) |
|
1683 { |
|
1684 switch (aName) |
|
1685 { |
|
1686 case KLMGetBasebandHandle: |
|
1687 { |
|
1688 if (aOption.Length() != sizeof(THCIConnHandle)) |
|
1689 { |
|
1690 return KErrArgument; |
|
1691 } |
|
1692 aOption = TPtrC8(reinterpret_cast<const TUint8*>(&iHandle), sizeof(THCIConnHandle)); |
|
1693 return KErrNone; |
|
1694 } |
|
1695 |
|
1696 case EBBGetSniffInterval: |
|
1697 if (aOption.Length() != sizeof(TBasebandTime)) |
|
1698 { |
|
1699 return KErrArgument; |
|
1700 } |
|
1701 aOption = TPtrC8(reinterpret_cast<const TUint8*>(&iSniffInterval), sizeof(TBasebandTime)); |
|
1702 return KErrNone; |
|
1703 |
|
1704 default: |
|
1705 return KErrNotSupported; |
|
1706 } |
|
1707 } |
|
1708 else |
|
1709 { |
|
1710 return KErrNotSupported; |
|
1711 } |
|
1712 } |
|
1713 |
|
1714 TInt CPhysicalLink::Arbitrate(const TBool aImmediately, const TBool aLocalPriority) |
|
1715 { |
|
1716 LOG_FUNC |
|
1717 if (!IsConnected()) |
|
1718 return KErrDisconnected; |
|
1719 |
|
1720 if ( aImmediately ) |
|
1721 { |
|
1722 iArbitrationDelay->Cancel(); |
|
1723 } |
|
1724 else if (iArbitrationDelay->IsActive()) |
|
1725 { |
|
1726 return KErrNone; |
|
1727 } |
|
1728 |
|
1729 //start arbitrate process with what our local controller supports |
|
1730 TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later |
|
1731 TBool roleSwitchAllowed = EFalse; |
|
1732 |
|
1733 if (iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed()) |
|
1734 { |
|
1735 roleSwitchAllowed = ETrue; |
|
1736 } |
|
1737 |
|
1738 // ask proxies what they want from the PHY |
|
1739 TUint8 requestedModeMask = 0; |
|
1740 TUint8 requestedMode = 0; |
|
1741 TBool activeModeIsRequested = EFalse; |
|
1742 TSglQueIter<CBTProxySAP> iter(iProxySAPs); |
|
1743 while (iter) |
|
1744 { |
|
1745 CBTProxySAP* proxy = iter++; |
|
1746 |
|
1747 requestedMode = proxy->GetRequestedModes(); |
|
1748 requestedModeMask |= requestedMode; |
|
1749 |
|
1750 if (requestedMode == EActiveMode && proxy->RequestedActiveMode()) |
|
1751 { |
|
1752 // An Active Mode request will override all other local low power mode requests |
|
1753 // but continue to collect the requirement from the other proxies.. |
|
1754 activeModeIsRequested = ETrue; |
|
1755 } |
|
1756 |
|
1757 allowedModesMask &= proxy->GetAllowedModes(); |
|
1758 roleSwitchAllowed &= proxy->IsRoleSwitchAllowed(); |
|
1759 } |
|
1760 |
|
1761 if (activeModeIsRequested) |
|
1762 { |
|
1763 // Any Active Mode request will override all other low power mode requests, |
|
1764 // so overwrite the requestedModeMask but keep allowedModesMask and roleSwitchAllowed |
|
1765 // as specified by all the local proxies |
|
1766 requestedModeMask = EActiveMode; |
|
1767 } |
|
1768 |
|
1769 // clear out modes not supported by local Controller |
|
1770 allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally(); |
|
1771 |
|
1772 if(iOverrideParkRequests) |
|
1773 { |
|
1774 // We wish to ensure the physical link is not in PARK mode. |
|
1775 // The only way to guarantee this is to disallow PARK via the link policy settings. |
|
1776 allowedModesMask &= ~EParkMode; |
|
1777 } |
|
1778 |
|
1779 if(allowedModesMask != iLinkPolicy.LowPowerModePolicy() |
|
1780 || roleSwitchAllowed != iLinkPolicy.IsSwitchAllowed()) |
|
1781 { |
|
1782 // Controller policy for the connection needs updating |
|
1783 SetModesAllowed(allowedModesMask, roleSwitchAllowed); |
|
1784 } |
|
1785 |
|
1786 //If OverrideLPM flag is set, we do not disable LP modes via the link policy settings |
|
1787 //This is done because OverrideLPM should not prevent remotes putting us into an LPM |
|
1788 //Later on, when OverrideLPM flag is cancelled, it would allow us to enforce requested LPM |
|
1789 if(iOverrideLPMRequests) |
|
1790 { |
|
1791 // We need to ensure the physical link is in active mode. |
|
1792 allowedModesMask = EActiveMode; |
|
1793 } |
|
1794 |
|
1795 TUint8 modeChangeMask = static_cast<TUint8>(requestedModeMask & allowedModesMask); |
|
1796 TUint8 modeCompareMask = 0; |
|
1797 |
|
1798 if(aLocalPriority) |
|
1799 { |
|
1800 // If we want local priority, we go with what we want to do |
|
1801 // irrespective of what the remote may have previously requested. |
|
1802 modeCompareMask = modeChangeMask; |
|
1803 } |
|
1804 else |
|
1805 { |
|
1806 // This logic allows us to see if the current low power mode has recently |
|
1807 // changed NOT because of a change in the local proxies' requests, but (probably) |
|
1808 // because a remote device has changed it.. |
|
1809 |
|
1810 // modeCompareMask should start only having zero bits where |
|
1811 // requestedModeMask has a zero bit and iPreviousRequestedModeMask does not |
|
1812 // i.e. a mode is newly no longer requested. |
|
1813 modeCompareMask = requestedModeMask | ~iPreviousRequestedModeMask; |
|
1814 |
|
1815 // Remove bits from modeCompareMask that are not in allowedModesMask |
|
1816 // We cannot stay in a power mode that we do not allow. |
|
1817 modeCompareMask &= allowedModesMask; |
|
1818 } |
|
1819 |
|
1820 iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value. |
|
1821 |
|
1822 TUint8 currentModeMask = static_cast<TUint8>(iLinkState.LinkMode()); |
|
1823 if(modeCompareMask & currentModeMask) |
|
1824 { |
|
1825 // The current state is the same as the permitted required role(s). |
|
1826 return KErrNone; |
|
1827 } |
|
1828 |
|
1829 if(modeChangeMask == EActiveMode && currentModeMask != EActiveMode) |
|
1830 { |
|
1831 // The current low power mode should be exited. |
|
1832 return RequestActive(); |
|
1833 } |
|
1834 |
|
1835 if(modeChangeMask != EActiveMode) |
|
1836 { |
|
1837 if(currentModeMask != EActiveMode) |
|
1838 { |
|
1839 // The system is currently in a low power mode. Exit this before |
|
1840 // entering the new mode. |
|
1841 TInt rerr = RequestActive(); |
|
1842 if(rerr != KErrNone) |
|
1843 { |
|
1844 return rerr; |
|
1845 } |
|
1846 } |
|
1847 |
|
1848 if(modeChangeMask & EHoldMode) |
|
1849 { |
|
1850 return RequestHold(); |
|
1851 } |
|
1852 if(modeChangeMask & ESniffMode) |
|
1853 { |
|
1854 return RequestSniff(); |
|
1855 } |
|
1856 if(modeChangeMask & EParkMode) |
|
1857 { |
|
1858 return RequestPark(); |
|
1859 } |
|
1860 } |
|
1861 |
|
1862 // This point in the code is reached if the Link Policy settings are |
|
1863 // changed but the mode is not. Return OK error code. |
|
1864 return KErrNone; |
|
1865 } |
|
1866 |
|
1867 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey) |
|
1868 { |
|
1869 LOG_FUNC |
|
1870 // We store the key for use if it succeeds. |
|
1871 iNewPinCode.Copy(aPassKey); |
|
1872 iNewPinCodeValid = ETrue; |
|
1873 } |
|
1874 |
|
1875 const TBTPinCode& CPhysicalLink::PassKey() const |
|
1876 { |
|
1877 LOG_FUNC |
|
1878 return iDevice.PassKey(); |
|
1879 } |
|
1880 |
|
1881 void CPhysicalLink::StartArbitrationTimer() const |
|
1882 { |
|
1883 LOG_FUNC |
|
1884 iArbitrationDelay->Start(); |
|
1885 } |
|
1886 |
|
1887 TInt CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy) |
|
1888 { |
|
1889 LOG_FUNC |
|
1890 // assume that we will be master until told otherwise |
|
1891 ASSERT_DEBUG(!IsConnected()); |
|
1892 |
|
1893 UpdateFromInquiryCache(); |
|
1894 |
|
1895 TUint8 psrm = iDevice.IsValidPageScanRepMode() ? iDevice.PageScanRepMode() : TUint8(KDefaultBluetoothPageScanRepMode); |
|
1896 TUint8 psm = iDevice.IsValidPageScanMode() ? iDevice.PageScanMode() : TUint8(KDefaultBluetoothPageScanMode); |
|
1897 TUint16 clockOffset = iDevice.IsValidClockOffset() ? iDevice.ClockOffset() : TUint16(KDefaultBluetoothClockOffset); |
|
1898 |
|
1899 TUint8 allowRoleSwitch = static_cast<TUint8>(iLinksMan.ActiveConnectRoleSwitchAllowed()); |
|
1900 |
|
1901 TUint16 pkt = KHCIDefaultPacketType; |
|
1902 |
|
1903 // optimise paging (as a best-effort attempt). |
|
1904 TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit); |
|
1905 iLinksMan.TryToChangePageTimeout(pagetimeout); |
|
1906 |
|
1907 TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch)); |
|
1908 if(ret==KErrNone) |
|
1909 { |
|
1910 iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending); |
|
1911 iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink); |
|
1912 iLinkState.SetLinkRole(EMaster); |
|
1913 } |
|
1914 |
|
1915 return ret; |
|
1916 } |
|
1917 |
|
1918 TInt CPhysicalLink::SCOConnect() |
|
1919 /** |
|
1920 A utility service provided to the SCO transport |
|
1921 We bring up a "default" SCO link, choosing the packet based on what we |
|
1922 know the controllers can support |
|
1923 */ |
|
1924 { |
|
1925 LOG_FUNC |
|
1926 return SCOConnect(EAnySCOPacket); |
|
1927 } |
|
1928 |
|
1929 TInt CPhysicalLink::SCOConnect(const TUint16 aUserHVPacketTypes) |
|
1930 /** |
|
1931 A utility service provided to the SCO transport |
|
1932 We bring up a SCO link which allows only the user specified packet types |
|
1933 Implementation of SCOSAP::SetOption guarantees aUserHVPacketTypes contains at |
|
1934 least one valid SCO packet type |
|
1935 */ |
|
1936 { |
|
1937 LOG_FUNC |
|
1938 TBTSCOPackets scoPackets = iLinksMan.LinkManagerProtocol().PacketsSupportedLocally().SCOPackets(); |
|
1939 |
|
1940 scoPackets &= aUserHVPacketTypes; |
|
1941 // combine with remote supported packets |
|
1942 scoPackets &= iRemoteFeatures.SCOPackets(); |
|
1943 |
|
1944 TInt ret; |
|
1945 |
|
1946 if (!scoPackets) |
|
1947 ret = KErrNotSupported; |
|
1948 else |
|
1949 { |
|
1950 // we put all in for now - if HW doesn't support that, the HCI can be changed |
|
1951 OverridePark(); |
|
1952 |
|
1953 TRAP(ret, iLinksMan.HCIFacade().SCOConnectL(Handle(), scoPackets, BDAddr())); |
|
1954 if(ret==KErrNone) |
|
1955 { |
|
1956 iLinksMan.Baseband().UpdateModel(Handle(), EACLLink, scoPackets, ESCOLink); |
|
1957 } |
|
1958 } |
|
1959 return ret; |
|
1960 } |
|
1961 |
|
1962 TInt CPhysicalLink::SynchronousConnect(TUint aTransmitBandwidth, TUint aReceiveBandwidth, |
|
1963 TUint16 aMaxLatency, TUint16 aVoiceSettings, |
|
1964 TUint8 aRetransmissionEffort, const TBTSyncPacketTypes aUserPacketTypes) |
|
1965 /** |
|
1966 A utility service provided to the eSCO transport |
|
1967 We bring up a eSCO link which allows only the user specified packet types |
|
1968 Implementation of SCOSAP::SetOption guarantees aUserPacketTypes contains at |
|
1969 least one valid SCO packet type |
|
1970 */ |
|
1971 { |
|
1972 LOG_FUNC |
|
1973 TBTSyncPacketTypes escoPackets = iLinksMan.LinkManagerProtocol().PacketsSupportedLocally().SyncPackets(); |
|
1974 |
|
1975 escoPackets &= aUserPacketTypes; |
|
1976 // combine with remote supported packets |
|
1977 escoPackets &= iRemoteFeatures.SyncPackets(); |
|
1978 |
|
1979 TInt ret; |
|
1980 |
|
1981 if (!escoPackets) |
|
1982 ret = KErrNotSupported; |
|
1983 else |
|
1984 { |
|
1985 // we put all in for now - if HW doesn't support that, the HCI can be changed |
|
1986 // THCIConnHandle aACLHandle, TUint aTransmitBandwidth, TUint aReceiveBandwidth, |
|
1987 // TUint16 aMaxLatency, TUint16 aVoiceSettings, TUint8 aRetransmissionEffort, |
|
1988 // TUint16 aPacketTypeMask |
|
1989 TRAP(ret, iLinksMan.HCIFacade().SetupSynchronousConnectionCommandL( |
|
1990 Handle(), |
|
1991 aTransmitBandwidth, aReceiveBandwidth, |
|
1992 aMaxLatency, aVoiceSettings, aRetransmissionEffort, |
|
1993 escoPackets, |
|
1994 BDAddr() |
|
1995 )); |
|
1996 if(ret==KErrNone) |
|
1997 { |
|
1998 iLinksMan.Baseband().UpdateModel(Handle(), EACLLink, escoPackets, EeSCOLink); |
|
1999 } |
|
2000 } |
|
2001 return ret; |
|
2002 } |
|
2003 |
|
2004 TInt CPhysicalLink::SubscribeProxySAP(CBTProxySAP& aProxySAP) |
|
2005 { |
|
2006 LOG_FUNC |
|
2007 // a new Proxy SAP wishes to attach to this physical SAP |
|
2008 #ifdef _DEBUG |
|
2009 // check to see if the same proxy is already there |
|
2010 TSglQueIter<CBTProxySAP> iter(iProxySAPs); |
|
2011 while (iter) |
|
2012 { |
|
2013 ASSERT_DEBUG(iter++!=&aProxySAP); |
|
2014 } |
|
2015 #endif |
|
2016 SubscribeLinkObserver(aProxySAP); |
|
2017 iProxySAPs.AddLast(aProxySAP); |
|
2018 Arbitrate(); |
|
2019 return KErrNone; |
|
2020 } |
|
2021 |
|
2022 void CPhysicalLink::UnsubscribeProxySAP(CBTProxySAP& aProxySAP) |
|
2023 { |
|
2024 LOG_FUNC |
|
2025 ASSERT_DEBUG(!iProxySAPs.IsEmpty()); |
|
2026 iProxySAPs.Remove(aProxySAP); |
|
2027 UnsubscribeLinkObserver(aProxySAP); |
|
2028 Arbitrate(); // good time to see what phy properties should be used |
|
2029 PhysicalLinkUserIdle(); |
|
2030 } |
|
2031 |
|
2032 |
|
2033 TInt CPhysicalLink::AttachLogicalLink(TLinkType aLink, CBTBasebandSAP& aSAP) |
|
2034 { |
|
2035 // effectively this part of this class encapsulates the Logical Transports |
|
2036 // but they're not really worthy of a class - just some understanding that they're |
|
2037 // not ignored |
|
2038 LOG_FUNC |
|
2039 TInt retVal = KErrNone; |
|
2040 |
|
2041 switch (aLink) |
|
2042 { |
|
2043 case EACLLink: |
|
2044 { |
|
2045 // it is important for error handling at the end of |
|
2046 // CPhysicalLink::ConnectionRequest that this remains an |
|
2047 // append i.e. 'aSAP' is added to the end of the queue |
|
2048 retVal = iACLLogicalLinks.Append(static_cast<CACLLink*>(&aSAP)); |
|
2049 break; |
|
2050 } |
|
2051 |
|
2052 case ESCOLink: |
|
2053 { |
|
2054 if (!(iRemoteFeatures.IsSCOLinkSupported())) |
|
2055 retVal = KErrNotSupported; |
|
2056 else |
|
2057 { |
|
2058 // Don't attach SCO if already exists, avoids confusion with some h/w. |
|
2059 // .....return the outcome, higher levels depend on this action |
|
2060 if (iSyncLogicalLink) |
|
2061 { |
|
2062 retVal = KErrInUse; |
|
2063 } |
|
2064 else |
|
2065 { |
|
2066 iSyncLogicalLink = static_cast<CSCOLink*>(&aSAP); |
|
2067 } |
|
2068 } |
|
2069 break; |
|
2070 } |
|
2071 |
|
2072 case EeSCOLink: |
|
2073 { |
|
2074 if (!(iRemoteFeatures.IsExtendedSCOLinkSupported())) |
|
2075 retVal = KErrNotSupported; |
|
2076 else |
|
2077 { |
|
2078 if (iSyncLogicalLink) |
|
2079 { |
|
2080 retVal = KErrInUse; |
|
2081 } |
|
2082 else |
|
2083 { |
|
2084 iSyncLogicalLink = static_cast<CeSCOLink*>(&aSAP); |
|
2085 } |
|
2086 } |
|
2087 break; |
|
2088 } |
|
2089 |
|
2090 default: |
|
2091 Panic(EBTUnknownLogicalLink); |
|
2092 } |
|
2093 |
|
2094 if (retVal == KErrNone) |
|
2095 { |
|
2096 RemoveIdleTimer(); |
|
2097 } |
|
2098 |
|
2099 return retVal; |
|
2100 } |
|
2101 |
|
2102 void CPhysicalLink::DetachLogicalLink(TLinkType aLink, CBTBasebandSAP& aSAP) |
|
2103 { |
|
2104 LOG_FUNC |
|
2105 LOG3(_L("CPhysicalLink: Logical Link type %d, 0x%08x detaching from PHY 0x%08x"), aLink, &aSAP, this); |
|
2106 switch (aLink) |
|
2107 { |
|
2108 case EACLLink: |
|
2109 { |
|
2110 #ifdef _DEBUG |
|
2111 TInt numFound = 0; |
|
2112 #endif |
|
2113 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
2114 { |
|
2115 if (iACLLogicalLinks[i] == &aSAP) |
|
2116 { |
|
2117 #ifdef _DEBUG |
|
2118 numFound++; |
|
2119 #endif |
|
2120 iACLLogicalLinks.Remove(i); // don't delete - it's not ours! |
|
2121 } |
|
2122 } |
|
2123 __ASSERT_DEBUG(numFound==1, Panic(EBTACLLogicalLinkBadDebind)); |
|
2124 break; |
|
2125 } |
|
2126 |
|
2127 case ESCOLink: |
|
2128 case EeSCOLink: |
|
2129 { |
|
2130 __ASSERT_DEBUG(iSyncLogicalLink==&aSAP, Panic(EBTSCOLogicalLinkBadDebind)); |
|
2131 iSyncLogicalLink = NULL; |
|
2132 break; |
|
2133 } |
|
2134 |
|
2135 default: |
|
2136 Panic(EBTUnknownLogicalLink); |
|
2137 } |
|
2138 } |
|
2139 |
|
2140 void CPhysicalLink::PhysicalLinkUserIdle() |
|
2141 { |
|
2142 LOG_FUNC |
|
2143 if(IsPhysicalLinkIdle() && iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp) |
|
2144 { |
|
2145 // try to stash device details - juice and last used date |
|
2146 TTime t; |
|
2147 t.UniversalTime(); |
|
2148 iDevice.SetUsed(t); |
|
2149 TRAPD(ignore, StoreDeviceL(ETrue)); //ETrue: new meaning - prevent addition of device in registry |
|
2150 |
|
2151 if (!iIdleTimerQueued) |
|
2152 // we don't want to send the read clock offset command more than one |
|
2153 // here, so just check if we already passed from here. |
|
2154 { |
|
2155 // Take this opportunity to get latest info on clock offset |
|
2156 // so that we can stash it in HR - subsequent connections may then be quicker |
|
2157 TRAP(ignore, iLinksMan.HCIFacade().ReadClockOffsetL(iHandle)); |
|
2158 // ignore error - was an optimisation |
|
2159 |
|
2160 // Disconnect the PHY, it is no longer required. |
|
2161 QueueIdleTimer(KPhysicalLinkIdleTimeout); |
|
2162 } |
|
2163 } |
|
2164 } |
|
2165 |
|
2166 |
|
2167 TBool CPhysicalLink::IsPhysicalLinkIdle() const |
|
2168 { |
|
2169 LOG_FUNC |
|
2170 TBool physicalLinkIdle = ETrue; |
|
2171 // Check ACL and SCO links. If any link is not idle, then the PHY remains |
|
2172 // active. |
|
2173 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
2174 { |
|
2175 physicalLinkIdle &= iACLLogicalLinks[i]->IsIdle(); |
|
2176 } |
|
2177 |
|
2178 if(iSyncLogicalLink) |
|
2179 { |
|
2180 physicalLinkIdle &= iSyncLogicalLink->IsIdle(); |
|
2181 } |
|
2182 |
|
2183 if (iPinRequester) |
|
2184 { |
|
2185 physicalLinkIdle = EFalse; |
|
2186 } |
|
2187 |
|
2188 if (IsAuthenticationPending()) |
|
2189 { |
|
2190 physicalLinkIdle = EFalse; |
|
2191 } |
|
2192 |
|
2193 return physicalLinkIdle; |
|
2194 } |
|
2195 |
|
2196 |
|
2197 void CPhysicalLink::QueueIdleTimer(TInt aTime) |
|
2198 /** |
|
2199 Queue idle timer entry. |
|
2200 When this timer expires, it'll call TryToClose, which actually |
|
2201 causes the thing to finally close down. |
|
2202 **/ |
|
2203 { |
|
2204 LOG_FUNC |
|
2205 if (!iIdleTimerQueued) |
|
2206 { |
|
2207 TCallBack cb(TerminateCallback, this); |
|
2208 iIdleTimerEntry.Set(cb); |
|
2209 iIdleTimeout = aTime; |
|
2210 BTSocketTimer::Queue(iIdleTimeout * 1000000, iIdleTimerEntry); |
|
2211 iIdleTimerQueued = ETrue; |
|
2212 } |
|
2213 } |
|
2214 |
|
2215 |
|
2216 void CPhysicalLink::RemoveIdleTimer() |
|
2217 /** |
|
2218 Called whenever we're opened. |
|
2219 Checks there are no idle timer entries queued. |
|
2220 **/ |
|
2221 { |
|
2222 LOG_FUNC |
|
2223 if (!iIdleTimerQueued) |
|
2224 { |
|
2225 // it's fine for callers to just try to remove the timer |
|
2226 return; |
|
2227 } |
|
2228 BTSocketTimer::Remove(iIdleTimerEntry); |
|
2229 iIdleTimerQueued = EFalse; |
|
2230 } |
|
2231 |
|
2232 void CPhysicalLink::QueueLPMOverrideTimer(TInt aTimeout) |
|
2233 /** |
|
2234 Queue LPM Override timer entry. |
|
2235 When this timer expires, it'll call UndoLPMOverride. |
|
2236 **/ |
|
2237 { |
|
2238 LOG_FUNC |
|
2239 __ASSERT_DEBUG(aTimeout!=0, Panic(EBTPhysicalLinksInvalidArgument)); |
|
2240 if (iLPMOverrideTimerQueued) |
|
2241 { |
|
2242 BTSocketTimer::Remove(iOverrideLPMTimerEntry); |
|
2243 } |
|
2244 BTSocketTimer::Queue(aTimeout, iOverrideLPMTimerEntry); |
|
2245 iLPMOverrideTimerQueued = ETrue; |
|
2246 } |
|
2247 |
|
2248 void CPhysicalLink::NotifyStateChange(TBTBasebandEventNotification& aEvent) |
|
2249 { |
|
2250 LOG_FUNC |
|
2251 // If this event is 'physical link down' / 'physical link error' then any ProxySAP |
|
2252 // subscribers will unsubscribe as a result of PhysicalLinkChange being called. |
|
2253 // This will result in the entry being removed from the iBasebandSubscribers array. |
|
2254 // Consequently the array must be traversed from end to start. |
|
2255 TDblQueIter<TPhysicalLinkObserverQLink> iter(iBasebandSubscribers); |
|
2256 TPhysicalLinkObserverQLink* l; |
|
2257 while ((l=iter++)!=NULL) |
|
2258 { |
|
2259 l->Item()->PhysicalLinkChange(aEvent, *this); |
|
2260 } |
|
2261 |
|
2262 if(((aEvent.EventType() & ENotifyActiveMode) || |
|
2263 (aEvent.EventType() & ENotifySniffMode)|| |
|
2264 (aEvent.EventType() & ENotifyParkMode)|| |
|
2265 (aEvent.EventType() & ENotifyHoldMode)) && |
|
2266 (aEvent.ErrorCode() == KErrNone)) |
|
2267 { |
|
2268 iArbitrationDelay->Start(); |
|
2269 } |
|
2270 } |
|
2271 |
|
2272 /*static*/ TInt CPhysicalLink::TerminateCallback(TAny* aCPhysicalLink) |
|
2273 { |
|
2274 LOG_STATIC_FUNC |
|
2275 CPhysicalLink* c = reinterpret_cast<CPhysicalLink*>(aCPhysicalLink); |
|
2276 c->iIdleTimerQueued = EFalse; |
|
2277 |
|
2278 TInt retVal = EFalse; |
|
2279 |
|
2280 // Queue another idle timer in case this disconnect fails |
|
2281 |
|
2282 // Check if the physical link is still idle after the timer. |
|
2283 if(c->IsPhysicalLinkIdle() && c->iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp) |
|
2284 { |
|
2285 // Increase the idle time for the next callback by just over 50% |
|
2286 TInt newIdleTime = (c->iIdleTimeout * 3)/2 + 1; |
|
2287 if (newIdleTime > KMaxPhysicalLinkIdleTimeout) |
|
2288 { |
|
2289 newIdleTime = KMaxPhysicalLinkIdleTimeout; |
|
2290 } |
|
2291 |
|
2292 c->QueueIdleTimer(newIdleTime); |
|
2293 if (c->Terminate(ERemoteUserEndedConnection) == KErrNone) |
|
2294 { |
|
2295 retVal = EFalse; |
|
2296 } |
|
2297 else |
|
2298 { |
|
2299 retVal = ETrue; |
|
2300 } |
|
2301 } |
|
2302 return retVal; |
|
2303 } |
|
2304 |
|
2305 TInt CPhysicalLink::Terminate(THCIErrorCode aReason) |
|
2306 { |
|
2307 LOG_FUNC |
|
2308 TInt err = KErrNone; |
|
2309 |
|
2310 if (iLinkState.LinkState() == TBTBasebandLinkState::ELinkPending) |
|
2311 { |
|
2312 // If the Link is not yet up then we cannot know the correct connection handle |
|
2313 // to disconnect so remember the request so we disconnect the link straight away |
|
2314 // after it does come up. |
|
2315 iDisconnectRequested = ETrue; |
|
2316 } |
|
2317 else |
|
2318 { |
|
2319 __ASSERT_DEBUG(iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp, Panic(EInvalidLinkStateDuringDisconnect)); |
|
2320 |
|
2321 TRAP(err, iDisconnectCtrl.Disconnect(aReason)); |
|
2322 } |
|
2323 |
|
2324 return err; |
|
2325 } |
|
2326 |
|
2327 void CPhysicalLink::SetModesAllowed(TUint8 aModesAllowed, TBool aRoleSwitchAllowed) |
|
2328 { |
|
2329 LOG_FUNC |
|
2330 TBTLinkModeSet supportedModes = iRemoteFeatures.LinkModes(); |
|
2331 aModesAllowed &= supportedModes; |
|
2332 aRoleSwitchAllowed &= IsRoleSwitchSupported(); |
|
2333 |
|
2334 if(aModesAllowed != iLinkPolicy.LowPowerModePolicy() || |
|
2335 aRoleSwitchAllowed != iLinkPolicy.IsSwitchAllowed()) |
|
2336 { |
|
2337 TLinkPolicy tempPolicy; |
|
2338 tempPolicy.SetModesAllowed(aModesAllowed); |
|
2339 tempPolicy.SetSwitchAllowed(aRoleSwitchAllowed); |
|
2340 |
|
2341 TRAPD(err, iLinksMan.HCIFacade().WriteLinkPolicySettingsL(Handle(), tempPolicy.LinkPolicy())); |
|
2342 |
|
2343 if (err==KErrNone) |
|
2344 { |
|
2345 iLinkPolicy = tempPolicy; |
|
2346 } |
|
2347 } |
|
2348 } |
|
2349 |
|
2350 void CPhysicalLink::NotifyLogicalLinkDown(TPhysicalLinkPort aPort) |
|
2351 { |
|
2352 LOG_FUNC |
|
2353 switch (aPort) |
|
2354 { |
|
2355 case EACLLink: |
|
2356 { |
|
2357 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
2358 { |
|
2359 // subscribers will unsubscribe as a result of this |
|
2360 // This will result in the entry being removed from the iACLLogicalLinks array. |
|
2361 // Consequently the array must be traversed from end to start. |
|
2362 iACLLogicalLinks[i]->Disconnection(); |
|
2363 } |
|
2364 break; |
|
2365 } |
|
2366 case ESCOLink: |
|
2367 case EeSCOLink: |
|
2368 { |
|
2369 if (iSyncLogicalLink) |
|
2370 { |
|
2371 iSyncLogicalLink->Disconnection(); |
|
2372 } |
|
2373 break; |
|
2374 } |
|
2375 |
|
2376 default: |
|
2377 Panic(EBTPhysicalLinkBadPort); |
|
2378 } |
|
2379 } |
|
2380 |
|
2381 void CPhysicalLink::NotifyLogicalLinkUp(const TBTConnect& aConnect) |
|
2382 { |
|
2383 LOG_FUNC |
|
2384 switch (aConnect.iLinkType) |
|
2385 { |
|
2386 case EACLLink: |
|
2387 { |
|
2388 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
2389 { |
|
2390 // all of them are open |
|
2391 iACLLogicalLinks[i]->ConnectComplete(aConnect); |
|
2392 } |
|
2393 break; |
|
2394 } |
|
2395 |
|
2396 case ESCOLink: |
|
2397 case EeSCOLink: |
|
2398 { |
|
2399 if (iSyncLogicalLink) |
|
2400 { |
|
2401 iSyncLogicalLink->ConnectComplete(aConnect); |
|
2402 } |
|
2403 break; |
|
2404 } |
|
2405 |
|
2406 default: |
|
2407 Panic(EBTPhysicalLinkBadPort); |
|
2408 } |
|
2409 } |
|
2410 |
|
2411 void CPhysicalLink::NotifyLogicalSyncLinkUp(const TBTConnect& aConnect, const TBTSyncConnectOpts& aSyncOpts) |
|
2412 { |
|
2413 LOG_FUNC |
|
2414 switch (aConnect.iLinkType) |
|
2415 { |
|
2416 case ESCOLink: |
|
2417 case EeSCOLink: |
|
2418 { |
|
2419 if (iSyncLogicalLink) |
|
2420 { |
|
2421 iSyncLogicalLink->SyncConnectComplete(aConnect, aSyncOpts); |
|
2422 } |
|
2423 break; |
|
2424 } |
|
2425 |
|
2426 default: |
|
2427 Panic(EBTPhysicalLinkBadPort); |
|
2428 } |
|
2429 } |
|
2430 |
|
2431 |
|
2432 void CPhysicalLink::NotifyLogicalLinkError(TPhysicalLinkPort aPort, TInt aError) |
|
2433 { |
|
2434 LOG_FUNC |
|
2435 switch (aPort) |
|
2436 { |
|
2437 case EACLLink: |
|
2438 { |
|
2439 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
2440 { |
|
2441 // all of them are open |
|
2442 iACLLogicalLinks[i]->Error(aError); |
|
2443 } |
|
2444 break; |
|
2445 } |
|
2446 |
|
2447 case ESCOLink: |
|
2448 case EeSCOLink: |
|
2449 { |
|
2450 if (iSyncLogicalLink) |
|
2451 { |
|
2452 iSyncLogicalLink->Error(aError); |
|
2453 } |
|
2454 break; |
|
2455 } |
|
2456 |
|
2457 default: |
|
2458 Panic(EBTPhysicalLinkBadPort); |
|
2459 } |
|
2460 } |
|
2461 |
|
2462 |
|
2463 TBool CPhysicalLink::IsModeSupportedRemotely(TBTLinkMode aMode) const |
|
2464 { |
|
2465 LOG_FUNC |
|
2466 return iRemoteFeatures.LinkModes() & aMode; |
|
2467 } |
|
2468 |
|
2469 TBool CPhysicalLink::IsEncryptionPauseResumeSupported() const |
|
2470 { |
|
2471 LOG_FUNC |
|
2472 return (iLinksMan.LinkManagerProtocol().IsEncryptionPauseResumeSupportedLocally() && iRemoteFeatures.IsEncryptionPauseResumeSupported()); |
|
2473 } |
|
2474 |
|
2475 TBool CPhysicalLink::IsEncryptionSupported() const |
|
2476 { |
|
2477 LOG_FUNC |
|
2478 return (iRemoteFeatures.IsEncryptionSupported() && iLinksMan.LinkManagerProtocol().IsEncryptionSupportedLocally()); |
|
2479 } |
|
2480 |
|
2481 TBool CPhysicalLink::IsRoleSwitchSupported() const |
|
2482 { |
|
2483 LOG_FUNC |
|
2484 // the physical link _can_ switch when encryption is on - see RequestChangeRole |
|
2485 return (iRemoteFeatures.IsRoleSwitchSupported() && iLinksMan.RoleSwitchAllowed()); |
|
2486 } |
|
2487 |
|
2488 |
|
2489 // |
|
2490 // Change the packet types allowed on the link. |
|
2491 // Note that this is only suitable for use on ACL and old-style (pre eSCO) SCO links. |
|
2492 // |
|
2493 TInt CPhysicalLink::ChangeConnectionPacketType(TUint16 aType) |
|
2494 { |
|
2495 LOG_FUNC |
|
2496 TInt rerr = KErrNone; |
|
2497 |
|
2498 // Build a mask of locally supported packet types (we shouldn't care about |
|
2499 // what the remote supports (this is alluded to in the spec) probably |
|
2500 // because they can change too. |
|
2501 |
|
2502 // DM1, DH1 and HV1 packets are always supported. |
|
2503 TUint16 supportedTypes = EPacketsDM1 | EPacketsDH1 | EPacketsHV1; |
|
2504 |
|
2505 // get extra locally-supported packets (our controller may not support things) |
|
2506 TBTFeatures localPackets = iLinksMan.LinkManagerProtocol().PacketsSupportedLocally(); |
|
2507 |
|
2508 // 3 slot ACL packets |
|
2509 if (localPackets[ESupportedThreeSlotPacketsBit]) |
|
2510 { |
|
2511 supportedTypes |= (EPacketsDM3 | EPacketsDH3); |
|
2512 } |
|
2513 |
|
2514 // 5 slot ACL packets |
|
2515 if (localPackets[ESupportedFiveSlotPacketsBit]) |
|
2516 { |
|
2517 supportedTypes |= (EPacketsDM5 | EPacketsDH5); |
|
2518 } |
|
2519 |
|
2520 // HV2 single-slot packets |
|
2521 if (localPackets[ESupportedHV2PacketsBit]) |
|
2522 { |
|
2523 supportedTypes |= EPacketsHV2; |
|
2524 } |
|
2525 |
|
2526 // HV3 single-slot packets |
|
2527 if (localPackets[ESupportedHV3PacketsBit]) |
|
2528 { |
|
2529 supportedTypes |= EPacketsHV3; |
|
2530 } |
|
2531 |
|
2532 // Note: If one of the following EDR bits is set it indicates that the EDR |
|
2533 // packet type shall NOT be used on this physical link. However, we must |
|
2534 // not set any packet types that are not supported, so check first. |
|
2535 |
|
2536 // EDR 2Mbps |
|
2537 if (localPackets[EEDR_ACL_2MbpsModeBit]) |
|
2538 { |
|
2539 supportedTypes |= EPackets2_DH1; |
|
2540 // EDR 3 slot ACL packets |
|
2541 if (localPackets[ESupportedEDRThreeSlotPacketsBit]) |
|
2542 { |
|
2543 supportedTypes |= EPackets2_DH3; |
|
2544 } |
|
2545 // EDR 5 slot ACL packets |
|
2546 if (localPackets[ESupportedEDRFiveSlotPacketsBit]) |
|
2547 { |
|
2548 supportedTypes |= EPackets2_DH5; |
|
2549 } |
|
2550 |
|
2551 // EDR 3Mbps - Have to have 2Mbps to have 3Mbps |
|
2552 if (localPackets[EEDR_ACL_3MbpsModeBit]) |
|
2553 { |
|
2554 supportedTypes |= EPackets3_DH1; |
|
2555 // EDR 3 slot ACL packets |
|
2556 if (localPackets[ESupportedEDRThreeSlotPacketsBit]) |
|
2557 { |
|
2558 supportedTypes |= EPackets3_DH3; |
|
2559 } |
|
2560 // EDR 5 slot ACL packets |
|
2561 if (localPackets[ESupportedEDRFiveSlotPacketsBit]) |
|
2562 { |
|
2563 supportedTypes |= EPackets3_DH5; |
|
2564 } |
|
2565 } |
|
2566 } |
|
2567 |
|
2568 supportedTypes &= aType; |
|
2569 // Check if the new supported types differ from the current configuration. |
|
2570 if(supportedTypes != iLinkState.PacketTypes()) |
|
2571 { |
|
2572 rerr = iLinksMan.HCIFacade().ChangeConnectionPacketType(iHandle, supportedTypes); |
|
2573 } |
|
2574 |
|
2575 if(rerr == KErrNone) |
|
2576 { |
|
2577 iConnectionPacketTypeChanged = ETrue; |
|
2578 } |
|
2579 |
|
2580 return rerr; |
|
2581 } |
|
2582 |
|
2583 TInt CPhysicalLink::ExitMode(TBTLinkMode aMode) |
|
2584 { |
|
2585 LOG_FUNC |
|
2586 return iLowPowModeCtrl.ExitMode(aMode, iHandle); |
|
2587 } |
|
2588 |
|
2589 TInt CPhysicalLink::RequestMode(TBTLinkMode aMode) |
|
2590 { |
|
2591 LOG_FUNC |
|
2592 if (!IsConnected()) |
|
2593 return KErrDisconnected; |
|
2594 |
|
2595 // if active mode is required, try to exit whatever Low Power mode we are in - |
|
2596 // if neither sniff nor park nothing will happen. |
|
2597 if(aMode == EActiveMode) |
|
2598 { |
|
2599 return ExitMode(iLinkState.LinkMode()); |
|
2600 } |
|
2601 |
|
2602 // now request this connection goes to requested mode |
|
2603 return iLowPowModeCtrl.ChangeMode(aMode, iHandle); |
|
2604 } |
|
2605 |
|
2606 TInt CPhysicalLink::RequestChangeRole(TBTBasebandRole aRole) |
|
2607 { |
|
2608 LOG_FUNC |
|
2609 TInt err = KErrNone; |
|
2610 |
|
2611 // Check that the requested role is not the current role. |
|
2612 if(iLinkState.LinkRole() != aRole) |
|
2613 { |
|
2614 if(!iLinkPolicy.IsSwitchAllowed()) |
|
2615 { |
|
2616 err = KErrNotSupported; |
|
2617 } |
|
2618 |
|
2619 // 1) Role switch is not allowed if there is a sync connection |
|
2620 // (or there is a sync connection negotiation in progress) |
|
2621 else if (HasSyncLink() || SyncConnectPending()) |
|
2622 { |
|
2623 err = KErrNotReady; |
|
2624 } |
|
2625 |
|
2626 // 2) Check if role switch is supported on the remote device |
|
2627 else if (!IsRoleSwitchSupported()) |
|
2628 { |
|
2629 err = KErrNotSupported; |
|
2630 } |
|
2631 |
|
2632 // 3) Check if role switch is supported locally |
|
2633 else if (!iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally()) |
|
2634 { |
|
2635 err = KErrNotSupported; |
|
2636 } |
|
2637 |
|
2638 // Same role request is already with LinkMgr, or most probably running just now |
|
2639 else if (iRoleSwitcher) |
|
2640 { |
|
2641 LOG(_L("CPhysicalLink - Same role change in progress!")) |
|
2642 err = KErrNone; |
|
2643 } |
|
2644 |
|
2645 // ok to change role |
|
2646 // we kick off a role switcher state machine, to remove LPM and encryption, prior to |
|
2647 // role switch |
|
2648 else |
|
2649 { |
|
2650 TRAP(err, iRoleSwitcher = CRoleSwitcher::NewL(iLinksMan, *this, aRole)); |
|
2651 } |
|
2652 } |
|
2653 #ifdef _DEBUG |
|
2654 else |
|
2655 { |
|
2656 LOG(_L("CPhysicalLink We are in requested role!!!")) |
|
2657 } |
|
2658 #endif |
|
2659 |
|
2660 return err; |
|
2661 } |
|
2662 |
|
2663 void CPhysicalLink::AsyncDeleteRoleSwitcher() |
|
2664 { |
|
2665 LOG_FUNC |
|
2666 iRoleSwitchCompleteCallBack->CallBack(); |
|
2667 } |
|
2668 |
|
2669 /*static*/ TInt CPhysicalLink::RoleSwitchCompleteCallBack(TAny* aPhysicalLink) |
|
2670 { |
|
2671 LOG_STATIC_FUNC |
|
2672 CPhysicalLink* physicalLink = static_cast<CPhysicalLink*>(aPhysicalLink); |
|
2673 physicalLink->DeleteRoleSwitcher(); |
|
2674 return EFalse; |
|
2675 } |
|
2676 |
|
2677 void CPhysicalLink::DeleteRoleSwitcher() |
|
2678 { |
|
2679 LOG_FUNC |
|
2680 delete iRoleSwitcher; |
|
2681 iRoleSwitcher = NULL; |
|
2682 } |
|
2683 |
|
2684 TBool CPhysicalLink::IsEncryptionDisabledForRoleSwitch() const |
|
2685 /** |
|
2686 If link is encrypted, but role switcher temporarily disabled encryption, returns true. |
|
2687 **/ |
|
2688 { |
|
2689 LOG_FUNC |
|
2690 if (iRoleSwitcher) |
|
2691 { |
|
2692 return iRoleSwitcher->IsEncryptionDisabledForRoleSwitch(); |
|
2693 } |
|
2694 return EFalse; |
|
2695 } |
|
2696 |
|
2697 TInt CPhysicalLink::OverridePark() |
|
2698 /** |
|
2699 A request has come in that requires us to ensure we are not parked. |
|
2700 |
|
2701 Try to make it happen |
|
2702 **/ |
|
2703 { |
|
2704 LOG_FUNC |
|
2705 iOverrideParkRequests = ETrue; |
|
2706 |
|
2707 // Only arbitrate if Park mode is currently active. |
|
2708 TInt rerr = KErrNone; |
|
2709 if(iLinkState.LinkMode() & EParkMode) |
|
2710 { |
|
2711 rerr = Arbitrate(); |
|
2712 } |
|
2713 return rerr; |
|
2714 } |
|
2715 |
|
2716 TInt CPhysicalLink::UndoOverridePark() |
|
2717 /** |
|
2718 A need to ensure we are not parked has gone. |
|
2719 |
|
2720 Try to go back to power mode resulting from an unoverriden Arbitrate |
|
2721 **/ |
|
2722 { |
|
2723 LOG_FUNC |
|
2724 iOverrideParkRequests = EFalse; |
|
2725 |
|
2726 //Arbitrate even if there isn't an outstanding local park mode request beacuse |
|
2727 //the remote device may be requesting park mode. |
|
2728 return Arbitrate(); |
|
2729 } |
|
2730 |
|
2731 TInt CPhysicalLink::OverrideLPMWithTimeout(TUint aTimeout) |
|
2732 { |
|
2733 LOG_FUNC |
|
2734 if(aTimeout == 0) |
|
2735 { |
|
2736 return KErrNone; //facility not wanted |
|
2737 } |
|
2738 |
|
2739 TInt rerr = OverrideLPM(); |
|
2740 QueueLPMOverrideTimer(aTimeout); |
|
2741 |
|
2742 return rerr; |
|
2743 } |
|
2744 |
|
2745 TInt CPhysicalLink::OverrideLPM() |
|
2746 /** |
|
2747 A request has come in that requires us to ensure we are not using |
|
2748 an LPM (low power mode). |
|
2749 |
|
2750 Try to make it happen |
|
2751 **/ |
|
2752 { |
|
2753 LOG_FUNC |
|
2754 iOverrideLPMRequests = ETrue; |
|
2755 |
|
2756 return Arbitrate(); |
|
2757 } |
|
2758 |
|
2759 /*static*/ TInt CPhysicalLink::OverrideLPMTimeoutCallback(TAny* aCPhysicalLink) |
|
2760 { |
|
2761 LOG_STATIC_FUNC |
|
2762 CPhysicalLink* c = reinterpret_cast<CPhysicalLink*>(aCPhysicalLink); |
|
2763 TInt err = c->UndoOverrideLPM(); |
|
2764 //we deliberately ignore this return value because we can't do anything to correct the error situation |
|
2765 if (KErrNone != err) |
|
2766 { |
|
2767 LOG2(_L("Physical link: UndoOverrideLPM returned an error %d on the connection 0x%08x"), err, c); |
|
2768 } |
|
2769 c->iLPMOverrideTimerQueued = EFalse; |
|
2770 return KErrNone; |
|
2771 } |
|
2772 |
|
2773 TInt CPhysicalLink::UndoOverrideLPM() |
|
2774 /** |
|
2775 A need to ensure we are not in LPM has gone. |
|
2776 |
|
2777 Try to go back to power mode resulting from an unoverriden Arbitrate |
|
2778 **/ |
|
2779 { |
|
2780 LOG_FUNC |
|
2781 iOverrideLPMRequests = EFalse; |
|
2782 |
|
2783 // Call Arbitrate(...) to determine if removing the override requires any change to |
|
2784 // the physical link state. |
|
2785 return Arbitrate(); |
|
2786 } |
|
2787 |
|
2788 // security stuff |
|
2789 // connection looks after this as it may be passively initiated and there wont |
|
2790 // be a accessrequester in those situations |
|
2791 |
|
2792 void CPhysicalLink::PinRequest(const TBTDevAddr& aAddr, MPINCodeResponseHandler& aRequester) |
|
2793 { |
|
2794 LOG_FUNC |
|
2795 // If we receive a Pin_Request while another is outstanding then the controller is faulty. |
|
2796 // So we just ignore any multiple requests, as they do not make sense. |
|
2797 // However, in UDEB we panic to raise awareness that the hardware is behaving incorrectly. |
|
2798 __ASSERT_DEBUG(!iPinRequester, Panic(EBTConnectionPINRequestedTwice)); |
|
2799 |
|
2800 SetAuthenticationPending(EPinRequestPending); // if not already set (because the remote initiated authentication). |
|
2801 |
|
2802 if (iPinRequester) |
|
2803 { |
|
2804 return; |
|
2805 } |
|
2806 |
|
2807 __ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress)); |
|
2808 |
|
2809 if(!IsPairable()) |
|
2810 { |
|
2811 aRequester.PINCodeRequestNegativeReply(aAddr); |
|
2812 return; |
|
2813 } |
|
2814 |
|
2815 TBTPinCode pinCode; |
|
2816 if(iLinksMan.PrefetchMan().IsPrefetchAvailable(aAddr, pinCode)) |
|
2817 { |
|
2818 aRequester.PINCodeRequestReply(aAddr, pinCode); |
|
2819 return; |
|
2820 } |
|
2821 |
|
2822 iPinHandler = &aRequester; |
|
2823 |
|
2824 TRAPD(err, DoPinRequestL(aAddr, *this)); // physical links will proxy a request. |
|
2825 |
|
2826 // if there is an error we should reply PIN negative... |
|
2827 if (err) |
|
2828 { |
|
2829 iPinHandler->PINCodeRequestNegativeReply(aAddr); |
|
2830 iPinHandler = NULL; |
|
2831 } |
|
2832 } |
|
2833 |
|
2834 void CPhysicalLink::DoPinRequestL(const TBTDevAddr& aAddr, MPINCodeResponseHandler& aResponseHandler) |
|
2835 { |
|
2836 LOG_FUNC |
|
2837 // Bluetooth is fairly poor at allowing name requests on partially connected links |
|
2838 // this typically occurs in security mode 3 |
|
2839 |
|
2840 // find out is it locally or remotley initiated authentication ... |
|
2841 TBool locallyInitiated; //Authentication |
|
2842 TBool strongKeyRequired; |
|
2843 TUint minPasskeyLength=0; |
|
2844 TUint recommendedPasskeyLength=0; |
|
2845 |
|
2846 iLinksMan.SecMan().GetPassKeyLengthAndOriginator(aAddr, minPasskeyLength, locallyInitiated, strongKeyRequired); |
|
2847 |
|
2848 /* If we have an activeAccessRequester and authentication was not actually required, |
|
2849 * this is a speculative authentication. |
|
2850 * In that case we did not expect to get a PinRequest. |
|
2851 * We leave as the link already exists, causing the PinRequest to get a negative reply. |
|
2852 */ |
|
2853 if(iDevice.IsValidLinkKey()) |
|
2854 { |
|
2855 CBTAccessRequester* activeAccessRequester = iLinksMan.SecMan().FindActiveAccessRequester(aAddr); |
|
2856 if (activeAccessRequester) |
|
2857 { |
|
2858 if (!activeAccessRequester->AuthenticationRequired()) |
|
2859 { |
|
2860 User::Leave(KErrAlreadyExists); |
|
2861 } |
|
2862 } |
|
2863 } |
|
2864 |
|
2865 /* If link is already authenticated with a link key greater than the currently required minimum key length, then store |
|
2866 * the current passkey length as a recommended length. If this recommendation is followed, then the strength of |
|
2867 * the current link key will be maintained. This recommended length is made available via |
|
2868 * TBTPinCodeEntryNotifierParams::RecommendedPinCodeMinLength(). |
|
2869 */ |
|
2870 TUint devicePasskeyLength = iDevice.PassKeyLength(); |
|
2871 if(iDevice.IsValidLinkKey()&&devicePasskeyLength>minPasskeyLength) |
|
2872 { |
|
2873 //Ignore the previous link key length if it is not at least the minimum we require now anyway. |
|
2874 recommendedPasskeyLength=devicePasskeyLength; |
|
2875 } |
|
2876 else |
|
2877 { |
|
2878 //Recommend the currently required minimum length. |
|
2879 recommendedPasskeyLength=minPasskeyLength; |
|
2880 } |
|
2881 |
|
2882 iPinRequester = CBTPinRequester::NewL(BDAddr(), aResponseHandler, iLinksMan.SecMan(), |
|
2883 minPasskeyLength, locallyInitiated, strongKeyRequired, recommendedPasskeyLength); |
|
2884 } |
|
2885 |
|
2886 TBool CPhysicalLink::LinkKeyRequestPending() |
|
2887 { |
|
2888 LOG_FUNC |
|
2889 return iAuthStateMask & ELinkKeyRequestPending; |
|
2890 } |
|
2891 |
|
2892 void CPhysicalLink::SetAuthenticationPending(TUint8 aState) |
|
2893 { |
|
2894 LOG_FUNC |
|
2895 iAuthStateMask |= aState; |
|
2896 LOG1(_L("SetAuthenticationPending: set state [%d] in an authentication state mask"), aState); |
|
2897 } |
|
2898 |
|
2899 void CPhysicalLink::AuthenticationComplete(TUint8 aState) |
|
2900 { |
|
2901 LOG_FUNC |
|
2902 iAuthStateMask &= ~aState; |
|
2903 LOG1(_L("AuthenticationComplete: reset state [%d] in an authentication state mask"), aState); |
|
2904 PhysicalLinkUserIdle(); |
|
2905 } |
|
2906 |
|
2907 TBool CPhysicalLink::IsPairable() const |
|
2908 { |
|
2909 // Determines if pairing can be performed on the physical link; |
|
2910 // it previously was determined by the PIN code notifier, but with |
|
2911 // 2.1 pairable mode has been replaced with bondable mode and |
|
2912 // so being pairable is now a function of the security level |
|
2913 // the device is operating under. |
|
2914 // Here the policy is as follows: |
|
2915 // |
|
2916 // Pairable if... |
|
2917 // 1) Not in paired only connections mode |
|
2918 // OR |
|
2919 // 2) The link is already authenticated |
|
2920 // OR |
|
2921 // 3) A logical link was locally initiated |
|
2922 // OR |
|
2923 // 4) A dedicated bonding attempt is in progress |
|
2924 // (it might be better to migrate dedicated bonding above the logical |
|
2925 // link to remove this special case...) |
|
2926 // |
|
2927 // This policy provides strong security for while not applying |
|
2928 // blanket restricts on explicit user requests (i.e. outgoing |
|
2929 // connections). |
|
2930 TBool locallyInitiatedLogicalLink = EFalse; |
|
2931 for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--) |
|
2932 { |
|
2933 if(iACLLogicalLinks[i]->IsLocallyInitiated()) |
|
2934 { |
|
2935 locallyInitiatedLogicalLink = ETrue; |
|
2936 } |
|
2937 } |
|
2938 return (!iLinksMan.IsAcceptPairedOnlyMode()) |
|
2939 || iLinkState.Authenticated() |
|
2940 || locallyInitiatedLogicalLink |
|
2941 || iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()); |
|
2942 } |
|
2943 |
|
2944 void CPhysicalLink::DeleteLinkKeyL() |
|
2945 /** |
|
2946 ensure that the LinkKey is removed from the device in the registry |
|
2947 **/ |
|
2948 { |
|
2949 LOG_FUNC |
|
2950 CBTLinkKeyDeleter* deleter = CBTLinkKeyDeleter::NewL(iRegSess, *this); |
|
2951 iRegistryHelpers.AddLast(*deleter); |
|
2952 deleter->Start(BDAddr()); |
|
2953 } |
|
2954 |
|
2955 TBool CPhysicalLink::IsConnectionRequestPending() const |
|
2956 { |
|
2957 LOG_FUNC |
|
2958 return iPendingConnection; |
|
2959 } |
|
2960 |
|
2961 void CPhysicalLink::PendingConnectionRequest(TInt /*aError*/) |
|
2962 { |
|
2963 LOG_FUNC |
|
2964 __ASSERT_DEBUG(iPendingConnection, Panic(EPhysicalLinkNoConnectionPending)); |
|
2965 |
|
2966 // Note: We could do something clever with the error code returned |
|
2967 // to prevent us thrashing in OOM situations, but it is complicated. |
|
2968 // We want to try again as now the pending connection address may |
|
2969 // now be in the cache even if we have a non-KErrNone error code, |
|
2970 // and so with that we will proceed sucessfully. But if we are |
|
2971 // deferred we may end up here again and again with, perhaps with a |
|
2972 // KErrNoMemory for example ... which is how the thrashing will occur. |
|
2973 // This thrashing will be limited however by the "Connection Accept |
|
2974 // Timeout" imposed by the controller on the host, and for this |
|
2975 // reason we live with it. |
|
2976 iPendingConnection = EFalse; |
|
2977 ConnectionRequest(iLastPendingConnection); |
|
2978 } |
|
2979 |
|
2980 TBool CPhysicalLink::IsPasskeyMinLengthOK() |
|
2981 { |
|
2982 LOG_FUNC |
|
2983 /** |
|
2984 check whether current passkey (retrieved from BTRegistry) is long enough to fulfill user passkey requirement |
|
2985 It must be called only when iDevice is ready and has LinkKey |
|
2986 **/ |
|
2987 __ASSERT_DEBUG(iDeviceResult==KErrNone && iDevice.IsValidLinkKey(), |
|
2988 Panic(EBTPhysicalLinkNotAuthenticated)); |
|
2989 |
|
2990 TUint newMinPasskeyLength=0; |
|
2991 TBool isPasskeyMinLengthOK = ETrue; |
|
2992 |
|
2993 TBool locInit, strongKey; |
|
2994 iLinksMan.SecMan().GetPassKeyLengthAndOriginator( iDevice.Address(), newMinPasskeyLength, locInit, strongKey); |
|
2995 |
|
2996 TBTPinCode currentPassKey = iDevice.PassKey(); |
|
2997 |
|
2998 // check current PIN code length against user requirement |
|
2999 if ( newMinPasskeyLength ) |
|
3000 { |
|
3001 if ( newMinPasskeyLength > currentPassKey().iLength ) |
|
3002 { |
|
3003 // longer PIN code is requested |
|
3004 isPasskeyMinLengthOK = EFalse; |
|
3005 } |
|
3006 } |
|
3007 |
|
3008 return isPasskeyMinLengthOK; |
|
3009 } |
|
3010 |
|
3011 void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& aAddr, MLinkKeyResponseHandler& /*aRequester*/) |
|
3012 { |
|
3013 LOG_FUNC |
|
3014 // we don't keep a copy of the device record - we just leave the one copy with |
|
3015 // the baseband - it can tell us if there's a link key |
|
3016 // we can tell if the baseband has the device record or not |
|
3017 |
|
3018 SetAuthenticationPending(ELinkKeyRequestPending); //authentication process started by remote |
|
3019 |
|
3020 // If the ACL to the peer device is not yet connected, and the peer has initiated |
|
3021 // authentication then it must be in security mode 3. This information is stored and |
|
3022 // if the connection completes the link will be set as authenticated. |
|
3023 if (!IsConnected()) |
|
3024 { |
|
3025 iPeerInSecurityMode3 = ETrue; |
|
3026 } |
|
3027 |
|
3028 if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) |
|
3029 { |
|
3030 // If we are doing DedicatedBonding then we should ignore the existing linkkey |
|
3031 // in an attempt to generate a stronger one if possible. |
|
3032 // Security mode 3 is a odd case - because we get what looks like double pairing (the remote |
|
3033 // initiated pairing on connection, then the dedicated bonding pairing). So we have removed |
|
3034 // this feature for security mode 3 devices...they will have to suffer for their transgressions |
|
3035 LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply")); |
|
3036 iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); |
|
3037 iRequireAuthenticatedLinkKey = EFalse; |
|
3038 } |
|
3039 else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey()) |
|
3040 { |
|
3041 if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) |
|
3042 { |
|
3043 LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) |
|
3044 iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); |
|
3045 } |
|
3046 else |
|
3047 { |
|
3048 if (iDevice.LinkKeyType() != ELinkKeyCombination) |
|
3049 { |
|
3050 if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) |
|
3051 { |
|
3052 LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) |
|
3053 iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); |
|
3054 } |
|
3055 else |
|
3056 { |
|
3057 LOG(_L("CPhysicalLink: Issuing link key to HC now")) |
|
3058 iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey()); |
|
3059 } |
|
3060 } |
|
3061 else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled) |
|
3062 { |
|
3063 LOG(_L("CPhysicalLink: Issuing link key to HC now")) |
|
3064 iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey()); |
|
3065 } |
|
3066 else |
|
3067 { |
|
3068 LOG(_L("CPhysicalLink: Current PIN code too short!")) |
|
3069 iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); |
|
3070 } |
|
3071 } |
|
3072 iRequireAuthenticatedLinkKey = EFalse; |
|
3073 } |
|
3074 else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound) |
|
3075 { |
|
3076 LOG(_L("CPhysicalLink: No Link key available for the device")); |
|
3077 iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); |
|
3078 iRequireAuthenticatedLinkKey = EFalse; |
|
3079 } |
|
3080 else |
|
3081 { |
|
3082 LOG(_L("CPhysicalLink: Waiting for link key from Registry!")) |
|
3083 // we're still waiting for the device....we'll respond when it turns up |
|
3084 iWaitingForLinkKeyFromRegistry = ETrue; |
|
3085 } |
|
3086 |
|
3087 } |
|
3088 |
|
3089 TInt CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin) const |
|
3090 { |
|
3091 ASSERT_DEBUG(aDevAddr == this->BDAddr()); |
|
3092 const_cast<CPhysicalLink*>(this)->PINCodeRequestReply(aDevAddr, aPin); |
|
3093 return KErrNone; |
|
3094 } |
|
3095 |
|
3096 TInt CPhysicalLink::PINCodeRequestNegativeReply(const TBTDevAddr& aDevAddr) const |
|
3097 { |
|
3098 ASSERT_DEBUG(aDevAddr == this->BDAddr()); |
|
3099 const_cast<CPhysicalLink*>(this)->PINCodeRequestNegativeReply(aDevAddr); |
|
3100 return KErrNone; |
|
3101 } |
|
3102 |
|
3103 void CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin) |
|
3104 { |
|
3105 SetPassKey(aPin); |
|
3106 PinRequestSent(); |
|
3107 iPinHandler->PINCodeRequestReply(aDevAddr, aPin); |
|
3108 PinRequestComplete(); |
|
3109 } |
|
3110 |
|
3111 void CPhysicalLink::PINCodeRequestNegativeReply(const TBTDevAddr& aDevAddr) |
|
3112 { |
|
3113 iPinHandler->PINCodeRequestNegativeReply(aDevAddr); |
|
3114 PinRequestComplete(); |
|
3115 } |
|
3116 |
|
3117 |
|
3118 void CPhysicalLink::PinRequestSent() |
|
3119 { |
|
3120 LOG_FUNC |
|
3121 iLinkKeyPending = ETrue; |
|
3122 } |
|
3123 |
|
3124 void CPhysicalLink::PinRequestComplete() |
|
3125 /** |
|
3126 Just clean up now that PIN request has completed |
|
3127 **/ |
|
3128 { |
|
3129 LOG_FUNC |
|
3130 delete iPinRequester; |
|
3131 iPinRequester = NULL; |
|
3132 iPinHandler = NULL; |
|
3133 AuthenticationComplete(EPinRequestPending); |
|
3134 } |
|
3135 |
|
3136 |
|
3137 TInt CPhysicalLink::RequestHold() |
|
3138 { |
|
3139 LOG_FUNC |
|
3140 return RequestMode(EHoldMode); |
|
3141 } |
|
3142 |
|
3143 TInt CPhysicalLink::RequestSniff() |
|
3144 { |
|
3145 LOG_FUNC |
|
3146 return RequestMode(ESniffMode); |
|
3147 } |
|
3148 |
|
3149 TInt CPhysicalLink::RequestPark() |
|
3150 { |
|
3151 LOG_FUNC |
|
3152 return RequestMode(EParkMode); |
|
3153 } |
|
3154 |
|
3155 TInt CPhysicalLink::RequestActive() |
|
3156 { |
|
3157 LOG_FUNC |
|
3158 return RequestMode(EActiveMode); |
|
3159 } |
|
3160 |
|
3161 void CPhysicalLink::ReadNewPhysicalLinkMetricValue(TUint aIoctlName, CBTProxySAP& aSAP, TInt aCurrentValue) |
|
3162 { |
|
3163 LOG_FUNC |
|
3164 iPhysicalLinkMetrics->ReadNewPhysicalLinkMetricValue(aIoctlName, aSAP, aCurrentValue); |
|
3165 } |
|
3166 |
|
3167 void CPhysicalLink::GetCurrentBasebandState(TBTBasebandEventNotification & aEvent) |
|
3168 { |
|
3169 LOG_FUNC |
|
3170 // Populate the event with the current baseband state. |
|
3171 TUint32 events = 0; |
|
3172 switch(iLinkState.LinkRole()) |
|
3173 { |
|
3174 case EMaster: |
|
3175 events |= ENotifyMaster; |
|
3176 break; |
|
3177 case ESlave: |
|
3178 events |= ENotifySlave; |
|
3179 break; |
|
3180 case ERoleUnknown: |
|
3181 default: |
|
3182 break; |
|
3183 }; |
|
3184 |
|
3185 switch(iLinkState.LinkMode()) |
|
3186 { |
|
3187 case EActiveMode: |
|
3188 events |= ENotifyActiveMode; |
|
3189 break; |
|
3190 case ESniffMode: |
|
3191 events |= ENotifySniffMode; |
|
3192 break; |
|
3193 case EParkMode: |
|
3194 events |= ENotifyParkMode; |
|
3195 break; |
|
3196 case EHoldMode: |
|
3197 events |= ENotifyHoldMode; |
|
3198 break; |
|
3199 case EScatterMode: |
|
3200 default: |
|
3201 break; |
|
3202 }; |
|
3203 |
|
3204 switch(iLinkState.MaxSlots()) |
|
3205 { |
|
3206 case 1: |
|
3207 events |= ENotifyMaxSlots1; |
|
3208 break; |
|
3209 case 3: |
|
3210 events |= ENotifyMaxSlots3; |
|
3211 break; |
|
3212 case 5: |
|
3213 events |= ENotifyMaxSlots5; |
|
3214 break; |
|
3215 default: |
|
3216 break; |
|
3217 }; |
|
3218 |
|
3219 TUint16 packetTypes = iLinkState.PacketTypes(); |
|
3220 if(packetTypes & EPacketsDM1) |
|
3221 { |
|
3222 events |= ENotifyPacketsDM1; |
|
3223 } |
|
3224 if(packetTypes & EPacketsDM3) |
|
3225 { |
|
3226 events |= ENotifyPacketsDM3; |
|
3227 } |
|
3228 if(packetTypes & EPacketsDM5) |
|
3229 { |
|
3230 events |= ENotifyPacketsDM5; |
|
3231 } |
|
3232 if(packetTypes & EPacketsDH1) |
|
3233 { |
|
3234 events |= ENotifyPacketsDH1; |
|
3235 } |
|
3236 if(packetTypes & EPacketsDH3) |
|
3237 { |
|
3238 events |= ENotifyPacketsDH3; |
|
3239 } |
|
3240 if(packetTypes & EPacketsDH5) |
|
3241 { |
|
3242 events |= ENotifyPacketsDH5; |
|
3243 } |
|
3244 if(packetTypes & EPacketsHV1) |
|
3245 { |
|
3246 events |= ENotifyPacketsHV1; |
|
3247 } |
|
3248 if(packetTypes & EPacketsHV2) |
|
3249 { |
|
3250 events |= ENotifyPacketsHV2; |
|
3251 } |
|
3252 if(packetTypes & EPacketsHV3) |
|
3253 { |
|
3254 events |= ENotifyPacketsHV3; |
|
3255 } |
|
3256 |
|
3257 if(iLinkState.Authenticated()) |
|
3258 { |
|
3259 events |= ENotifyAuthenticationComplete; |
|
3260 } |
|
3261 |
|
3262 if(iLinkState.Encrypted()) |
|
3263 { |
|
3264 events |= ENotifyEncryptionChangeOn; |
|
3265 } |
|
3266 else |
|
3267 { |
|
3268 events |= ENotifyEncryptionChangeOff; |
|
3269 } |
|
3270 |
|
3271 switch(iLinkState.LinkState()) |
|
3272 { |
|
3273 case TBTBasebandLinkState::ELinkUp: |
|
3274 events |= ENotifyPhysicalLinkUp; |
|
3275 |
|
3276 if (iSyncLogicalLink) |
|
3277 { |
|
3278 if (iSyncLogicalLink->IsOpen()) |
|
3279 { |
|
3280 events |= ENotifySynchronousLinkUp; |
|
3281 } |
|
3282 else |
|
3283 { |
|
3284 events |= ENotifySynchronousLinkDown; |
|
3285 } |
|
3286 } |
|
3287 break; |
|
3288 case TBTBasebandLinkState::ELinkDown: |
|
3289 events |= ENotifyPhysicalLinkDown; |
|
3290 break; |
|
3291 default: |
|
3292 break; |
|
3293 }; |
|
3294 |
|
3295 aEvent.SetEventType(events); |
|
3296 aEvent.SetErrorCode(0); |
|
3297 } |
|
3298 |
|
3299 TBool CPhysicalLink::ACLConnectPending() const |
|
3300 { |
|
3301 LOG_FUNC |
|
3302 return !IsConnected(); |
|
3303 } |
|
3304 |
|
3305 TBool CPhysicalLink::SyncConnectPending() const |
|
3306 { |
|
3307 LOG_FUNC |
|
3308 if (!iSyncLogicalLink) |
|
3309 { |
|
3310 return EFalse; |
|
3311 } |
|
3312 |
|
3313 return iSyncLogicalLink->ConnectPending(); |
|
3314 } |
|
3315 |
|
3316 TInt CPhysicalLink::ManageEncryptionEnforcement(THCIEncryptModeFlag aEnable) |
|
3317 { |
|
3318 LOG_FUNC |
|
3319 // Although this code has been written as if this method could be called more then once, |
|
3320 // with different argument values: |
|
3321 // ChangeEncryption() (and then ManageEncryptionEnforcement()) is called only |
|
3322 // once and only with aEnable = EPointToPointEncryption. |
|
3323 // It's called if during the physical link creation the encryption is requested. |
|
3324 // That is because the assertion below. |
|
3325 __ASSERT_DEBUG(aEnable != EEncryptionDisabled, Panic(EBTInvalidEncryptionDisableRequest)); |
|
3326 |
|
3327 // although "&& (iEncryptionEnforcer)" is not necessary, we leave it because |
|
3328 // clarify that we had asked for the encryption, so it's our responsability to |
|
3329 // delete iEncryptionEnforcer. |
|
3330 if ((aEnable == EEncryptionDisabled) && (iEncryptionEnforcer)) |
|
3331 { |
|
3332 delete iEncryptionEnforcer; |
|
3333 iEncryptionEnforcer = NULL; |
|
3334 } |
|
3335 else if ((aEnable != EEncryptionDisabled) && (!iEncryptionEnforcer)) |
|
3336 { |
|
3337 TRAPD(err, iEncryptionEnforcer = CEncryptionEnforcer::NewL(*this, aEnable)); |
|
3338 return err; |
|
3339 } |
|
3340 return KErrNone; |
|
3341 } |
|
3342 |
|
3343 TBasebandTime CPhysicalLink::CalculatePageTimeout(TBasebandPageTimePolicy aPolicy, TUint8 aRepMode, TBool aValidClockOffset) |
|
3344 { |
|
3345 LOG_FUNC |
|
3346 TBasebandTime pageTimeout = TBasebandPolicy::KPageTimeoutR0; |
|
3347 |
|
3348 switch (aRepMode) |
|
3349 { |
|
3350 // PSRM defined in spec |
|
3351 case 0x00: |
|
3352 // already set |
|
3353 break; |
|
3354 |
|
3355 case 0x01: |
|
3356 pageTimeout = TBasebandPolicy::KPageTimeoutR1; |
|
3357 break; |
|
3358 |
|
3359 case 0x02: |
|
3360 // fallthrough |
|
3361 default: |
|
3362 pageTimeout = TBasebandPolicy::KPageTimeoutR2; |
|
3363 break; |
|
3364 } |
|
3365 |
|
3366 if (!aValidClockOffset) |
|
3367 { |
|
3368 pageTimeout*=2; |
|
3369 } |
|
3370 else |
|
3371 { |
|
3372 // normalPageTimeout+=5; //slots |
|
3373 } |
|
3374 |
|
3375 // policy may not be valid - or dontcare/normal |
|
3376 switch (aPolicy) |
|
3377 { |
|
3378 case EPagingBestEffort: |
|
3379 pageTimeout = static_cast<TBasebandTime>(TBasebandPolicy::KBestEffortTimeMultiplier * pageTimeout); |
|
3380 break; |
|
3381 |
|
3382 case EPagingQuick: |
|
3383 pageTimeout = static_cast<TBasebandTime>(TBasebandPolicy::KQuickTimeMultiplier * pageTimeout); |
|
3384 break; |
|
3385 |
|
3386 default: |
|
3387 break; |
|
3388 // leave as is |
|
3389 |
|
3390 } |
|
3391 return pageTimeout; |
|
3392 } |
|
3393 |
|
3394 // CArbitrationDelayTimer |
|
3395 |
|
3396 CArbitrationDelayTimer::CArbitrationDelayTimer(CPhysicalLink* aParent) |
|
3397 :CTimer(CActive::EPriorityStandard), |
|
3398 iParent(aParent) |
|
3399 { |
|
3400 LOG_FUNC |
|
3401 } |
|
3402 |
|
3403 void CArbitrationDelayTimer::ConstructL() |
|
3404 { |
|
3405 LOG_FUNC |
|
3406 CTimer::ConstructL(); |
|
3407 CActiveScheduler::Add(this); |
|
3408 } |
|
3409 |
|
3410 CArbitrationDelayTimer* CArbitrationDelayTimer::NewL(CPhysicalLink* aParent) |
|
3411 { |
|
3412 LOG_STATIC_FUNC |
|
3413 CArbitrationDelayTimer* self = new (ELeave) CArbitrationDelayTimer(aParent); |
|
3414 CleanupStack::PushL(self); |
|
3415 self->ConstructL(); |
|
3416 CleanupStack::Pop(self); |
|
3417 return self; |
|
3418 } |
|
3419 |
|
3420 void CArbitrationDelayTimer::Start() |
|
3421 { |
|
3422 LOG_FUNC |
|
3423 if (IsActive()) |
|
3424 { |
|
3425 Cancel(); |
|
3426 } |
|
3427 After(KBTArbitrationDelay); |
|
3428 } |
|
3429 |
|
3430 |
|
3431 void CArbitrationDelayTimer::RunL() |
|
3432 /** |
|
3433 Allow arbitration of low power modes when the timer expires |
|
3434 **/ |
|
3435 { |
|
3436 LOG_FUNC |
|
3437 if (iParent) |
|
3438 { |
|
3439 iParent->Arbitrate(); |
|
3440 } |
|
3441 } |
|
3442 |
|
3443 TInt CPhysicalLink::GetNumPendingHandles(TInt& aConnectionHandles, TLinkType aLinkType) const |
|
3444 { |
|
3445 LOG_FUNC |
|
3446 aConnectionHandles = 0; |
|
3447 |
|
3448 switch(aLinkType) |
|
3449 { |
|
3450 case EeSCOLink: |
|
3451 |
|
3452 if (iSyncLogicalLink && iSyncLogicalLink->ConnectPending()) |
|
3453 { |
|
3454 // Currently there is a maximum of one synclink per |
|
3455 // physical link |
|
3456 |
|
3457 ++aConnectionHandles; |
|
3458 } |
|
3459 |
|
3460 break; |
|
3461 |
|
3462 case ESCOLink: |
|
3463 |
|
3464 if (iSyncLogicalLink && iSyncLogicalLink->ConnectPending()) |
|
3465 { |
|
3466 // Currently there is a maximum of one synclink per |
|
3467 // physical link |
|
3468 |
|
3469 ++aConnectionHandles; |
|
3470 } |
|
3471 |
|
3472 break; |
|
3473 |
|
3474 case EACLLink: |
|
3475 |
|
3476 if (!IsConnected()) |
|
3477 { |
|
3478 // Currently there is a maximum of one asynclink per |
|
3479 // physical link |
|
3480 ++aConnectionHandles; |
|
3481 } |
|
3482 |
|
3483 break; |
|
3484 |
|
3485 default: |
|
3486 return KErrUnknown; |
|
3487 } |
|
3488 |
|
3489 return KErrNone; |
|
3490 } |
|
3491 |
|
3492 TInt CPhysicalLink::GetConnectionHandles(RHCIConnHandleArray& aConnectionHandles, |
|
3493 TLinkType aLinkType) const |
|
3494 { |
|
3495 LOG_FUNC |
|
3496 // Always append to client supplied array - do not clear the |
|
3497 // contents. Only return connected handles. |
|
3498 |
|
3499 switch(aLinkType) |
|
3500 { |
|
3501 case EeSCOLink: |
|
3502 |
|
3503 if (!iSyncLogicalLink || iSyncLogicalLink->ConnectPending()) |
|
3504 { |
|
3505 return KErrNone; |
|
3506 } |
|
3507 |
|
3508 if (iSyncLogicalLink->LinkType() == EeSCOLink) |
|
3509 { |
|
3510 // Currently there is a maximum of one synclink per |
|
3511 // physical link |
|
3512 aConnectionHandles.Append(iSyncLogicalLink->Handle()); |
|
3513 } |
|
3514 |
|
3515 break; |
|
3516 |
|
3517 case ESCOLink: |
|
3518 |
|
3519 if (!iSyncLogicalLink || iSyncLogicalLink->ConnectPending()) |
|
3520 { |
|
3521 return KErrNone; |
|
3522 } |
|
3523 |
|
3524 if (iSyncLogicalLink->LinkType() == ESCOLink) |
|
3525 { |
|
3526 // Currently there is a maximum of one synclink per |
|
3527 // physical link |
|
3528 aConnectionHandles.Append(iSyncLogicalLink->Handle()); |
|
3529 } |
|
3530 |
|
3531 break; |
|
3532 |
|
3533 case EACLLink: |
|
3534 // Currently there is a maximum of one asynclink per physical |
|
3535 // link and they share the same handle - this may change in |
|
3536 // the future for QoS. |
|
3537 |
|
3538 if (!IsConnected()) |
|
3539 { |
|
3540 return KErrNone; |
|
3541 } |
|
3542 |
|
3543 aConnectionHandles.Append(iHandle); |
|
3544 break; |
|
3545 |
|
3546 default: |
|
3547 return KErrUnknown; |
|
3548 } |
|
3549 |
|
3550 return KErrNone; |
|
3551 } |
|
3552 |
|
3553 void CPhysicalLink::IOCapabilityAskForResponse(THCIIoCapability aIOCapability, THCIOobDataPresence aOOBDataPresence, THCIAuthenticationRequirement aAuthenticationRequirement) |
|
3554 { |
|
3555 LOG_FUNC |
|
3556 iIOCapsReceived = ETrue; |
|
3557 iIOCapability = aIOCapability; |
|
3558 iOOBDataPresence = aOOBDataPresence; |
|
3559 iAuthenticationRequirement = aAuthenticationRequirement; |
|
3560 |
|
3561 //If we haven't determined the SSP pairing mode till now then enable it and notify the state m/c. |
|
3562 //This condition is to cater the fast remote device which responds very quickly, |
|
3563 //even before we determine whether it supports simple pairing!*/ |
|
3564 __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); |
|
3565 if(SimplePairingMode() == EPhySimplePairingUndefined) |
|
3566 { |
|
3567 //Since we have received a I/O cap response the simple pairing must be enabled |
|
3568 iSimplePairingMode = EPhySimplePairingEnabled; |
|
3569 iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); |
|
3570 } |
|
3571 } |
|
3572 |
|
3573 |
|
3574 TBool CPhysicalLink::AuthWithMITM() const |
|
3575 { |
|
3576 LOG_FUNC |
|
3577 return (iLocalMITM || (iAuthenticationRequirement & KAuthenticationMitmReqMask)) |
|
3578 && (iIOCapability != EIOCapsNoInputNoOutput); |
|
3579 } |
|
3580 |
|
3581 void CPhysicalLink::SetLocalMITM(TBool aLocalMITM) |
|
3582 { |
|
3583 LOG_FUNC |
|
3584 iLocalMITM = aLocalMITM; |
|
3585 } |
|
3586 |
|
3587 TPhysicalLinkSimplePairingMode CPhysicalLink::SimplePairingMode() const |
|
3588 { |
|
3589 LOG_FUNC |
|
3590 return iSimplePairingMode; |
|
3591 } |
|
3592 |
|
3593 TBool CPhysicalLink::HasRemoteOobData() const |
|
3594 { |
|
3595 LOG_FUNC |
|
3596 return iLinksMan.SecMan().OobDataManager().HasRemoteOobData(BDAddr()); |
|
3597 } |
|
3598 |
|
3599 THCIAuthenticationRequirement CPhysicalLink::AuthenticationRequirement() const |
|
3600 { |
|
3601 LOG_FUNC |
|
3602 return iAuthenticationRequirement; |
|
3603 } |
|
3604 |
|
3605 void CPhysicalLink::NewNumericComparatorL(const TBTDevAddr aAddr, |
|
3606 CBTSecMan& aSecMan, |
|
3607 TUint32 aNumericValue, |
|
3608 TBool aInternallyInitiated) |
|
3609 { |
|
3610 LOG_FUNC |
|
3611 __ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress)); |
|
3612 |
|
3613 // Check remote IO capabilities so that the BTNumericComparator can tell the user |
|
3614 TBTNumericComparisonParams::TComparisonScenario compScenario = TBTNumericComparisonParams::ERemoteCanConfirm; |
|
3615 if(iIOCapsReceived) |
|
3616 { |
|
3617 switch(iIOCapability) |
|
3618 { |
|
3619 case EIOCapsDisplayOnly: |
|
3620 compScenario = TBTNumericComparisonParams::ERemoteCannotConfirm; |
|
3621 break; |
|
3622 case EIOCapsDisplayYesNo: |
|
3623 compScenario = TBTNumericComparisonParams::ERemoteCanConfirm; |
|
3624 break; |
|
3625 default: |
|
3626 // If iIOCapability = EIOCapsKeyboardOnly or EIOCapsNoInputNoOutput |
|
3627 // we should not be using a Numeric Comparitor |
|
3628 __ASSERT_DEBUG(EFalse, Panic(EUnexpectedIOCapability)); |
|
3629 break; |
|
3630 } |
|
3631 } |
|
3632 iNumericComparator = CBTNumericComparator::NewL(aAddr, aSecMan, aNumericValue, compScenario, aInternallyInitiated); |
|
3633 } |
|
3634 |
|
3635 CBTNumericComparator* CPhysicalLink::InstanceNumericComparator() const |
|
3636 { |
|
3637 LOG_FUNC |
|
3638 return iNumericComparator; |
|
3639 } |
|
3640 |
|
3641 TBool CPhysicalLink::IsNumericComparatorActive()const |
|
3642 { |
|
3643 LOG_FUNC |
|
3644 return iNumericComparator->IsActive(); |
|
3645 } |
|
3646 |
|
3647 void CPhysicalLink::DeleteNumericComparator() |
|
3648 { |
|
3649 LOG_FUNC |
|
3650 delete iNumericComparator; |
|
3651 iNumericComparator = NULL; |
|
3652 } |
|
3653 void CPhysicalLink::CancelNumericComparator() |
|
3654 { |
|
3655 LOG_FUNC |
|
3656 iNumericComparator->Cancel(); |
|
3657 } |
|
3658 |
|
3659 void CPhysicalLink::NewPasskeyEntryL(const TBTDevAddr aAddr, |
|
3660 CBTSecMan& aSecMan, |
|
3661 TUint32 aNumericValue, |
|
3662 TBool aInternallyInitiated) |
|
3663 { |
|
3664 LOG_FUNC |
|
3665 iPasskeyEntry = CBTPasskeyEntry::NewL(aAddr, aSecMan, aNumericValue, aInternallyInitiated); |
|
3666 } |
|
3667 |
|
3668 CBTPasskeyEntry* CPhysicalLink::InstancePasskeyEntry() const |
|
3669 { |
|
3670 LOG_FUNC |
|
3671 return iPasskeyEntry; |
|
3672 } |
|
3673 |
|
3674 TBool CPhysicalLink::IsPasskeyEntryActive()const |
|
3675 { |
|
3676 LOG_FUNC |
|
3677 return iPasskeyEntry->IsActive(); |
|
3678 } |
|
3679 |
|
3680 void CPhysicalLink::DeletePasskeyEntry() |
|
3681 { |
|
3682 LOG_FUNC |
|
3683 delete iPasskeyEntry; |
|
3684 iPasskeyEntry = NULL; |
|
3685 } |
|
3686 |
|
3687 void CPhysicalLink::CancelPasskeyEntry() |
|
3688 { |
|
3689 LOG_FUNC |
|
3690 iPasskeyEntry->Cancel(); |
|
3691 } |
|
3692 |
|
3693 void CPhysicalLink::PasskeyEntryKeyPressed(THCIPasskeyEntryNotificationType aKey) |
|
3694 { |
|
3695 LOG_FUNC |
|
3696 iPasskeyEntry->KeyPressed(aKey); |
|
3697 } |
|
3698 |
|
3699 |
|
3700 TBasebandTime CPhysicalLink::GetSniffInterval() const |
|
3701 { |
|
3702 return iSniffInterval; |
|
3703 } |
|
3704 |
|
3705 // |
|
3706 // TLowPowModeCmdController |
|
3707 // |
|
3708 |
|
3709 TLowPowModeCmdController::TLowPowModeCmdController(CPhysicalLink& aLink, MHCICommandQueue& aCmdController) : |
|
3710 iParent(aLink), |
|
3711 iCmdController(aCmdController), |
|
3712 iOutstandingCmd(EFalse) |
|
3713 { |
|
3714 LOG_FUNC |
|
3715 } |
|
3716 |
|
3717 void TLowPowModeCmdController::Abort() |
|
3718 { |
|
3719 LOG_FUNC |
|
3720 LOG(_L("TLowPowModeCmdController::Abort")); |
|
3721 iCmdController.MhcqRemoveAllCommands(*this); |
|
3722 } |
|
3723 |
|
3724 void TLowPowModeCmdController::DoExitModeL(TBTLinkMode aMode, THCIConnHandle aConnHandle) |
|
3725 { |
|
3726 LOG_FUNC |
|
3727 LOG2(_L("TLowPowModeCmdController::DoExitModeL: mode:%d iOutstandingCmd:%d"), aMode, iOutstandingCmd); |
|
3728 if (!iOutstandingCmd) |
|
3729 { |
|
3730 switch (aMode) |
|
3731 { |
|
3732 case ESniffMode: |
|
3733 { |
|
3734 ExitSniffL(aConnHandle); |
|
3735 break; |
|
3736 } |
|
3737 case EParkMode: |
|
3738 { |
|
3739 ExitParkL(aConnHandle); |
|
3740 break; |
|
3741 } |
|
3742 // Not possile to prematurely exit hold mode |
|
3743 default: |
|
3744 break; |
|
3745 } |
|
3746 iOutstandingCmd = ETrue; |
|
3747 } |
|
3748 else |
|
3749 { |
|
3750 LOG1(_L("TLowPowModeCmdController::DoExitModeL: cannot exit from mode:%d due to an outstanding command"), aMode); |
|
3751 } |
|
3752 } |
|
3753 |
|
3754 TInt TLowPowModeCmdController::ExitMode(TBTLinkMode aMode, THCIConnHandle aHandle) |
|
3755 { |
|
3756 LOG_FUNC |
|
3757 TRAPD(err, DoExitModeL(aMode, aHandle)); |
|
3758 return err; |
|
3759 } |
|
3760 |
|
3761 void TLowPowModeCmdController::DoChangeModeL(TBTLinkMode aMode, THCIConnHandle aConnHandle) |
|
3762 { |
|
3763 LOG_FUNC |
|
3764 LOG2(_L("TLowPowModeCmdController::DoChangeModeL: mode:%d iOutstandingCmd:%d"), aMode, iOutstandingCmd); |
|
3765 if (!iOutstandingCmd) |
|
3766 { |
|
3767 switch (aMode) |
|
3768 { |
|
3769 case ESniffMode: |
|
3770 { |
|
3771 SniffL(aConnHandle); |
|
3772 break; |
|
3773 } |
|
3774 case EParkMode: |
|
3775 { |
|
3776 ParkL(aConnHandle); |
|
3777 break; |
|
3778 } |
|
3779 case EHoldMode: |
|
3780 { |
|
3781 HoldL(aConnHandle); |
|
3782 break; |
|
3783 } |
|
3784 case EScatterMode: |
|
3785 case EActiveMode: |
|
3786 __ASSERT_DEBUG(0, Panic(EHCICommandBadArgument)); |
|
3787 break; |
|
3788 } |
|
3789 iOutstandingCmd = ETrue; |
|
3790 } |
|
3791 else |
|
3792 { |
|
3793 LOG1(_L("TLowPowModeCmdController::DoChangeModeL: cannot change to mode:%d due to an outstanding command"), aMode); |
|
3794 } |
|
3795 } |
|
3796 |
|
3797 TInt TLowPowModeCmdController::ChangeMode(TBTLinkMode aMode, THCIConnHandle aHandle) |
|
3798 { |
|
3799 LOG_FUNC |
|
3800 TRAPD(err, DoChangeModeL(aMode, aHandle)); |
|
3801 return err; |
|
3802 } |
|
3803 |
|
3804 void TLowPowModeCmdController::SniffL(THCIConnHandle aHandleToRemote) |
|
3805 { |
|
3806 LOG_FUNC |
|
3807 CSniffModeCommand* cmd = CSniffModeCommand::NewL(aHandleToRemote, KBTSniffModeMaxInterval, KBTSniffModeMinInterval, KBTSniffModeAttempt, KBTSniffModeTimeout); |
|
3808 |
|
3809 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
3810 iCmdController.MhcqAddCommandL(cmd, *this); |
|
3811 } |
|
3812 |
|
3813 void TLowPowModeCmdController::ExitSniffL(THCIConnHandle aHandleToRemote) |
|
3814 { |
|
3815 LOG_FUNC |
|
3816 CExitSniffModeCommand* cmd = CExitSniffModeCommand::NewL(aHandleToRemote); |
|
3817 |
|
3818 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
3819 iCmdController.MhcqAddCommandL(cmd, *this); |
|
3820 } |
|
3821 |
|
3822 void TLowPowModeCmdController::HoldL(THCIConnHandle aHandle) |
|
3823 { |
|
3824 LOG_FUNC |
|
3825 CHoldModeCommand* cmd = CHoldModeCommand::NewL(aHandle, KBTHoldModeMaxInterval, KBTHoldModeMinInterval); |
|
3826 |
|
3827 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
3828 iCmdController.MhcqAddCommandL(cmd, *this); |
|
3829 } |
|
3830 |
|
3831 void TLowPowModeCmdController::ParkL(THCIConnHandle aHandle) |
|
3832 { |
|
3833 LOG_FUNC |
|
3834 CParkModeCommand* cmd = CParkModeCommand::NewL(aHandle, KBTParkModeBeaconMaxInterval, KBTParkModeBeaconMinInterval); |
|
3835 |
|
3836 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
3837 iCmdController.MhcqAddCommandL(cmd, *this); |
|
3838 } |
|
3839 |
|
3840 void TLowPowModeCmdController::ExitParkL(THCIConnHandle aHandle) |
|
3841 { |
|
3842 LOG_FUNC |
|
3843 CExitParkModeCommand* cmd = CExitParkModeCommand::NewL(aHandle); |
|
3844 |
|
3845 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
3846 iCmdController.MhcqAddCommandL(cmd, *this); |
|
3847 } |
|
3848 |
|
3849 void TLowPowModeCmdController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand) |
|
3850 { |
|
3851 LOG_FUNC |
|
3852 THCIEventCode code = aEvent.EventCode(); |
|
3853 |
|
3854 __ASSERT_DEBUG(!(code != EModeChangeEvent && code != ECommandStatusEvent), Panic(EHCIUnknownCommandEvent)); // this should never happen |
|
3855 __ASSERT_DEBUG(aRelatedCommand != NULL, Panic(EHCIUnknownCommandEvent)); // this should never happen |
|
3856 |
|
3857 if (!aRelatedCommand) // it is not the response to our command - should never happen |
|
3858 return; |
|
3859 |
|
3860 if ((code == ECommandStatusEvent) && (aEvent.ErrorCode() != EOK)) |
|
3861 { |
|
3862 LOG3(_L("TLowPowModeCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x error:0x%x"), code, aRelatedCommand->Opcode(), aEvent.ErrorCode()); |
|
3863 iOutstandingCmd = EFalse; // reset the outstanding flag |
|
3864 iParent.StartArbitrationTimer(); |
|
3865 } |
|
3866 else if (code == EModeChangeEvent) |
|
3867 { |
|
3868 iOutstandingCmd = EFalse; // reset the outstanding flag |
|
3869 |
|
3870 LOG2(_L("TLowPowModeCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x"), code, aRelatedCommand->Opcode()); |
|
3871 |
|
3872 const TModeChangeEvent& modeChangeEvent = TModeChangeEvent::Cast(aEvent); |
|
3873 TBTLinkMode mode = EActiveMode; |
|
3874 switch(modeChangeEvent.CurrentMode()) |
|
3875 { |
|
3876 // Mode 0, as defined for the Mode Change Event, is Active Mode |
|
3877 case 0: |
|
3878 break; |
|
3879 case 1: |
|
3880 mode = EHoldMode; |
|
3881 break; |
|
3882 case 2: |
|
3883 mode = ESniffMode; |
|
3884 break; |
|
3885 case 3: |
|
3886 mode = EParkMode; |
|
3887 break; |
|
3888 default: |
|
3889 __ASSERT_ALWAYS(EFalse, Panic(EHCICommandBadArgument)); |
|
3890 break; |
|
3891 } |
|
3892 // In the HCI_Facade, in this situation, CPhysicalLinksManager::ModeChanged() is called. |
|
3893 // Since this methods find the CPhysicalLink object (that is iParent) and then call its |
|
3894 // ModeChange method, we can call it directly. |
|
3895 iParent.ModeChange(aEvent.ErrorCode(), modeChangeEvent.ConnectionHandle(), mode, modeChangeEvent.Interval()); |
|
3896 } |
|
3897 } |
|
3898 |
|
3899 void TLowPowModeCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand)) |
|
3900 { |
|
3901 LOG_FUNC |
|
3902 __ASSERT_DEBUG(aCommand, Panic(EHCIUnknownCommandEvent)); // this should never happen |
|
3903 #ifdef _DEBUG |
|
3904 LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode()); |
|
3905 #endif |
|
3906 iOutstandingCmd = EFalse; // reset the outstanding flag |
|
3907 iParent.StartArbitrationTimer(); |
|
3908 } |
|
3909 |
|
3910 |
|
3911 |
|
3912 |
|
3913 // |
|
3914 // CEncryptionEnforcer |
|
3915 // |
|
3916 |
|
3917 CEncryptionEnforcer::CEncryptionEnforcer (CPhysicalLink& aLink, THCIEncryptModeFlag aEncryptionMode) : |
|
3918 CActive(EPriorityStandard), // Standard priority |
|
3919 iLink(aLink), |
|
3920 iEncryptionMode(aEncryptionMode), |
|
3921 iState(EInactive) |
|
3922 { |
|
3923 LOG_FUNC |
|
3924 } |
|
3925 |
|
3926 CEncryptionEnforcer* CEncryptionEnforcer::NewLC(CPhysicalLink& aLink, THCIEncryptModeFlag aEncryptionMode) |
|
3927 { |
|
3928 LOG_STATIC_FUNC |
|
3929 CEncryptionEnforcer* self = new ( ELeave ) CEncryptionEnforcer(aLink, aEncryptionMode); |
|
3930 CleanupStack::PushL (self); |
|
3931 self->ConstructL (); |
|
3932 return self; |
|
3933 } |
|
3934 |
|
3935 CEncryptionEnforcer* CEncryptionEnforcer::NewL(CPhysicalLink& aLink, THCIEncryptModeFlag aEncryptionMode) |
|
3936 { |
|
3937 LOG_STATIC_FUNC |
|
3938 CEncryptionEnforcer* self = CEncryptionEnforcer::NewLC (aLink, aEncryptionMode); |
|
3939 CleanupStack::Pop(self); |
|
3940 return self; |
|
3941 } |
|
3942 |
|
3943 void CEncryptionEnforcer::ConstructL() |
|
3944 { |
|
3945 LOG_FUNC |
|
3946 User::LeaveIfError (iTimer.CreateLocal () ); // Initialize timer |
|
3947 CActiveScheduler::Add (this); // Add to scheduler |
|
3948 } |
|
3949 |
|
3950 CEncryptionEnforcer::~CEncryptionEnforcer() |
|
3951 { |
|
3952 LOG_FUNC |
|
3953 Cancel (); // Cancel any request, if outstanding |
|
3954 iTimer.Close (); // Destroy the RTimer object |
|
3955 } |
|
3956 |
|
3957 void CEncryptionEnforcer::DoCancel () |
|
3958 { |
|
3959 LOG_FUNC |
|
3960 iTimer.Cancel (); |
|
3961 ChangeState(EInactive); |
|
3962 } |
|
3963 |
|
3964 void CEncryptionEnforcer::Start(TInt delay) |
|
3965 { |
|
3966 LOG_FUNC |
|
3967 Cancel (); // Cancel any request, just to be sure |
|
3968 LOG(_L("CEncryptionEnforcer activate timer")) |
|
3969 iTimer.After (iStatus, delay); // Set for later |
|
3970 SetActive (); // Tell scheduler a request is active |
|
3971 } |
|
3972 |
|
3973 void CEncryptionEnforcer::Stop() |
|
3974 { |
|
3975 LOG_FUNC |
|
3976 Cancel(); |
|
3977 } |
|
3978 |
|
3979 void CEncryptionEnforcer::RunL () |
|
3980 { |
|
3981 LOG_FUNC |
|
3982 switch(iState) |
|
3983 { |
|
3984 case ERoleSwitchTimerInProgress: |
|
3985 LOG(_L("CEncryptionEnforcer::RunL() : timer expired after a roleswitch, enforce encryption")) |
|
3986 ChangeState(EForcingInProgress); |
|
3987 User::LeaveIfError(iLink.ChangeEncryption(iEncryptionMode)); |
|
3988 break; |
|
3989 case ENoRoleSwitchTimerInProgress: |
|
3990 LOG(_L("CEncryptionEnforcer::RunL() : timer expired and no roleswitch performed, terminate the link")) |
|
3991 iLink.Terminate(ERemoteUserEndedConnection); |
|
3992 break; |
|
3993 default: |
|
3994 // this should never happen, so we assert in debug so to raise the problem. |
|
3995 // however it doesn't break our behaviour, so we don't care in release. |
|
3996 LOG(_L("CEncryptionEnforcer::RunL() : bad state")) |
|
3997 __ASSERT_DEBUG(EFalse, Panic(EEncryptionEnforcerBadState)); |
|
3998 break; |
|
3999 } |
|
4000 } |
|
4001 |
|
4002 TInt CEncryptionEnforcer::RunError(TInt IF_FLOGGING(aError)) |
|
4003 { |
|
4004 LOG_FUNC |
|
4005 LOG1(_L("CEncryptionEnforcer::RunError() : error = %d"), aError); |
|
4006 LOG(_L("CEncryptionEnforcer::RunError() : try to terminate the link")); |
|
4007 return iLink.Terminate(ERemoteUserEndedConnection); |
|
4008 } |
|
4009 |
|
4010 void CEncryptionEnforcer::ChangeState(TState aState) |
|
4011 { |
|
4012 LOG_FUNC |
|
4013 LOG2(_L("CEncryptionEnforcer::ChangeState(): old state = %d; new state = %d"), iState, aState); |
|
4014 iState = aState; |
|
4015 } |
|
4016 |
|
4017 void CEncryptionEnforcer::EncryptionEnabled() |
|
4018 { |
|
4019 LOG_FUNC |
|
4020 LOG1(_L("CEncryptionEnforcer::EncryptionEnabled() : current status = %d"), iState); |
|
4021 switch(iState) |
|
4022 { |
|
4023 case EInactive: |
|
4024 // do nothing, it means is the first encryption event as reply to our ChangeEncryption cmd. |
|
4025 break; |
|
4026 case EForcingInProgress: |
|
4027 ChangeState(EInactive); |
|
4028 break; |
|
4029 case ENoRoleSwitchTimerInProgress: |
|
4030 case ERoleSwitchTimerInProgress: |
|
4031 Stop(); |
|
4032 break; |
|
4033 } |
|
4034 } |
|
4035 |
|
4036 void CEncryptionEnforcer::EncryptionDisabled(TBool aSecurityModeFour) |
|
4037 { |
|
4038 LOG_FUNC |
|
4039 LOG1(_L("CEncryptionEnforcer::EncryptionDisabled() : current status = %d"), iState); |
|
4040 |
|
4041 if(aSecurityModeFour) |
|
4042 { |
|
4043 Stop(); |
|
4044 ChangeState(EForcingInProgress); |
|
4045 } |
|
4046 |
|
4047 switch(iState) |
|
4048 { |
|
4049 case EInactive: |
|
4050 LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : start timer")) |
|
4051 ChangeState(ENoRoleSwitchTimerInProgress); |
|
4052 Start(KTimeOutDelay); |
|
4053 break; |
|
4054 case EForcingInProgress: |
|
4055 LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : disconnect the link")) |
|
4056 iLink.Terminate(ERemoteUserEndedConnection); |
|
4057 break; |
|
4058 default: |
|
4059 // this should never happen, so we assert in debug so to raise the problem. |
|
4060 // however it doesn't break our behaviour, so we don't care in release. |
|
4061 LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : bad state")) |
|
4062 __ASSERT_DEBUG(EFalse, Panic(EEncryptionEnforcerBadState)); |
|
4063 break; |
|
4064 } |
|
4065 } |
|
4066 |
|
4067 void CEncryptionEnforcer::RoleSwitchEvent() |
|
4068 { |
|
4069 LOG_FUNC |
|
4070 |
|
4071 switch(iState) |
|
4072 { |
|
4073 case EInactive: |
|
4074 // This is possible with EPR support - we don't need to do anything in this case. |
|
4075 break; |
|
4076 case ENoRoleSwitchTimerInProgress: |
|
4077 ChangeState(ERoleSwitchTimerInProgress); |
|
4078 break; |
|
4079 default: |
|
4080 // this should never happen, so we assert in debug so to raise the problem. |
|
4081 // however it doesn't break our behaviour, so we don't care in release. |
|
4082 LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : bad state")) |
|
4083 __ASSERT_DEBUG(EFalse, Panic(EEncryptionEnforcerBadState)); |
|
4084 break; |
|
4085 } |
|
4086 } |
|
4087 |
|
4088 void XAutoKeyRefreshToken::Release() |
|
4089 { |
|
4090 LOG_FUNC |
|
4091 iQueLink.Deque(); |
|
4092 delete this; |
|
4093 } |
|
4094 |
|
4095 // |
|
4096 // TRegistryDeviceOutChecker |
|
4097 // |
|
4098 TRegistryDeviceBeingModified::TRegistryDeviceBeingModified() : |
|
4099 iReferenceCount(0) |
|
4100 { |
|
4101 LOG_FUNC |
|
4102 } |
|
4103 |
|
4104 TBool TRegistryDeviceBeingModified::InUse() const |
|
4105 { |
|
4106 LOG_FUNC |
|
4107 return iReferenceCount > 0; |
|
4108 } |
|
4109 |
|
4110 TBool TRegistryDeviceBeingModified::IsEqual(const TBTNamelessDevice& aDevice) const |
|
4111 { |
|
4112 LOG_FUNC |
|
4113 return (iDevice == aDevice); |
|
4114 } |
|
4115 |
|
4116 void TRegistryDeviceBeingModified::Begin(const TBTNamelessDevice& aDevice) |
|
4117 { |
|
4118 LOG_FUNC |
|
4119 iDevice = aDevice; |
|
4120 iReferenceCount++; |
|
4121 } |
|
4122 |
|
4123 void TRegistryDeviceBeingModified::RequestCompleted() |
|
4124 { |
|
4125 LOG_FUNC |
|
4126 iReferenceCount--; |
|
4127 __ASSERT_DEBUG(iReferenceCount >= 0, Panic(ETRegistryDevBeingModUnexpectedCompleted)); |
|
4128 } |
|
4129 |
|
4130 // |
|
4131 // TDisconnectCmdController |
|
4132 // HCI Command Queue Interface for Disconnect Commands |
|
4133 // |
|
4134 |
|
4135 TDisconnectCmdController::TDisconnectCmdController(CPhysicalLink& aLink, MHCICommandQueue& aCmdController) : |
|
4136 iParent(aLink), |
|
4137 iCmdController(aCmdController) |
|
4138 { |
|
4139 LOG_FUNC |
|
4140 } |
|
4141 |
|
4142 void TDisconnectCmdController::Abort() |
|
4143 { |
|
4144 LOG_FUNC |
|
4145 iCmdController.MhcqRemoveAllCommands(*this); |
|
4146 } |
|
4147 |
|
4148 TInt TDisconnectCmdController::Disconnect(THCIErrorCode aReason) |
|
4149 { |
|
4150 LOG_FUNC |
|
4151 TRAPD(err, DoDisconnectL(aReason)); |
|
4152 return err; |
|
4153 } |
|
4154 |
|
4155 void TDisconnectCmdController::DoDisconnectL(THCIErrorCode aReason) |
|
4156 { |
|
4157 LOG_FUNC |
|
4158 CDisconnectCommand* cmd = CDisconnectCommand::NewL(iParent.Handle(), aReason); |
|
4159 |
|
4160 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
4161 iCmdController.MhcqAddCommandL(cmd, *this); |
|
4162 } |
|
4163 |
|
4164 void TDisconnectCmdController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand) |
|
4165 { |
|
4166 LOG_FUNC |
|
4167 THCIEventCode code = aEvent.EventCode(); |
|
4168 |
|
4169 __ASSERT_DEBUG(!(code != EDisconnectionCompleteEvent && code != ECommandStatusEvent), Panic(EDiscCtrlUnexpectedCommandEvent)); // this should never happen |
|
4170 __ASSERT_DEBUG(aRelatedCommand != NULL, Panic(EDiscCtrlUnmatchedCommandEvent)); // this should never happen |
|
4171 |
|
4172 if (!aRelatedCommand) // it is not the response to our command - should never happen |
|
4173 return; |
|
4174 |
|
4175 if ((code == ECommandStatusEvent) && (aEvent.ErrorCode() != EOK)) |
|
4176 { |
|
4177 iParent.Disconnection(aEvent.ErrorCode(), iParent.Handle(), aEvent.ErrorCode()); |
|
4178 } |
|
4179 else if (code == EDisconnectionCompleteEvent) |
|
4180 { |
|
4181 const TDisconnectionCompleteEvent& disconnectionCompleteEvent = TDisconnectionCompleteEvent::Cast(aEvent); |
|
4182 // The connection handle in the disconnect complete event should be the same as the physical link's connection handle |
|
4183 __ASSERT_DEBUG(disconnectionCompleteEvent.ConnectionHandle() == iParent.Handle(), Panic(EDiscCtrlUnexpectedConnectionHandle)); |
|
4184 iParent.Disconnection(aEvent.ErrorCode(), disconnectionCompleteEvent.ConnectionHandle(), static_cast<THCIErrorCode>(disconnectionCompleteEvent.Reason())); |
|
4185 } |
|
4186 } |
|
4187 |
|
4188 void TDisconnectCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand)) |
|
4189 { |
|
4190 LOG_FUNC |
|
4191 __ASSERT_DEBUG(aCommand, Panic(EDiscCtrlUnmatchedCommandEvent)); // this should never happen |
|
4192 #ifdef _DEBUG |
|
4193 LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode()); |
|
4194 #endif |
|
4195 // Pass this to the physical link as Command Disallowed |
|
4196 iParent.Disconnection(ECommandDisallowed, iParent.Handle(), ECommandDisallowed); |
|
4197 } |
|
4198 |
|
4199 |
|
4200 // |
|
4201 // TAuthenticationCmdController |
|
4202 // |
|
4203 |
|
4204 TAuthenticationCmdController::TAuthenticationCmdController(CPhysicalLink& aLink, MHCICommandQueue& aCmdController) : |
|
4205 iParent(aLink), |
|
4206 iCmdController(aCmdController) |
|
4207 { |
|
4208 LOG_FUNC |
|
4209 } |
|
4210 |
|
4211 void TAuthenticationCmdController::Abort() |
|
4212 { |
|
4213 LOG_FUNC |
|
4214 iCmdController.MhcqRemoveAllCommands(*this); |
|
4215 } |
|
4216 |
|
4217 TInt TAuthenticationCmdController::LinkKeyRequestReply(const TBTDevAddr& aBdaddr, const TDesC8& aLinkKey) const |
|
4218 /** |
|
4219 We have obtained a linkkey, tell HC |
|
4220 **/ |
|
4221 { |
|
4222 CLinkKeyRequestReplyCommand* cmd = NULL; |
|
4223 TBTLinkKey linkkey; |
|
4224 linkkey.Copy(aLinkKey); |
|
4225 |
|
4226 TRAPD(err, cmd = CLinkKeyRequestReplyCommand::NewL(aBdaddr, linkkey)); |
|
4227 if (err == KErrNone) |
|
4228 { |
|
4229 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
4230 TRAP(err,iCmdController.MhcqAddCommandL(cmd, (MHCICommandQueueClient&)(*this))); |
|
4231 } |
|
4232 if(err != KErrNone) |
|
4233 { |
|
4234 iParent.AuthenticationComplete(ELinkKeyRequestPending); |
|
4235 } |
|
4236 return err; |
|
4237 } |
|
4238 |
|
4239 TInt TAuthenticationCmdController::LinkKeyRequestNegativeReply(const TBTDevAddr& aBdaddr) const |
|
4240 /** |
|
4241 We have not obtained a linkkey, tell HC |
|
4242 **/ |
|
4243 { |
|
4244 CLinkKeyRequestReplyNegativeCommand* cmd = NULL; |
|
4245 |
|
4246 TRAPD(err, cmd = CLinkKeyRequestReplyNegativeCommand::NewL(aBdaddr)); |
|
4247 if (err == KErrNone) |
|
4248 { |
|
4249 // Ownership of cmd transfered even if MhcqAddCommandL leaves |
|
4250 TRAP(err, iCmdController.MhcqAddCommandL(cmd, (MHCICommandQueueClient&)(*this))); |
|
4251 } |
|
4252 |
|
4253 if(err != KErrNone) |
|
4254 { |
|
4255 iParent.AuthenticationComplete(ELinkKeyRequestPending); |
|
4256 } |
|
4257 return err; |
|
4258 } |
|
4259 |
|
4260 void TAuthenticationCmdController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand) |
|
4261 { |
|
4262 LOG_FUNC |
|
4263 THCIEventCode code = aEvent.EventCode(); |
|
4264 |
|
4265 __ASSERT_DEBUG(!(code != ECommandCompleteEvent && code != ECommandStatusEvent), Panic(EHCIUnknownCommandEvent)); // this should never happen |
|
4266 __ASSERT_DEBUG(aRelatedCommand != NULL, Panic(EHCIUnknownCommandEvent)); // this should never happen |
|
4267 |
|
4268 if (!aRelatedCommand) // it is not the response to our command - should never happen |
|
4269 return; |
|
4270 |
|
4271 if ((code == ECommandStatusEvent) && (aEvent.ErrorCode() != EOK)) |
|
4272 { |
|
4273 LOG3(_L("TAuthenticationCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x error:0x%x"), code, aRelatedCommand->Opcode(), aEvent.ErrorCode()); |
|
4274 } |
|
4275 else if (code == ECommandCompleteEvent) |
|
4276 { |
|
4277 LOG2(_L("TAuthenticationCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x"), code, aRelatedCommand->Opcode()); |
|
4278 iParent.AuthenticationComplete(ELinkKeyRequestPending); |
|
4279 } |
|
4280 } |
|
4281 |
|
4282 void TAuthenticationCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand)) |
|
4283 { |
|
4284 LOG_FUNC |
|
4285 __ASSERT_DEBUG(aCommand, Panic(EHCIUnknownCommandEvent)); // this should never happen |
|
4286 #ifdef _DEBUG |
|
4287 LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode()); |
|
4288 #endif |
|
4289 iParent.AuthenticationComplete(ELinkKeyRequestPending); |
|
4290 } |
|
4291 |