bluetooth/btstack/linkmgr/hostresolver.cpp
changeset 0 29b1cd4cb562
child 22 786b94c6f0a4
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-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 // L2CAP Host resolver.
       
    15 // Implements Inquiry and Name lookup
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "hostresolver.h"
       
    20 #include <bluetooth/logger.h>
       
    21 #include <bluetooth/hci/event.h>
       
    22 #include <bluetooth/hci/hciutil.h>
       
    23 #include <bluetooth/hci/hciconsts.h>
       
    24 #include <bluetooth/hci/inquirycommand.h>
       
    25 #include <bluetooth/hci/inquirycancelcommand.h>
       
    26 #include <bluetooth/hci/writeinquirymodecommand.h>
       
    27 #include <bluetooth/hci/writeextendedinquiryresponsecommand.h>
       
    28 #include <bluetooth/hci/readextendedinquiryresponsecommand.h>
       
    29 #include <bluetooth/hci/remotenamerequestcommand.h>
       
    30 #include <bluetooth/hci/remotenamereqcompleteevent.h>
       
    31 #include <bluetooth/hci/remotenamerequestcancelcommand.h>
       
    32 #include <bluetooth/hci/remotehostsupportedfeaturesnotificationevent.h>
       
    33 #include <bluetooth/hci/readlocalnamecommand.h>
       
    34 
       
    35 // Command Events
       
    36 #include <bluetooth/hci/inquiryresultevent.h>
       
    37 #include <bluetooth/hci/inquiryresultwithrssievent.h>
       
    38 #include <bluetooth/hci/extendedinquiryresultevent.h>
       
    39 
       
    40 // Command Complete Events
       
    41 #include <bluetooth/hci/readlocalnamecompleteevent.h>
       
    42 #include <bluetooth/hci/commandcompleteevent.h>
       
    43 #include <bluetooth/hci/commandstatusevent.h>
       
    44 
       
    45 #include <e32std.h>
       
    46 #include <s32mem.h>
       
    47 #include <bt_sock.h>
       
    48 #include <utf.h>
       
    49 #include "debug.h"
       
    50 #include "linkutil.h"
       
    51 #include "physicallinksmanager.h"	// to get baseband freed up for inquiries
       
    52 #include "BTSec.h"
       
    53 
       
    54 //Diagnostic string for security check failures, in builds without platsec
       
    55 //diagnostics this will be NULL.
       
    56 const char* const KBT_HOSTRESOLVER_NAME_DIAG = __PLATSEC_DIAGNOSTIC_STRING("Bluetooth Host Resolver");
       
    57 
       
    58 const static TUint KHostResDontBlock = 4;
       
    59 
       
    60 #ifdef __FLOG_ACTIVE
       
    61 _LIT8(KLogComponent, LOG_COMPONENT_HOSTRESOLVER);
       
    62 #endif
       
    63 
       
    64 
       
    65 
       
    66 //
       
    67 //	BT Inquiry Result record.
       
    68 //
       
    69 
       
    70 CBTInqResultRecord::CBTInqResultRecord(const TBTDevAddr& aAddr)
       
    71 	: iCodec(iEntry.iExtendedInquiryResponse)
       
    72 	{
       
    73 	LOG_FUNC
       
    74 	iEntry.iBdaddr = aAddr;
       
    75 	// Default to page scan repetition mode R2 as recommended by Bray to give best
       
    76 	// chance of success for host resolver needs.
       
    77 	// Also allow other default values to be entered here
       
    78 	iEntry.iPageScanRepetitionMode = KDefaultBluetoothPageScanRepMode;
       
    79 	iEntry.iPageScanMode = KDefaultBluetoothPageScanMode;
       
    80 	iEntry.iClockOffset = KDefaultBluetoothClockOffset;
       
    81 	iEntry.iCoD = KDefaultBluetoothClassOfDevice;
       
    82 	
       
    83 	if(aAddr!=TBTDevAddr())
       
    84 		{
       
    85 		iJuiceFromHCIMask = EBluetoothAddr;
       
    86 		}
       
    87 	//else 0 cos 'C' class
       
    88 	
       
    89 	SetNameValid(EFalse);
       
    90 	}
       
    91 
       
    92 CBTInqResultRecord::~CBTInqResultRecord()
       
    93 	{
       
    94 	LOG_FUNC
       
    95 	iIACs.Close();
       
    96 	}
       
    97 
       
    98 inline void CBTInqResultRecord::Open()
       
    99 /**
       
   100 	Some reference is now pointing at us.
       
   101 	Inc the ref count.
       
   102 **/
       
   103 	{
       
   104 	LOG_FUNC
       
   105 	++iRefCount;
       
   106 	}
       
   107 
       
   108 void CBTInqResultRecord::Close()
       
   109 /**
       
   110 	Reference closing.
       
   111 	Auto delete if this was the last reference pointing to us.
       
   112 **/
       
   113 	{
       
   114 	LOG_FUNC
       
   115 	--iRefCount;
       
   116 	if (iRefCount <= 0)
       
   117 		delete this;
       
   118 	}
       
   119 
       
   120 TInquiryLogEntry& CBTInqResultRecord::LogEntry()
       
   121 /**
       
   122 	The inquiry result.
       
   123 	This is stored as it was returned from the HCI.
       
   124 	The host resolver will convert it into an InquirySockAddr
       
   125 	when a client actually wants to retreve it.
       
   126 **/
       
   127 	{
       
   128 	LOG_FUNC
       
   129 	return iEntry;
       
   130 	}
       
   131 
       
   132 inline void CBTInqResultRecord::SetName(const TDesC8& aName)
       
   133 	{
       
   134 	LOG_FUNC
       
   135 	iName = aName;
       
   136 	}
       
   137 
       
   138 inline const TDesC8& CBTInqResultRecord::Name() const
       
   139 /**
       
   140 	The UTF name of the remote device.
       
   141 	This is stored as it comes in off the wire, the host resolver
       
   142 	converts to Unicode if & when a client actually requires it.
       
   143 **/
       
   144 	{
       
   145 	LOG_FUNC
       
   146 	return iName;
       
   147 	}
       
   148 
       
   149 inline TInt CBTInqResultRecord::IncFlushes()
       
   150 /**
       
   151 	Age the result record
       
   152 	Returns it's new age.
       
   153 **/
       
   154 	{
       
   155 	LOG_FUNC
       
   156 	return ++iFlushes;
       
   157 	}
       
   158 
       
   159 inline TBool CBTInqResultRecord::IsNameValid() const
       
   160 	{
       
   161 	LOG_FUNC
       
   162 	return iNameLookupResultCode == KErrNone;
       
   163 	}
       
   164 
       
   165 inline void CBTInqResultRecord::SetNameValid(TBool aBool)
       
   166 	{
       
   167 	LOG_FUNC
       
   168 	if(aBool)
       
   169 		iNameLookupResultCode = KErrNone;
       
   170 	else
       
   171 		iNameLookupResultCode = 1;
       
   172 	}
       
   173 
       
   174 void CBTInqResultRecord::SetNameLookupResultCode(TInt aResultCode)
       
   175 	{// Only record error, if we don't have a valid name already
       
   176 	LOG_FUNC
       
   177 	if(!IsNameValid())
       
   178 		iNameLookupResultCode = aResultCode;
       
   179 	}
       
   180 
       
   181 inline TBool CBTInqResultRecord::IsNameRequestPending() const
       
   182 	{
       
   183 	LOG_FUNC
       
   184 	return iNameStatus & ENamePending;
       
   185 	}
       
   186 
       
   187 inline void CBTInqResultRecord::SetNamePending(TBool aBool)
       
   188 	{
       
   189 	LOG_FUNC
       
   190 	if(aBool)
       
   191 		iNameStatus |= ENamePending;
       
   192 	else
       
   193 		iNameStatus &= ~ENamePending;
       
   194 	}
       
   195 
       
   196 inline TBool CBTInqResultRecord::IsNameRefreshRequested() const
       
   197 	{
       
   198 	LOG_FUNC
       
   199 	return iNameStatus & ENameRefreshRequested;
       
   200 	}
       
   201 
       
   202 inline void CBTInqResultRecord::SetNameRefreshRequested(TBool aBool)
       
   203 	{
       
   204 	LOG_FUNC
       
   205 	if(aBool)
       
   206 		iNameStatus |= ENameRefreshRequested;
       
   207 	else
       
   208 		iNameStatus &= ~ENameRefreshRequested;
       
   209 	}
       
   210 
       
   211 inline TBool CBTInqResultRecord::IsNameComplete() const
       
   212 	{
       
   213 	LOG_FUNC
       
   214 	return iNameStatus & ENameComplete;
       
   215 	}
       
   216 
       
   217 inline void CBTInqResultRecord::SetNameComplete(TBool aBool)
       
   218 	{
       
   219 	LOG_FUNC
       
   220 	if(aBool)
       
   221 		iNameStatus |= ENameComplete;
       
   222 	else
       
   223 		iNameStatus &= ~ENameComplete;
       
   224 	}
       
   225 
       
   226 inline TBool CBTInqResultRecord::IsExplicitNameRequest() const
       
   227 	{
       
   228 	LOG_FUNC
       
   229 	return iNameStatus & ENameExplicitRequest;
       
   230 	}
       
   231 
       
   232 inline void CBTInqResultRecord::SetExplicitNameRequest(TBool aBool)
       
   233 	{
       
   234 	LOG_FUNC
       
   235 	if(aBool)
       
   236 		iNameStatus |= ENameExplicitRequest;
       
   237 	else
       
   238 		iNameStatus &= ~ENameExplicitRequest;
       
   239 	}
       
   240 
       
   241 inline TBool CBTInqResultRecord::HaveNameLookupResult() const
       
   242 	{
       
   243 	LOG_FUNC
       
   244 	return iNameLookupResultCode <= KErrNone;
       
   245 	}
       
   246 
       
   247 inline TInt CBTInqResultRecord::NameLookupResultCode() const
       
   248 	{// Only valid if HaveNameLookupResult == ETrue
       
   249 	LOG_FUNC
       
   250 	__ASSERT_DEBUG(HaveNameLookupResult(), Panic(EBTNameLookupResultNotFound));
       
   251 	return iNameLookupResultCode;
       
   252 	}
       
   253 
       
   254 inline TInt CBTInqResultRecord::NameLookupAttempts() const
       
   255 	{
       
   256 	LOG_FUNC
       
   257 	return iNameLookupAttempts;
       
   258 	}
       
   259 
       
   260 void CBTInqResultRecord::GetInquirySockAddr(TInquirySockAddr& aAddr)
       
   261 /**
       
   262 	Read this result record out into a TInquirySockAddr.
       
   263 **/
       
   264 	{
       
   265 	LOG_FUNC
       
   266 	aAddr.SetBTAddr(LogEntry().iBdaddr);
       
   267 
       
   268 	TBTDeviceClass cod(LogEntry().iCoD);
       
   269 	aAddr.SetMajorServiceClass(cod.MajorServiceClass());
       
   270 	aAddr.SetMajorClassOfDevice(cod.MajorDeviceClass());
       
   271 	aAddr.SetMinorClassOfDevice(cod.MinorDeviceClass());
       
   272 	
       
   273 	TUint8 resultFlags = 0;
       
   274 	
       
   275 	if(iJuiceFromHCIMask & EBluetoothRssi)
       
   276 		{
       
   277 		TInquiryLogEntry* logEntry = &(LogEntry());
       
   278 		resultFlags |= TInquirySockAddr::ERssiValid;
       
   279 		aAddr.SetRssi(static_cast<TInquiryLogEntryWithRssi*>(logEntry)->iRssi.RSSI());
       
   280 		}
       
   281 
       
   282 	aAddr.SetResultFlags(resultFlags);
       
   283 	}
       
   284 
       
   285 TInt CBTInqResultRecord::GetEir(TNameRecord& aNameRec, TBool aIgnoreCachedName)
       
   286 	{
       
   287 	// Reformat the EIR (i.e. remove 0s from EIR) for the constructor
       
   288 	LOG_FUNC
       
   289 	TInt error = KErrNone;
       
   290 
       
   291 	aNameRec.iName.Zero();
       
   292 	iCodec.Set(aNameRec);
       
   293 	if(IsEirPresent())
       
   294 		{
       
   295 		TInquiryLogEntry* logEntry = &(LogEntry());
       
   296 		iCodec.Copy(static_cast<TInquiryLogEntryWithEir*>(logEntry)->iExtendedInquiryResponse);
       
   297 		}
       
   298 	// replace device name in eir with iName if there is a complete name present
       
   299 	if(IsNameValid() && IsNameComplete() && !aIgnoreCachedName)
       
   300 		{
       
   301 		iCodec.SetDeviceName(iName, ETrue);
       
   302 		}
       
   303 	return error;
       
   304 	}
       
   305 
       
   306 TInt CBTInqResultRecord::GetName(TNameRecord& aNameRec)
       
   307 	{
       
   308 	LOG_FUNC
       
   309 	TInt err = KErrNotFound;
       
   310 	if(HaveNameLookupResult())
       
   311 		{
       
   312 		err = CnvUtfConverter::ConvertToUnicodeFromUtf8(aNameRec.iName, iName);
       
   313 		if (err >= KErrNone)
       
   314 			{
       
   315 			err = KErrNone;
       
   316 			if(!IsNameComplete())
       
   317 				{
       
   318 				aNameRec.iFlags |= TNameRecord::EPartial;
       
   319 				}
       
   320 			else
       
   321 				{
       
   322 				aNameRec.iFlags &= ~(TNameRecord::EPartial);
       
   323 				}
       
   324 			}
       
   325 		}
       
   326 	else
       
   327 		{
       
   328 		err = KErrNone; // just following the old way of working.
       
   329 		aNameRec.iName.Zero();
       
   330 		}
       
   331 	return err;
       
   332 	}
       
   333 
       
   334 TInt CBTInqResultRecord::AddIAC(TUint aIAC)
       
   335 /**
       
   336 	Adds IAC into list of those this device has responded to
       
   337 	@return KErrNone	IAC added without any bother
       
   338 	@return KErrAlreadyExists	IAC already in list
       
   339 **/
       
   340 	{
       
   341 	LOG_FUNC
       
   342 	return iIACs.InsertInOrder(aIAC);
       
   343 	}
       
   344 
       
   345 inline TBool CBTInqResultRecord::HasRespondedToIAC(TUint aIAC)
       
   346 	{
       
   347 	LOG_FUNC
       
   348 	return (iIACs.FindInOrder(aIAC) >= 0);
       
   349 	}
       
   350 
       
   351 inline TInt CBTInqResultRecord::NumberOfIACsRespondedTo()
       
   352 	{
       
   353 	LOG_FUNC
       
   354 	return iIACs.Count();
       
   355 	}
       
   356 
       
   357 inline void CBTInqResultRecord::ClearIACs()
       
   358 	{
       
   359 	LOG_FUNC
       
   360 	iIACs.Reset();
       
   361 	}
       
   362 
       
   363 //
       
   364 //	Inquiry result reference.
       
   365 //
       
   366 CBTInqResultRef::CBTInqResultRef(CBTInqResultRef& aRef)
       
   367 	: iRecord(aRef.iRecord)
       
   368 	{
       
   369 	LOG_FUNC
       
   370 	iRecord.Open();
       
   371 	}
       
   372 
       
   373 CBTInqResultRef::~CBTInqResultRef()
       
   374 	{
       
   375 	LOG_FUNC
       
   376 	iRecord.Close();
       
   377 	iLink.Deque();
       
   378 	}
       
   379 
       
   380 CBTInqResultRef::CBTInqResultRef(CBTInqResultRecord& aRec)
       
   381 	: iRecord(aRec)
       
   382 	{
       
   383 	LOG_FUNC
       
   384 	iRecord.Open();
       
   385 	}
       
   386 
       
   387 inline CBTInqResultRecord& CBTInqResultRef::Result() const
       
   388 	{
       
   389 	LOG_FUNC
       
   390 	return iRecord;
       
   391 	}
       
   392 
       
   393 
       
   394 
       
   395 //
       
   396 //	BT Inquiry Result Set.
       
   397 //
       
   398 
       
   399 CBTInqResultSet::CBTInqResultSet()
       
   400 	: iResultRefs(_FOFF(CBTInqResultRef, iLink)),
       
   401 	iNextRefIter(iResultRefs)
       
   402 	{
       
   403 	LOG_FUNC
       
   404 	}
       
   405 
       
   406 CBTInqResultSet::~CBTInqResultSet()
       
   407 	{
       
   408 	LOG_FUNC
       
   409 	Reset();
       
   410 	}
       
   411 
       
   412 void CBTInqResultSet::Reset()
       
   413 	{
       
   414 	LOG_FUNC
       
   415 	while (!iResultRefs.IsEmpty())
       
   416 		delete iResultRefs.First();
       
   417 	ReturnToFirstResult();
       
   418 	}
       
   419 
       
   420 CBTInqResultRef* CBTInqResultSet::Add(CBTInqResultRecord& aRec)
       
   421 	{
       
   422 	LOG_FUNC
       
   423 	CBTInqResultRef* ref = new CBTInqResultRef(aRec);
       
   424 	if (!ref)
       
   425 		{
       
   426 		return 0;
       
   427 		}
       
   428 	iResultRefs.AddLast(*ref);
       
   429 	if (!iNextRefIter)
       
   430 		{
       
   431 		iNextRefIter.SetToLast();
       
   432 		}
       
   433 	return ref;
       
   434 	}
       
   435 
       
   436 CBTInqResultRef* CBTInqResultSet::FindEntry(const TBTDevAddr& aAddr)
       
   437 	{
       
   438 	LOG_FUNC
       
   439 	TResultQueIter iter(iResultRefs);
       
   440 	while (iter)
       
   441 		{
       
   442 		CBTInqResultRef* ref = iter++;
       
   443 		if (ref->Result().LogEntry().iBdaddr == aAddr)
       
   444 			{
       
   445 			return ref;
       
   446 			}
       
   447 		}
       
   448 	return 0;
       
   449 	}
       
   450 
       
   451 CBTInqResultRef* CBTInqResultSet::NextResult()
       
   452 	{
       
   453 	LOG_FUNC
       
   454 	return iCurrentResult = (iNextRefIter++);
       
   455 	}
       
   456 
       
   457 inline CBTInqResultRef* CBTInqResultSet::CurrentResult()
       
   458 	{
       
   459 	LOG_FUNC
       
   460 	return iCurrentResult;
       
   461 	}
       
   462 
       
   463 void CBTInqResultSet::ReturnToFirstResult()
       
   464 	{
       
   465 	LOG_FUNC
       
   466 	iNextRefIter.SetToFirst();
       
   467 	iCurrentResult = 0;
       
   468 	}
       
   469 
       
   470 inline TBool CBTInqResultSet::IsEmpty()
       
   471 	{
       
   472 	LOG_FUNC
       
   473 	return iResultRefs.IsEmpty();
       
   474 	}
       
   475 
       
   476 void CBTInqResultSet::MoveToback(CBTInqResultRef& aRef)
       
   477 	{
       
   478 	LOG_FUNC
       
   479 	if(iNextRefIter == &aRef)
       
   480 		NextResult();
       
   481 	aRef.iLink.Deque();
       
   482 	iResultRefs.AddLast(aRef);
       
   483 	if (!iNextRefIter)
       
   484 		{
       
   485 		iNextRefIter.SetToLast();
       
   486 		}
       
   487 	}
       
   488 
       
   489 //
       
   490 //	BT Host resolver.
       
   491 //
       
   492 
       
   493 
       
   494 CBTHostResolver::CBTHostResolver(CBTInquiryMgr& aInquiryMgr)
       
   495 	: iInquiryMgr(aInquiryMgr), 
       
   496 	iRequestState(EIdle),
       
   497 	iInquiryStatus(EInquiryReady)
       
   498 	{
       
   499 	LOG_FUNC
       
   500 #ifdef _DEBUG
       
   501 	iInquiryMgr.IncrementHRCount();
       
   502 #endif
       
   503 	}
       
   504 
       
   505 CBTHostResolver::~CBTHostResolver()
       
   506 	{
       
   507 	LOG_FUNC
       
   508 	iLink.Deque();
       
   509 	iInquiryMgr.DeletingHostResolver();
       
   510 #ifdef _DEBUG
       
   511 	iInquiryMgr.DecrementHRCount();
       
   512 #endif
       
   513 	}
       
   514 
       
   515 void CBTHostResolver::GetByName(TNameRecord& /*aName*/)
       
   516 	{
       
   517 	LOG_FUNC
       
   518 	iNotify->QueryComplete(KErrNotSupported);
       
   519 	}
       
   520 
       
   521 void CBTHostResolver::GetByAddress(TNameRecord& aName)
       
   522 	{
       
   523 	LOG_FUNC
       
   524 	__ASSERT_DEBUG(iRequestState == EIdle, Panic(EHostResolverTwoRequests));
       
   525 	iNameRecord = &aName;
       
   526 	iNameRecord->iName.Zero();
       
   527 	TInquirySockAddr& sa = TInquirySockAddr::Cast(aName.iAddr);
       
   528 
       
   529 	LOG1(_L("Host Resolver\tAction = %d"),sa.Action());
       
   530 
       
   531 	if(sa.Action() & KHostResCache)
       
   532 		//Complete immediately with info if available!
       
   533 		{
       
   534 		TInt err = KErrNotFound;
       
   535 		CBTInqResultRef* ref = iInquiryMgr.FindExistingCacheEntry(sa.BTAddr());
       
   536 		if (ref)
       
   537 			{// Got a result to send up
       
   538 			CBTInqResultRecord& rec = ref->Result();
       
   539 			rec.GetInquirySockAddr(sa); //Put BT address, CoD etc into 'aName'
       
   540 			// Check whether client wants EIRs instead of names
       
   541 			if(sa.Action() & KHostResEir)
       
   542 				{
       
   543 				// Client knows about EIR, we'll fill the TNameRecord with EIR
       
   544 				err = rec.GetEir(aName, EFalse);
       
   545 				}
       
   546 			else
       
   547 				{
       
   548 				// Client don't knows about EIR, we'll fill the TNameRecord with just encoded device name if present
       
   549 				err = rec.GetName(aName);
       
   550 				}
       
   551 			if (err != KErrNone)
       
   552 				{// error getting name - but other stuff fine - 
       
   553 				 // so ensure name is not gobbledigook
       
   554 				aName.iName.Zero();
       
   555 				}
       
   556 			err = KErrNone; //err has new meaning now, vis "record exists"
       
   557 			}
       
   558 		else
       
   559 			{
       
   560 			//err is KErrNotFound
       
   561 			}
       
   562 					
       
   563 		iNotify->QueryComplete(err);
       
   564 		return;
       
   565 		}
       
   566 	
       
   567 	// Must request at least one of inquiry or name lookup
       
   568 	if (!(sa.Action() & (KHostResInquiry | KHostResName)))
       
   569 		{
       
   570 		iRequestState = EError;
       
   571 		CompleteRequest(KErrArgument);
       
   572 		return;
       
   573 		}
       
   574 
       
   575 	// Check the hw state - can't do anything if its switched off
       
   576 	//
       
   577 	if(iInquiryMgr.HWState()==CBTInquiryMgr::EOff)
       
   578 		{
       
   579 		iRequestState = EError;
       
   580 		CompleteRequest(KErrHardwareNotAvailable);
       
   581 		return;
       
   582 		}
       
   583 
       
   584 	iNameLookupMode = (sa.Action()) & KHostResName ? EDoGetNames : EDontGetNames;
       
   585 	TBool ignoreCache = (sa.Action() & KHostResIgnoreCache) ? ETrue : EFalse;
       
   586 
       
   587 	if (sa.Action() & KHostResInquiry)
       
   588 		{
       
   589 		// We only support GIAC and LIAC
       
   590 		if (sa.IAC() != KLIAC && sa.IAC() != KGIAC)
       
   591 			{
       
   592 			iRequestState = EError;
       
   593 			CompleteRequest(KErrNotSupported);
       
   594 			return;
       
   595 			}
       
   596 		sa.SetBTAddr(TBTDevAddr());
       
   597 		iRequestState = EInquiry;
       
   598 		if (iInquiryStatus == EInquiryReady)
       
   599 			{// Need to start the inquiry process
       
   600 			iInquiryStatus = EInquiring;
       
   601 			// We set this before calling StartInquiry, as StartInquiry can call InquiryComplete synchronously. 
       
   602 			iResults.Reset();
       
   603 			iInquiryMgr.StartInquiry(*this, sa.IAC(), ignoreCache);
       
   604 			}
       
   605 		}
       
   606 	else // Not an inquiry - just a name lookup
       
   607 		{
       
   608 		// Just name lookup -- add it to the result set, and request a lookup of it
       
   609 		iResults.Reset();
       
   610 
       
   611 		CBTInqResultRef* ref = iInquiryMgr.AddEntryToCache(sa.BTAddr());
       
   612 		if(ref)
       
   613 			{// This ref is in cache -- need to make our own ref
       
   614 			ref = iResults.Add(ref->Result());
       
   615 			}
       
   616 		if (!ref)
       
   617 			{
       
   618 			CompleteRequest(KErrNoMemory);
       
   619 			return;
       
   620 			}
       
   621 		iResults.NextResult(); // Move iter onto first (only) result
       
   622 		iRequestState = ENameLookup;
       
   623 		iInquiryMgr.LookupName(*this, sa.BTAddr(), ignoreCache, ETrue);
       
   624 		}
       
   625 	TryToCompleteRequest();
       
   626 	}
       
   627 
       
   628 TInt CBTHostResolver::SetOption(TUint /*aLevel*/, TUint /*aName*/, const TDesC8& /*aOption*/)
       
   629 	{
       
   630 	LOG_FUNC
       
   631 	return KErrNone;
       
   632 	}
       
   633 
       
   634 void CBTHostResolver::SetHostName(TDes& aNameBuf)
       
   635 	{
       
   636 	LOG_FUNC
       
   637 	__ASSERT_DEBUG(iRequestState == EIdle, Panic(EHostResolverTwoRequests));
       
   638 	
       
   639 	TBuf8<KHCILocalDeviceNameMaxLength> utf8Name;
       
   640 	TInt ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(utf8Name, aNameBuf);
       
   641 	iRequestState=ESetLocalName;
       
   642 	if (ret > KErrNone)
       
   643 		{// Unconverted characters exist! Error the client
       
   644 		ret = KErrHostResNameTooLong;
       
   645 		}
       
   646 
       
   647 	// Check the hw state - can't do anything if its switched off
       
   648 	//
       
   649 	if(iInquiryMgr.HWState()==CBTInquiryMgr::EOff)
       
   650 		{
       
   651 		ret = KErrHardwareNotAvailable;
       
   652 		}
       
   653 
       
   654 	if (ret == KErrNone)
       
   655 		ret = iInquiryMgr.SetLocalName(utf8Name);
       
   656 
       
   657 	if (ret != KErrNone)
       
   658 		{
       
   659 		CompleteRequest(ret);
       
   660 		}
       
   661 	}
       
   662 
       
   663 void CBTHostResolver::GetHostName(TDes& aNameBuf)
       
   664 	{
       
   665 	LOG_FUNC
       
   666 	__ASSERT_DEBUG(iRequestState == EIdle, Panic(EHostResolverTwoRequests));
       
   667 
       
   668 	iHostNameBuf = &aNameBuf;
       
   669 	iRequestState=EGetLocalName;
       
   670 	TInt ret = KErrNone;
       
   671 
       
   672 	// Check the hw state - can't do anything if its switched off
       
   673 	//
       
   674 	if(iInquiryMgr.HWState()==CBTInquiryMgr::EOff)
       
   675 		{
       
   676 		ret = KErrHardwareNotAvailable;
       
   677 		}
       
   678 
       
   679 	if(ret==KErrNone)
       
   680 		iInquiryMgr.GetLocalName();
       
   681 	else
       
   682 		CompleteRequest(ret);
       
   683 	}
       
   684 
       
   685 
       
   686 void CBTHostResolver::CancelCurrentOperation()
       
   687 /**
       
   688 	Current operation cancel by user app.
       
   689 	Reset, so that we don't bother picking up any future results.
       
   690 	We don't actually bother to cancel the async. operations, as
       
   691 	if they succeed, the InquiryMgr may as well cache them anyway.
       
   692 	The next operation after this (if there is any), must be a fresh
       
   693 	one -- i.e. it can not be a next.
       
   694 **/
       
   695 	{
       
   696 	LOG_FUNC
       
   697 	iRequestState = EIdle;
       
   698 	CompleteCurrentOperation();
       
   699 	}
       
   700 
       
   701 void CBTHostResolver::InquiryResult(CBTInqResultRecord& aResult)
       
   702 	{
       
   703 	LOG_FUNC
       
   704 	if (iInquiryStatus != EInquiring)
       
   705 		return;
       
   706 
       
   707 	// Check if we've already seen this result
       
   708 	CBTInqResultRef* ref = iResults.FindEntry(aResult.LogEntry().iBdaddr);
       
   709 	if (ref)
       
   710 		return;
       
   711 
       
   712 	TInquirySockAddr& sa = TInquirySockAddr::Cast(iNameRecord->iAddr);
       
   713 	if(!aResult.HasRespondedToIAC(sa.IAC()))
       
   714 		return; // It's never responded to our IAC, so ignore it
       
   715 
       
   716 	ref = iResults.Add(aResult);
       
   717 	if (!ref)
       
   718 		{
       
   719 		InquiryComplete(KErrNoMemory);
       
   720 		return;
       
   721 		}
       
   722 
       
   723 	if(iNameLookupMode == EDoGetNames)
       
   724 		{
       
   725 		// Find out whether cache was supposed to be ignored from TNameRecord that was passed into GetByAddress() previously
       
   726 		TBool ignoreCache = (sa.Action() & KHostResIgnoreCache) ? ETrue : EFalse;
       
   727 		// Handle a "special" case: Cache is to be ignored, but we got the _complete_ name during the inquiry process inside an EIR
       
   728 		// (which doesn't count as cached data, since it's freshly arrived from the radio). In this case we don't really want to 
       
   729 		// launch a remote name request
       
   730 		if(ignoreCache && ref->Result().IsEirPresent() && ref->Result().Codec().IsDataTypePresent(EEirLocalNameComplete))
       
   731 			{
       
   732 			// Do nothing, the entry already contains the name
       
   733 			}
       
   734 		else
       
   735 			{
       
   736 			iInquiryMgr.LookupName(*this, aResult.LogEntry().iBdaddr, ignoreCache, EFalse);
       
   737 			}
       
   738 		}
       
   739 
       
   740 	if (iRequestState == EInquiry)
       
   741 		{
       
   742 		TryToCompleteRequest();
       
   743 		}
       
   744 	}
       
   745 
       
   746 void CBTHostResolver::NameLookupResult(TInt aErr, const TBTDevAddr& aAddr, const TDesC8& aName)
       
   747 	{
       
   748 	LOG_FUNC
       
   749 	if (iNameLookupMode == EDontGetNames)
       
   750 		return; // We're not actually after names
       
   751 
       
   752 	// Check we've got this result recorded (mostly for error cases)
       
   753 	CBTInqResultRef* ref = iResults.FindEntry(aAddr);
       
   754 	if (ref && !(ref->Result().HaveNameLookupResult() && ref->Result().IsNameComplete()))
       
   755 		{
       
   756 		// we have successfully created a reference and there isn't a complete name available.
       
   757 		ref->Result().SetNameLookupResultCode(aErr);
       
   758 		ref->Result().SetNameComplete(ETrue);
       
   759 		ref->Result().SetName(aName);
       
   760 		}
       
   761 
       
   762 	TryToCompleteRequest();
       
   763 	}
       
   764 
       
   765 void CBTHostResolver::InquiryComplete(TInt aErr)
       
   766 	{
       
   767 	LOG_FUNC
       
   768 	// LC changed - if we are just doing a name lookup, iInquiryStatus
       
   769 	// doesn't get set so need additional check here.
       
   770 	//
       
   771 	if ((iInquiryStatus != EInquiring) && (iRequestState != ENameLookup))
       
   772 		return;
       
   773 	iInquiryStatus = EInquiryComplete;
       
   774 	iInqCompletionCode = aErr;
       
   775 	if(aErr==KErrHardwareNotAvailable)
       
   776 		iRequestState=EError;
       
   777 	TryToCompleteRequest();
       
   778 	}
       
   779 
       
   780 void CBTHostResolver::SetLocalNameComplete(TInt aErr)
       
   781 	{
       
   782 	LOG_FUNC
       
   783 	if (iRequestState != ESetLocalName)
       
   784 		return;
       
   785 	CompleteRequest(aErr);
       
   786 	}
       
   787 
       
   788 void CBTHostResolver::GetLocalNameComplete(TInt aErr, const TDesC8& aName)
       
   789 	{
       
   790 	LOG_FUNC
       
   791 	if (iRequestState != EGetLocalName)
       
   792 		return;
       
   793 	if (aErr == KErrNone)
       
   794 		{
       
   795 		aErr = CnvUtfConverter::ConvertToUnicodeFromUtf8(*iHostNameBuf, aName);
       
   796 		// Just allow names to be truncated...
       
   797 		}
       
   798 	CompleteRequest(aErr >= 0 ? KErrNone : aErr);
       
   799 	}
       
   800 
       
   801 TUint CBTHostResolver::GetIAC() const
       
   802 	{
       
   803 	LOG_FUNC
       
   804 	if (!iNameRecord)
       
   805 		{
       
   806 		return 0;		// avoid dereferencing a null ptr
       
   807 		}
       
   808 	
       
   809 	TInquirySockAddr& sa = TInquirySockAddr::Cast(iNameRecord->iAddr);
       
   810 	return sa.IAC();
       
   811 	}
       
   812 
       
   813 TInt CBTHostResolver::SecurityCheck(MProvdSecurityChecker *aSecurityChecker)
       
   814 	{
       
   815 	LOG_FUNC
       
   816 	__ASSERT_ALWAYS(aSecurityChecker, User::Panic(KSECURITY_PANIC, EBTPanicNullSecurityChecker));
       
   817 		
       
   818 	iSecurityChecker = aSecurityChecker;
       
   819 	return iSecurityChecker->CheckPolicy(KLOCAL_SERVICES, KBT_HOSTRESOLVER_NAME_DIAG);			
       
   820 	}
       
   821 
       
   822 void CBTHostResolver::TryToCompleteRequest()
       
   823 /**
       
   824 	This is where the work is done.
       
   825 	A big old state machine that tries to get us one step
       
   826 	closer to completing the query.
       
   827 	Gets an inquiry result out of the result set if appropriate and
       
   828 	there is one available.
       
   829 	Gets the name for the current result if required.
       
   830 	Completes the request if there is then nothing more to do.
       
   831 	Must only break out (i.e. return) if the request is completed, or
       
   832 	non-blocking mode requested
       
   833 **/
       
   834 	{
       
   835 	LOG_FUNC
       
   836 	TInquirySockAddr& sa = TInquirySockAddr::Cast(iNameRecord->iAddr);
       
   837 	if ((sa.Action() & KHostResInquiry) && iRequestState == EInquiry)
       
   838 		{
       
   839 		CBTInqResultRef* refNextRes = iResults.NextResult();
       
   840 		if (refNextRes)
       
   841 			{// Got a result to send up
       
   842 			if (iNameLookupMode == EDoGetNames)
       
   843 				{// Need to get the name of this baby...
       
   844 				iRequestState = ENameLookup;
       
   845 				}
       
   846 			else
       
   847 				{//Complete!
       
   848 				refNextRes->Result().GetInquirySockAddr(sa);
       
   849 				// If EIR was requested and we got one, stick it in the name field
       
   850 				TInt err = KErrNone;
       
   851 				if(sa.Action() & KHostResEir)
       
   852 					{
       
   853 					err = refNextRes->Result().GetEir(*iNameRecord, (sa.Action() & KHostResIgnoreCache) && !(sa.Action() & KHostResName));
       
   854 					}
       
   855 				else
       
   856 					{
       
   857 					err = refNextRes->Result().GetName(*iNameRecord);
       
   858 					}
       
   859 				if(err != KErrNone)
       
   860 					{
       
   861 					// Set name back to zero length
       
   862 					iNameRecord->iName.Zero();
       
   863 					}
       
   864 				CompleteRequest(err);
       
   865 				return;
       
   866 				}
       
   867 			}
       
   868 		else if (iInquiryStatus == EInquiryComplete)
       
   869 			{// Bad luck. No more results availble!
       
   870 			if (iInqCompletionCode == KErrNone)
       
   871 				{// Inquiry completed fine, so report end of file.
       
   872 				CompleteRequest(KErrHostResNoMoreResults);
       
   873 				}
       
   874 			else
       
   875 				{// Some error in the inquiry, so report that.
       
   876 				CompleteRequest(iInqCompletionCode);
       
   877 				}
       
   878 			return;
       
   879 			}
       
   880 		}
       
   881 
       
   882 	if ((sa.Action() & KHostResName) && iRequestState == ENameLookup)
       
   883 		{
       
   884 		CBTInqResultRef* refNextRes = iResults.CurrentResult();
       
   885 		if(!refNextRes)
       
   886 			{// Can't get the name... no result to lookup
       
   887 			CompleteRequest(KErrHostResNoMoreResults);
       
   888 			return;
       
   889 			}
       
   890 		// Walk through results and check if we have a name to complete
       
   891 		CBTInqResultRef* startResult = refNextRes;
       
   892 		do
       
   893 			{
       
   894 			CBTInqResultRecord& rec = refNextRes->Result();
       
   895 			if(rec.HaveNameLookupResult() && !rec.IsNameRequestPending() && rec.IsNameComplete())
       
   896 				{// Got a name! Complete the request
       
   897 				rec.GetInquirySockAddr(sa);
       
   898 				TInt err = rec.NameLookupResultCode();
       
   899 				if (err == KErrNone)
       
   900 					{// Copy & convert the UTF-8 name over into the result record.
       
   901 					if(sa.Action() & KHostResEir)
       
   902 						{
       
   903 						err = rec.GetEir(*iNameRecord, EFalse);
       
   904 						}
       
   905 					else
       
   906 						{
       
   907 						err = rec.GetName(*iNameRecord);
       
   908 						}
       
   909 					}
       
   910 				if (err != KErrNone)
       
   911 					{
       
   912 					iNameRecord->iName.Zero();
       
   913 					}
       
   914 				// Name lookup complete (poss. with errors)
       
   915 				if(sa.Action() & KHostResInquiry)
       
   916 					{// Ignore name failures if we're also doing inquiry
       
   917 					CompleteRequest(KErrNone);
       
   918 					}
       
   919 				else
       
   920 					{// Report any error encountered (or none)
       
   921 					CompleteRequest(err);
       
   922 					}
       
   923 				return;
       
   924 				}
       
   925 
       
   926 			iResults.MoveToback(*refNextRes);
       
   927 			refNextRes = iResults.NextResult();
       
   928 			} while(refNextRes != startResult);
       
   929 		}
       
   930 	else if(iRequestState==EError)
       
   931 		{
       
   932 		CompleteRequest(KErrHardwareNotAvailable);
       
   933 		}
       
   934 	if(sa.Action() & KHostResDontBlock)
       
   935 		{// Complete any outstanding non-blocking operation
       
   936 		CompleteRequest(KErrWouldBlock);
       
   937 		}
       
   938 
       
   939 	}
       
   940 
       
   941 void CBTHostResolver::CompleteRequest(TInt aErr)
       
   942 	{
       
   943 	LOG_FUNC
       
   944 	if (iRequestState == EIdle && aErr == KErrNone) 
       
   945 		return;
       
   946 	iRequestState = EIdle;
       
   947 	if (aErr != KErrNone)
       
   948 		{// End of query -- tidy up
       
   949 		CompleteCurrentOperation();
       
   950 		}
       
   951 	iNotify->QueryComplete(aErr);
       
   952 	}
       
   953 
       
   954 void CBTHostResolver::CompleteCurrentOperation()
       
   955 /**
       
   956 	Operation known to be complete.
       
   957 	This happens through a CancelCurrentOperation, or when
       
   958 	the current operation has read all the results out.
       
   959 **/
       
   960 	{
       
   961 	LOG_FUNC
       
   962 	if (iInquiryStatus == EInquiryReady)
       
   963 		return;
       
   964 	iInquiryStatus = EInquiryReady;
       
   965 	iResults.Reset();
       
   966 	}
       
   967 
       
   968 
       
   969 //
       
   970 //	BT Inquiry Manager.
       
   971 //
       
   972 CBTInquiryMgr::CBTInquiryMgr(CLinkMgrProtocol& aProtocol)
       
   973 	: iLinkMgrProtocol(aProtocol),
       
   974 	iNamePageTimeout((KMaxNamePageTimeout + KMinNamePageTimeout)/2), // start with mid-point timeout
       
   975 	iInquiryMode(EStandardInquiryFormat), iHRs(CBTHostResolver::LinkOffset())
       
   976 	{
       
   977 	LOG_FUNC
       
   978 	}
       
   979 
       
   980 CBTInquiryMgr::~CBTInquiryMgr()
       
   981 	{
       
   982 	LOG_FUNC
       
   983 	__ASSERT_DEBUG(iHRs.IsEmpty(), Panic(EBTHostControllerQueueNotEmpty));
       
   984 	SetHWState(EOff);
       
   985 	PublishStatus();// we're not doing anything more so publish status
       
   986 	ClearHCICommandQueue();
       
   987 	delete iFlusher;
       
   988 	delete iConnectingStatus;
       
   989 	}
       
   990 
       
   991 void CBTInquiryMgr::ClearHCICommandQueue()
       
   992 	{
       
   993 	LOG_FUNC
       
   994 	if (iCommandQueue)
       
   995 		{
       
   996 		iCommandQueue->MhcqRemoveAllCommands(*this);
       
   997 		}
       
   998 	iCommandQueue = NULL;
       
   999 	}
       
  1000 
       
  1001 void CBTInquiryMgr::SetHCICommandQueue(MHCICommandQueue& aCommandQueue)
       
  1002 	{
       
  1003 	LOG_FUNC
       
  1004 	__ASSERT_DEBUG(!iCommandQueue, Panic(EBTCommandQueueAlreadyExist));
       
  1005 	iCommandQueue = &aCommandQueue;
       
  1006 	}
       
  1007 
       
  1008 MHCICommandQueue& CBTInquiryMgr::CommandQueue() const
       
  1009 	{
       
  1010 	LOG_FUNC
       
  1011 	__ASSERT_DEBUG(iCommandQueue, Panic(EBTCommandQueueNotFound));
       
  1012 	return *iCommandQueue;
       
  1013 	}
       
  1014 
       
  1015 CBTInquiryMgr* CBTInquiryMgr::NewL(CLinkMgrProtocol& aProtocol)
       
  1016 	{
       
  1017 	LOG_STATIC_FUNC
       
  1018 	CBTInquiryMgr* self = new(ELeave) CBTInquiryMgr(aProtocol);
       
  1019 	CleanupStack::PushL(self);
       
  1020 	self->ConstructL();
       
  1021 	CleanupStack::Pop();
       
  1022 	return self;
       
  1023 	}
       
  1024 
       
  1025 void CBTInquiryMgr::ConstructL()
       
  1026 	{
       
  1027 	LOG_FUNC
       
  1028 	iFlusher = CPeriodic::NewL(CActive::EPriorityLow);
       
  1029 #ifdef CONNECTION_PREEMPTS_INQUIRY
       
  1030 	iConnectingStatus = CConnectingStatusSubscriber::NewL(*this);
       
  1031 #endif
       
  1032 	}
       
  1033 
       
  1034 CBTHostResolver* CBTInquiryMgr::NewHostResolverL()
       
  1035 	{
       
  1036 	LOG_FUNC
       
  1037 	// Leave if HW switched off
       
  1038 	//
       
  1039 	if(iHWState==EOff)
       
  1040 		User::Leave(KErrHardwareNotAvailable);
       
  1041 
       
  1042 	CBTHostResolver* r = new(ELeave) CBTHostResolver(*this);
       
  1043 	iHRs.AddFirst(*r);
       
  1044 	return r;
       
  1045 	}
       
  1046 
       
  1047 void CBTInquiryMgr::DeletingHostResolver()
       
  1048 	{
       
  1049 	LOG_FUNC
       
  1050 	// A host resolver is being deleted - we need to check if any other host resolvers want inquiry results from the current IAC.
       
  1051 	if(!iRequestedInquiryIAC)
       
  1052 		{
       
  1053 		 //No 'current' IAC exists
       
  1054 		 return;		 
       
  1055 		}
       
  1056 	TDblQueIter<CBTHostResolver> iter(iHRs);
       
  1057 	TBool iacFound=EFalse;
       
  1058 	while (iter)
       
  1059 		{
       
  1060 		if ((iter++)->GetIAC() == iRequestedInquiryIAC)
       
  1061 			{
       
  1062 			iacFound = ETrue;
       
  1063 			}
       
  1064 		}
       
  1065 	if (!iacFound)
       
  1066 		{
       
  1067 		iRequestedInquiryIAC = 0;
       
  1068 		}
       
  1069 	}
       
  1070 
       
  1071 void CBTInquiryMgr::InquiryResult(TInt aErr,const TInquiryLogEntry& aEntry)
       
  1072 /**
       
  1073 	Single Inquiry result received.
       
  1074 	Called via HCI for each incoming inquiry result. Need to demultiplex these
       
  1075 	out to all CBTHostResolver's interested in them.
       
  1076 
       
  1077 	@param  aErr	An EPOC error code. Any HCI mapping should be done before
       
  1078 					calling this function.
       
  1079 	@param	aEntry	The log entry returned through HCI.
       
  1080 **/
       
  1081 	{
       
  1082 	LOG_FUNC
       
  1083 	LOG5(_L("err: %d,ScanRepM: %d ScanPerM: %d ScanM: %d Type: %d"),
       
  1084 				 aErr,
       
  1085 				 aEntry.iPageScanRepetitionMode,
       
  1086 				 aEntry.iPageScanPeriodMode,
       
  1087 				 aEntry.iPageScanMode,
       
  1088 			   	 aEntry.iSpare );
       
  1089 
       
  1090 	CBTInqResultRef* ref = 0;
       
  1091 
       
  1092 	//Revise our cache record regardless - at least need to make sure
       
  1093 	//it knows we have received juice from the HCI	
       
  1094 	if(aErr == KErrNone)
       
  1095 		{
       
  1096 		ref = AddEntryWithJuiceToCache(aEntry);
       
  1097 		if (!ref)
       
  1098 			{
       
  1099 			aErr = KErrNoMemory;
       
  1100 			}
       
  1101 		else
       
  1102 			{
       
  1103 			ref->Result().iFlushes = 0;
       
  1104 			ref->Result().iFoundDuringCurrentInquiry = ETrue;
       
  1105 
       
  1106 			TInt ret = ref->Result().AddIAC(iCurrentInquiryIAC);
       
  1107 			switch(ret)
       
  1108 				{
       
  1109 			case KErrNone:
       
  1110 				++iResultCount;
       
  1111 				// drop through
       
  1112 			case KErrAlreadyExists:
       
  1113 				break;
       
  1114 			default: // Got an error adding the IAC
       
  1115 				aErr = ret;
       
  1116 				} // switch
       
  1117 			ref->Result().AddIAC(KGIAC); // This would come back on a GIAC, so try adding GIAC.
       
  1118 			// If this doesn't work, it doesn't really matter, so ignore the error.
       
  1119 			} // else
       
  1120 		} // if (aErr == KErrNone)
       
  1121 
       
  1122 	if (aErr != KErrNone)
       
  1123 		{
       
  1124 		InquiryComplete(aErr, 0);
       
  1125 		return;
       
  1126 		}
       
  1127 
       
  1128 	// Tell host resolvers
       
  1129 	TDblQueIter<CBTHostResolver> iter(iHRs);
       
  1130 	CBTHostResolver* hr;
       
  1131 	while ((hr = iter ++) != NULL)
       
  1132 		{
       
  1133 		if (hr->GetIAC() == iCurrentInquiryIAC || hr->GetIAC() == KGIAC)
       
  1134 			{
       
  1135 			hr->InquiryResult(ref->Result());
       
  1136 			}
       
  1137 		}
       
  1138 	}
       
  1139 
       
  1140 void CBTInquiryMgr::CoDResult(const TBTDevAddr& aAddr, TUint aCoD)
       
  1141 /**
       
  1142 	We have been donated a CoD from an incoming connection
       
  1143 	This is useful to keep in the registry for remotely
       
  1144 	initiated pairings - otherwise we will never have found
       
  1145 	the CoD of the device bonding with us
       
  1146 **/	
       
  1147 	{
       
  1148 	// create record if it doesn't already exist in cache. 
       
  1149 	// If this fails, we'll just not be able to store the CoD for this device.
       
  1150 
       
  1151 	LOG_FUNC
       
  1152 	AddEntryWithCoDToCache(aAddr, aCoD);
       
  1153 	}
       
  1154 
       
  1155 void CBTInquiryMgr::ClockOffsetResult(const TBTDevAddr& aAddr, TBasebandTime aClockOffset)
       
  1156 /**
       
  1157 	We have been donated a Clock Offset - maybe an update
       
  1158 **/	
       
  1159 	{
       
  1160 	LOG_FUNC
       
  1161 	AddEntryWithClockOffsetToCache(aAddr, aClockOffset);
       
  1162 	}
       
  1163 
       
  1164 void CBTInquiryMgr::InquiryComplete(TInt aErr, TUint8 /*aNumResponses*/)
       
  1165 /**
       
  1166 	Current Inquiry has completed.
       
  1167 	Must tell all CBTHostResolver's who may be waiting for inquiry results.
       
  1168 
       
  1169 	@param  aErr	An EPOC error code. Any HCI mapping should be done before
       
  1170 					calling this function.
       
  1171 	@param	aNumResponses	The number of calls to InquiryResult that should
       
  1172 					have been generated. We don't use this info atm, though.
       
  1173 **/
       
  1174 	{
       
  1175 	LOG_FUNC
       
  1176 	SetCacheAge(iCurrentInquiryIAC, 0);
       
  1177 	TUint iacToComplete = iRequestedInquiryIAC;
       
  1178 	iRequestedInquiryIAC = 0;
       
  1179 	iFlusher->Cancel(); // Stop watchdog, start flusher
       
  1180 	SetHWState(EIdle);
       
  1181 	// don't publish status here, might be doing a name lookup
       
  1182 	EnableFlusher();
       
  1183 
       
  1184 	// The inquiry has completed so clear any results that were marked found during
       
  1185 	// the just finished inquiry
       
  1186 	ClearCurrentInquiryResults();
       
  1187 
       
  1188 	if(aErr!=KErrHardwareNotAvailable)
       
  1189 		{
       
  1190 		LOG(_L("CBTInquiryMgr::InquiryComplete asking for another name lookup"));
       
  1191 		DoNameLookup(ETrue); // Get any pending name lookups going
       
  1192 		}
       
  1193 	else
       
  1194 		{
       
  1195 		SetHWState(EOff);
       
  1196 		LOG(_L("CBTInquiryMgr::InquiryComplete PublishState Idle"));
       
  1197 		PublishStatus();// we're not doing name lookup so publish status
       
  1198 		}
       
  1199 	TDblQueIter<CBTHostResolver> iter(iHRs);
       
  1200 	CBTHostResolver* hr;
       
  1201 	while ((hr = iter++) != NULL)
       
  1202 		{
       
  1203 		if (hr->GetIAC() == iacToComplete)
       
  1204 			{
       
  1205 			hr->InquiryComplete(aErr);
       
  1206 			}
       
  1207 		hr++;
       
  1208 		}
       
  1209 	// Only queue the inquiry if we have completed all the name requests from this one.
       
  1210 	// Otherwise, it will be issued after all the remote name requests have completed.
       
  1211 	if (iQueuedInquiryIAC != 0 && iPendingNameRequests == 0)
       
  1212 		{
       
  1213 		iRequestedInquiryIAC = iQueuedInquiryIAC;
       
  1214 		iQueuedInquiryIAC = 0;
       
  1215 		DoInquiry();
       
  1216 		}
       
  1217 	}
       
  1218 
       
  1219 /**
       
  1220 Name lookup result received.
       
  1221 Called via HCI for each incoming name result.
       
  1222 
       
  1223 The name lookup may not have been requested by the inquiry mgr as when the
       
  1224 stack gets a new connection it tries to solicit information about the
       
  1225 remote.  This sort of result is just to add to our cache.
       
  1226 
       
  1227 Otherwise it's from a request on us, pass it on for handling.
       
  1228 
       
  1229 @param	aErr	An EPOC error code. Any HCI mapping should be done before
       
  1230 				calling this function.
       
  1231 @param	aAddr	The address of the Bluetooth device that the name is associated
       
  1232 				with.
       
  1233 @param	aBuf	8 bit Descriptor up to KHCIRemoteDeviceNameMaxLength
       
  1234 				bytes long, containing the name.
       
  1235 */
       
  1236 void CBTInquiryMgr::RemoteNameResult(TInt aErr, const TBTDevAddr& aAddr, const TBTDeviceName8& aBuf)
       
  1237 	{
       
  1238 	LOG_FUNC
       
  1239 	LOG1(_L("aErr = %d"), aErr);
       
  1240 	LOG6(_L(", aAddr: %02x %02x %02x %02x %02x %02x"),
       
  1241 			  TUint8(aAddr[0]), TUint8(aAddr[1]), TUint8(aAddr[2]), TUint8(aAddr[3]), TUint8(aAddr[4]), 
       
  1242 			  TUint8(aAddr[5]));
       
  1243 
       
  1244 	CBTInqResultRef* ref = FindExistingCacheEntry(aAddr);
       
  1245 	if(ref)
       
  1246 		{
       
  1247 		CBTInqResultRecord& rec = ref->Result();
       
  1248 		if (rec.IsNameRequestPending())
       
  1249 			{
       
  1250 			// We asked for this
       
  1251 			HandleRemoteNameResult(aErr, *ref, aBuf);
       
  1252 			return;
       
  1253 			}
       
  1254 		}
       
  1255 
       
  1256 	// Unsolicited, just wham in cache if it's good
       
  1257 	if (aErr == KErrNone)
       
  1258 		{
       
  1259 		CBTInqResultRef* ref = AddEntryToCache(aAddr);
       
  1260 		if(ref)
       
  1261 			{
       
  1262 			CBTInqResultRecord& rec = ref->Result();
       
  1263 
       
  1264 			rec.SetName(aBuf);
       
  1265 			rec.SetNameComplete(ETrue);
       
  1266 			rec.iFlushes = 0;
       
  1267 			rec.SetNameValid(ETrue);
       
  1268 			rec.SetNameRefreshRequested(EFalse);
       
  1269 			}
       
  1270 		}
       
  1271 	}
       
  1272 
       
  1273 /**
       
  1274 Remote host supported features notification received.
       
  1275 
       
  1276 The remote host supported feature notification may be received during a
       
  1277 remote name request if the remote device provides entries in the remote
       
  1278 host supported feature page.
       
  1279 
       
  1280 @param	aErr	An EPOC error code. Any HCI mapping should be done before
       
  1281 				calling this function.
       
  1282 @param	aAddr	The address of the Bluetooth device that the name is associated
       
  1283 				with.
       
  1284 @param	aHostSupportedFeatures	64 bit field holding the remote host supported
       
  1285 				features page.
       
  1286 */
       
  1287 void CBTInquiryMgr::RemoteHostSupportedFeatures(TInt /*aErr*/, const TBTDevAddr& /*aAddr*/, const TUint64& /*aHostSupportedFeatures*/)
       
  1288 	{
       
  1289 	LOG_FUNC
       
  1290 	// This is currently not used by the stack since the optimisation it could provide would be
       
  1291 	// difficult to take advantage of and of minimal use.
       
  1292 
       
  1293 	// If to be used the result should be stored in the inquiry result record along with whether
       
  1294 	// a name request has been made (with EIR it is possible to have retrieved the name without
       
  1295 	// a name request)
       
  1296 	}
       
  1297 
       
  1298 /**
       
  1299 Name lookup result received.
       
  1300 
       
  1301 We need to demultiplex these out to all CBTHostResolver's
       
  1302 interested in them.
       
  1303 
       
  1304 @param  aErr	An EPOC error code. Any HCI mapping should be done before
       
  1305 				calling this function.
       
  1306 @param	aRef	The inquiry result for this info.
       
  1307 @param	aBuf	8 bit Descriptor up to KHCIRemoteDeviceNameMaxLength
       
  1308 				bytes long, containing the name.
       
  1309 */
       
  1310 void CBTInquiryMgr::HandleRemoteNameResult(TInt aErr, CBTInqResultRef& aRef, const TBTDeviceName8& aBuf)
       
  1311 	{
       
  1312 	LOG_FUNC
       
  1313 	
       
  1314 	if(iHWState != EConnecting)
       
  1315 		{
       
  1316 		SetHWState(EIdle);
       
  1317 		// don't set publish status here, doinquiry will do that
       
  1318 		}
       
  1319 		
       
  1320 	if(aErr == KErrNone)
       
  1321 		{
       
  1322 		if(iNamePageTimeout > KMinNamePageTimeout)
       
  1323 			{// got name OK, dec the page timeout
       
  1324 			iNamePageTimeout -= KNamePageTimeoutIncrement;
       
  1325 			}
       
  1326 		}
       
  1327 	else if(aErr == KHCIErrorBase - EPageTimedOut)
       
  1328 		{
       
  1329 		if(iNamePageTimeout < KMaxNamePageTimeout)
       
  1330 			{// Got pagetime, inc. pagetime a bit
       
  1331 			iNamePageTimeout += KNamePageTimeoutIncrement;
       
  1332 			}
       
  1333 		}
       
  1334 
       
  1335 
       
  1336 	CBTInqResultRecord& rec = aRef.Result();
       
  1337 
       
  1338 	--iPendingNameRequests;
       
  1339 	rec.SetNamePending(EFalse);
       
  1340 	++(rec.iNameLookupAttempts);
       
  1341 	if(iPendingNameRequests <= 0)
       
  1342 		{
       
  1343 		iNewPageRequestsPending = EFalse;
       
  1344 		}
       
  1345 
       
  1346 	// Update our cached version.
       
  1347 	if (aErr == KErrNone)
       
  1348 		{
       
  1349 		rec.SetName(aBuf);
       
  1350 		rec.SetNameComplete(ETrue);
       
  1351 		rec.iFlushes = 0;
       
  1352 		rec.SetNameValid(ETrue);
       
  1353 		rec.SetNameRefreshRequested(EFalse);
       
  1354 		rec.SetExplicitNameRequest(EFalse); // If we had an explicit name request on this, we've completed it now
       
  1355 		}
       
  1356 	else
       
  1357 		{
       
  1358 		// got an error
       
  1359 		if(rec.NameLookupAttempts() < KMaxNameLookupAttempts)
       
  1360 			{// try to get later - put to back of Que for getting
       
  1361 			++iPendingNameRequests;
       
  1362 			rec.SetNamePending(ETrue);
       
  1363 			iCurrentResults.MoveToback(aRef);
       
  1364 			}
       
  1365 		else
       
  1366 			{// No more chances -- record lookup error code
       
  1367 			rec.SetNameLookupResultCode(aErr);
       
  1368 			rec.SetExplicitNameRequest(EFalse); // If we had an explicit name request on this, we've completed it now
       
  1369 			}
       
  1370 		}
       
  1371 
       
  1372 	// Try to get more names, if needed
       
  1373 	LOG(_L("CBTInquiryMgr::HandleRemoteNameResult asking for another name lookup"));
       
  1374 	DoNameLookup(EFalse);
       
  1375 
       
  1376 	if(!aRef.Result().IsNameRequestPending())
       
  1377 		{// Don't propogate if name request is still pending
       
  1378 		TDblQueIter<CBTHostResolver> iter(iHRs);
       
  1379 		while (iter)
       
  1380 			{
       
  1381 			(iter++)->NameLookupResult(aErr, rec.LogEntry().iBdaddr, aBuf);
       
  1382 			}
       
  1383 		}
       
  1384 
       
  1385 	// In case we're now free, do inquiry
       
  1386 	LOG(_L("CBTInquiryMgr::HandleRemoteNameResult asking for another inquiry"));
       
  1387 	if (iPendingNameRequests == 0 && iRequestedInquiryIAC == 0) // If we've completed the current inquiry, see if we've got another one queued.
       
  1388 		{
       
  1389 		iRequestedInquiryIAC = iQueuedInquiryIAC;
       
  1390 		iQueuedInquiryIAC = 0;
       
  1391 		}
       
  1392 	DoInquiry();
       
  1393 	}
       
  1394 
       
  1395 const TDesC8* CBTInquiryMgr::DeviceNameFromCache(const TBTDevAddr& aAddr)
       
  1396 /**
       
  1397 	Used by other parts of the stack to get a name synchronously from cache if
       
  1398 	there is one
       
  1399 
       
  1400 	@return NULL if device is unknwon
       
  1401 **/
       
  1402 	{
       
  1403 	LOG_FUNC
       
  1404 	CBTInqResultRef* entry = FindExistingCacheEntry(aAddr);
       
  1405 	if (!entry)
       
  1406 		return NULL;
       
  1407 	else
       
  1408 		{
       
  1409 		return &entry->Result().Name(); 
       
  1410 		}
       
  1411 	}
       
  1412 
       
  1413 CBTInqResultRecord* CBTInquiryMgr::BasebandParametersFromCache(const TBTDevAddr& aAddr)
       
  1414 	{
       
  1415 	LOG_FUNC
       
  1416 	CBTInqResultRef* entry = FindExistingCacheEntry(aAddr);
       
  1417 	if (!entry)
       
  1418 		return NULL;
       
  1419 	else
       
  1420 		{
       
  1421 		return &(entry->Result());
       
  1422 		}
       
  1423 	}
       
  1424 
       
  1425 void CBTInquiryMgr::SetHWState(THWState aState)
       
  1426 	{
       
  1427 	LOG_FUNC
       
  1428 	iHWState = aState;
       
  1429 	}
       
  1430 
       
  1431 void CBTInquiryMgr::PublishStatus()
       
  1432 	{
       
  1433 	LOG_FUNC
       
  1434 	// sets the inquiry/discovery status to bool true or false
       
  1435 	TBool inquiryState = EFalse;
       
  1436 
       
  1437 	switch (iHWState)
       
  1438 		{
       
  1439 	/* deliberate fall throughs */
       
  1440 	case EInquiry:
       
  1441 	case ENameLookup:
       
  1442 		{	
       
  1443 		inquiryState = ETrue;
       
  1444 		}
       
  1445 		break;
       
  1446 	case EIdle:
       
  1447 	case EConnecting:
       
  1448 	case EOff:
       
  1449 	default:
       
  1450 		{
       
  1451 		// defaulted above to EFalse;
       
  1452 		}
       
  1453 		break;
       
  1454 		}
       
  1455 	/* only publish status if we've changed	
       
  1456 	 it is however the case that if the state changes sufficiently quickly
       
  1457 	 the subscriber will miss some of the state changes 
       
  1458 	 this is particularly the case while doing name searches where we toggle into 
       
  1459 	 idle and back to namelookup quickly and regularly, the subscriber
       
  1460 	 sees a stream of etrues coming through, the efalses are missing
       
  1461 	 this is probably ok as long as they know because this means they are told 
       
  1462 	 more than once they are inquiring, and indeed they are, its certainly better
       
  1463 	 than being told they're not if they are */	
       
  1464 	if (inquiryState != iReportedInquiryState)
       
  1465 		{		
       
  1466 		iLinkMgrProtocol.SetUIDiscovering(inquiryState);
       
  1467 		iReportedInquiryState = inquiryState;
       
  1468 		if (inquiryState)
       
  1469 			{
       
  1470 			LOG(_L("CBTInquiryMgr::PublishState setting status TRUE"));
       
  1471 			}
       
  1472 		else
       
  1473 			{
       
  1474 			LOG(_L("CBTInquiryMgr::PublishState setting status FALSE"));
       
  1475 			}
       
  1476 		}
       
  1477 	else
       
  1478 		{
       
  1479 		LOG(_L("CBTInquiryMgr::PublishState not updating status"));
       
  1480 		}			
       
  1481  	}
       
  1482 
       
  1483 void CBTInquiryMgr::SetLocalNameComplete(TInt aErr)
       
  1484 	{
       
  1485 	LOG_FUNC
       
  1486 	TDblQueIter<CBTHostResolver> iter(iHRs);
       
  1487 	while (iter)
       
  1488 		{
       
  1489 		(iter++)->SetLocalNameComplete(aErr);
       
  1490 		}
       
  1491 	}
       
  1492 
       
  1493 void CBTInquiryMgr::GetLocalNameComplete(TInt aErr, const TDesC8& aName)
       
  1494 	{
       
  1495 	LOG_FUNC
       
  1496 	TDblQueIter<CBTHostResolver> iter(iHRs);
       
  1497 	while (iter)
       
  1498 		{
       
  1499 		(iter++)->GetLocalNameComplete(aErr, aName);
       
  1500 		}
       
  1501 	}
       
  1502 
       
  1503 void CBTInquiryMgr::StartInquiry(CBTHostResolver& aResolver, TUint aIAC, TBool aIgnoreCache)
       
  1504 	{
       
  1505 	LOG_FUNC
       
  1506 	// Pre-load any existing results into the CBTHostResolver
       
  1507 	if (!aIgnoreCache)
       
  1508 		{
       
  1509 		// Pre-load any existing results into the CBTHostResolver
       
  1510 		iCurrentResults.ReturnToFirstResult();
       
  1511 		while (CBTInqResultRef* ref = iCurrentResults.NextResult())
       
  1512 			{
       
  1513 			// If GIAC is being requested, we return all results
       
  1514 			if (aIAC == KGIAC || ref->Result().HasRespondedToIAC(aIAC))
       
  1515 				{
       
  1516 				aResolver.InquiryResult(ref->Result());
       
  1517 				}
       
  1518 			}
       
  1519 		}
       
  1520 	
       
  1521 	if ( !aIgnoreCache && !iCurrentResults.IsEmpty() && CacheAge(aIAC) <= KCacheStaleAge)
       
  1522 		{// Cache not yet stale, so just give these results back and dont start
       
  1523 		LOG(_L("CBTInquiryMgr::StartInquiry giving result from cache"));
       
  1524 		aResolver.InquiryComplete(KErrNone);
       
  1525 		return;
       
  1526 		}
       
  1527 	
       
  1528 	if (iRequestedInquiryIAC || iQueuedInquiryIAC)
       
  1529 		{
       
  1530 		LOG(_L("CBTInquiryMgr::StartInquiry iRequestedInquiryIAC"));
       
  1531 		if(iRequestedInquiryIAC == aIAC)
       
  1532 			{
       
  1533 			// an Inquiry is ongoing, return any results already found during the
       
  1534 			// current Inquiry if not already done so as part of the complete cache
       
  1535 			if (aIgnoreCache)
       
  1536 				{
       
  1537 				iCurrentResults.ReturnToFirstResult();
       
  1538 				while (CBTInqResultRef* ref = iCurrentResults.NextResult())
       
  1539 					{
       
  1540 					if (ref->Result().iFoundDuringCurrentInquiry)
       
  1541 						{
       
  1542 						aResolver.InquiryResult(ref->Result());
       
  1543 						}
       
  1544 					}	
       
  1545 				}
       
  1546 			// the current Inquiry will just continue
       
  1547 			return;			
       
  1548 			}
       
  1549 		if (aIAC == KGIAC)
       
  1550 			{
       
  1551 			// If the current IAC is GIAC, and the requested inquiry IAC isn't, it must be LIAC
       
  1552 			__ASSERT_DEBUG(iRequestedInquiryIAC == KLIAC, Panic(EBTUnexpectedIAC)); 
       
  1553 			// Queue a general inquiry for when the current limited inquiry has finished
       
  1554 			iQueuedInquiryIAC = aIAC;
       
  1555 			return;
       
  1556 			}
       
  1557 		else if(iHWState == EInquiry)
       
  1558 			{
       
  1559 			// The host resolver should only allow through GIAC and LIAC, and we handle GIAC above
       
  1560 			__ASSERT_DEBUG(aIAC == KLIAC, Panic(EBTUnexpectedIAC)); 
       
  1561 			// We favour a Limited inqiury, so interrupt the current general inquiry
       
  1562 			TInt err = CancelHardwareInquiry();
       
  1563 			if(err!=KErrNone)
       
  1564 				{
       
  1565 				LOG(_L("CBTInquiryMgr::StartInquiry cancel didn't work"));
       
  1566 				aResolver.InquiryComplete(err); // cancel went wrong
       
  1567 				return;
       
  1568 				}
       
  1569 			// Queue a general inquiry for when the limited inquiry is complete
       
  1570 			iRequestedInquiryIAC = KLIAC;
       
  1571 			iQueuedInquiryIAC = KGIAC;
       
  1572 			SetHWState(ECancellingForNewIAC);
       
  1573 			iFlusher->Cancel(); 	// Stop watchdog, start flusher.
       
  1574 			return;
       
  1575 			}
       
  1576 		else
       
  1577 			{
       
  1578 			// The host resolver should only allow through GIAC and LIAC, and we handle GIAC above
       
  1579 			__ASSERT_DEBUG(aIAC == KLIAC, Panic(EBTUnexpectedIAC)); 
       
  1580 			iRequestedInquiryIAC = KLIAC;
       
  1581 			iQueuedInquiryIAC = KGIAC;
       
  1582 			}
       
  1583 		}
       
  1584 
       
  1585 	iRequestedInquiryIAC = aIAC;
       
  1586 	iInquiryInteruptions = 0;
       
  1587 
       
  1588 	DoInquiry();
       
  1589 	}
       
  1590 
       
  1591 void CBTInquiryMgr::Suspend()
       
  1592 /**
       
  1593 	Ah - somebody wishes to make a connection - we need to clear the way
       
  1594 	If we are doing a namerequest we can cancel.
       
  1595 	
       
  1596 	WARNING - The caller of this must ensure a call to Resume() ASAP
       
  1597 **/
       
  1598 	{
       
  1599 	LOG_FUNC
       
  1600 
       
  1601 	if(iHWState == EInquiry)
       
  1602 		{
       
  1603 		// This is a best effort service, the Connect will be tried even
       
  1604 		// if we fail to stop the inquiry, so ignore errors.
       
  1605 		static_cast<void>(CancelHardwareInquiry());
       
  1606 		}
       
  1607 	else if (iHWState == ENameLookup)
       
  1608 		{
       
  1609 		
       
  1610 		iCurrentResults.ReturnToFirstResult();
       
  1611 		while(CBTInqResultRef *ref = iCurrentResults.NextResult())
       
  1612 			{
       
  1613 
       
  1614 			CBTInqResultRecord& rec = ref->Result();
       
  1615 			if(rec.IsNameRequestPending())
       
  1616 				{
       
  1617 				// This is a best effort service, the Connect will be tried even
       
  1618 				// if we fail to stop the Name request, so ignore errors.
       
  1619 				TRAP_IGNORE(CancelRemoteNameL(rec.LogEntry().iBdaddr));
       
  1620 				}
       
  1621 			}
       
  1622 
       
  1623 		}
       
  1624 		
       
  1625 	iFlusher->Cancel(); 	// Stop watchdog, start flusher.
       
  1626 	SetHWState(EConnecting);	// will stop inquirymanager doing anything else
       
  1627 	// don't publish status here, will be cleared up when manager tries to do soemthing else
       
  1628 	EnableFlusher();
       
  1629 	}
       
  1630 
       
  1631 void CBTInquiryMgr::Resume()
       
  1632 /**
       
  1633 	We can now carry on...
       
  1634 **/
       
  1635 	{
       
  1636 	LOG_FUNC
       
  1637 	if(iHWState == EConnecting)
       
  1638 		{
       
  1639 		LOG(_L("InquiryMgr: Hardware connected; resuming operations (when a new inquiry starts"));
       
  1640 	 	SetHWState(EIdle);	
       
  1641 	 	// don't publish status here, it will be set by namelookup
       
  1642 		LOG(_L("CBTInquiryMgr::Resume asking for another name lookup"));
       
  1643 		DoNameLookup(EFalse);
       
  1644 		DoInquiry();
       
  1645 		EnableFlusher(); // in case no operations started
       
  1646 		}
       
  1647 	}
       
  1648 
       
  1649 void CBTInquiryMgr::LookupName(CBTHostResolver& aResolver, const TBTDevAddr& aAddr, TBool aIgnoreCache, TBool aExplicitNameRequest)
       
  1650 /**
       
  1651 This method is called by a CBTHostResolver to look up the name of a device with a given address. If the
       
  1652 name is not immediately available a name lookup request is queued within the inquiry manager. This 
       
  1653 request will be actioned by CBTInquiryMgr::DoNameLookup(), and the remote device response will be 
       
  1654 sent (by CBTInquiryMgr::RemoteNameResult) to all current host resolvers.
       
  1655 **/
       
  1656 	{
       
  1657 	LOG_FUNC
       
  1658 	LOG1(_L("CBTHostResolver: 0x%8x"), &aResolver);
       
  1659 	LOG6(_L(", aAddr: %02x %02x %02x %02x %02x %02x"),
       
  1660  				  TUint8(aAddr[0]), TUint8(aAddr[1]), TUint8(aAddr[2]), TUint8(aAddr[3]), TUint8(aAddr[4]), 
       
  1661  				  TUint8(aAddr[5]));
       
  1662  				  
       
  1663 	CBTInqResultRef* ref = AddEntryToCache(aAddr); //N.B. Creates a new entry if one doesn't exist
       
  1664 
       
  1665 	if(!ref)
       
  1666 		{
       
  1667 		aResolver.NameLookupResult(KErrNoMemory, aAddr, KNullDesC8);
       
  1668 		return;
       
  1669 		}
       
  1670 
       
  1671 	// check state of cache entry
       
  1672 	CBTInqResultRecord& rec = ref->Result();
       
  1673 
       
  1674 	if(rec.HaveNameLookupResult() && rec.IsNameComplete() && (!aIgnoreCache|| rec.iFoundDuringCurrentInquiry))
       
  1675 		{// Either got a name, or we made an attempt that failed
       
  1676 		aResolver.NameLookupResult(rec.NameLookupResultCode(),
       
  1677 								   rec.LogEntry().iBdaddr,
       
  1678 								   rec.iName);
       
  1679 		return;
       
  1680 		}
       
  1681 	
       
  1682 	if (aExplicitNameRequest)
       
  1683 		{
       
  1684 		rec.SetExplicitNameRequest(ETrue);
       
  1685 		}
       
  1686 	
       
  1687 	if(rec.IsNameRequestPending())
       
  1688 		{
       
  1689 		return; // it's already happening
       
  1690 		}
       
  1691 
       
  1692 	rec.SetNamePending(ETrue);
       
  1693 	rec.iNameLookupAttempts = 0;
       
  1694 	++iPendingNameRequests;
       
  1695 	iNewPageRequestsPending = ETrue;
       
  1696 
       
  1697 	if(iHWState == EInquiry)
       
  1698 		{
       
  1699 		if(iPendingNameRequests > iInquiryInteruptions
       
  1700 		   || iInquiryInteruptions < KImmediateNameFetch)
       
  1701 			{
       
  1702 			TryToInterruptInquiryForNameLookup();
       
  1703 			}
       
  1704 		}
       
  1705 	else
       
  1706 		{
       
  1707 		LOG(_L("CBTInquiryMgr::LookupName asking for another name lookup"));
       
  1708 		DoNameLookup(EFalse);
       
  1709 		}
       
  1710 	}
       
  1711 
       
  1712 void CBTInquiryMgr::ClearCache()
       
  1713 	{
       
  1714 	LOG_FUNC
       
  1715 	if(iHWState == EInquiry)
       
  1716 		{
       
  1717 		TInt err = CancelHardwareInquiry();
       
  1718 		if(err==KErrNone)
       
  1719 			{
       
  1720 			// Don't clear cache if we couldn't cancel inquiry.
       
  1721 			// We'll be slightly unfaithful in the case of OOM...
       
  1722 			iCurrentResults.Reset();
       
  1723 			InquiryComplete(KErrNone, 0);
       
  1724 			}
       
  1725 		}
       
  1726 	else
       
  1727 		{
       
  1728 		iCurrentResults.Reset();
       
  1729 		}
       
  1730 	}
       
  1731 
       
  1732 TInt CBTInquiryMgr::SetLocalName(const TDesC8& aName)
       
  1733 	{
       
  1734 	LOG_FUNC
       
  1735 	return iLinkMgrProtocol.SetLocalDeviceName(aName);
       
  1736 	}
       
  1737 
       
  1738 TInt CBTInquiryMgr::GetLocalName()
       
  1739 	{
       
  1740 	LOG_FUNC
       
  1741 	TRAPD(err, ReadLocalNameL());
       
  1742 	return err;
       
  1743 	}
       
  1744 
       
  1745 /**
       
  1746 	This is called whenever the local HCI version is updated (usually only during startup), 
       
  1747 	so that the inquiry mode is set accordingly
       
  1748 **/
       
  1749 void CBTInquiryMgr::SetInquiryMode()
       
  1750 	{
       
  1751 	LOG_FUNC
       
  1752 	
       
  1753 	THCIInquiryMode inquiryMode = EStandardInquiryFormat;
       
  1754 	
       
  1755 	if (iLinkMgrProtocol.IsExtendedInquiryResponseSupportedLocally())
       
  1756 		{
       
  1757 		inquiryMode = EInquiryWithRssiOrEir;
       
  1758 		}
       
  1759 	else if (iLinkMgrProtocol.IsRssiWithInquiryResultsSupportedLocally())
       
  1760 		{
       
  1761 		inquiryMode = EInquiryWithRssi;
       
  1762 		}
       
  1763 	
       
  1764 	if (inquiryMode != EStandardInquiryFormat)
       
  1765 		{
       
  1766 		TRAPD(err, WriteInquiryModeL(inquiryMode));
       
  1767 		if (err == KErrNone)
       
  1768 			{
       
  1769 			iPendingInquiryMode = inquiryMode;
       
  1770 			}
       
  1771 		}
       
  1772 	}
       
  1773 /**
       
  1774 	This is called whenever the pending WriteInquiryMode command has completed. 
       
  1775 **/
       
  1776 void CBTInquiryMgr::WriteInquiryModeComplete(TBool aSucceeded)
       
  1777 	{
       
  1778 	LOG_FUNC
       
  1779 	if (aSucceeded)
       
  1780 		{
       
  1781 		iInquiryMode = iPendingInquiryMode;
       
  1782 		return;
       
  1783 		}
       
  1784 
       
  1785 	// should we maybe try to set another mode? Probably worth a try...
       
  1786 	// let's downgrade the inquiry mode
       
  1787 	if (iPendingInquiryMode == EInquiryWithRssiOrEir)
       
  1788 		{
       
  1789 		TRAPD(err, WriteInquiryModeL(EInquiryWithRssi));
       
  1790 		if (err == KErrNone)
       
  1791 			{
       
  1792 			iPendingInquiryMode = EInquiryWithRssi;
       
  1793 			}
       
  1794 		}
       
  1795 	}
       
  1796 
       
  1797 void CBTInquiryMgr::DoInquiry()
       
  1798 /**
       
  1799 	Try to start the inquiry.
       
  1800 	Only starts it if there isn't already one going.
       
  1801 **/
       
  1802 	{
       
  1803 	LOG_FUNC
       
  1804 
       
  1805 	if(iRequestedInquiryIAC == 0 || iHWState != EIdle || iHRs.IsEmpty())
       
  1806 		{
       
  1807 #ifdef _DEBUG
       
  1808 		LOG3(_L("Not starting inquiry. iRequestedInquiryIAC == %d, iHWState == %d, iHostResolverCount == %d"), iRequestedInquiryIAC, iHWState, iNumHRs);
       
  1809 		if (iHRs.IsEmpty())
       
  1810 			{
       
  1811 			LOG(_L("No HRs interested in results - Stopping discovery"));
       
  1812 			}
       
  1813 #endif
       
  1814 		if (iHWState == EIdle)
       
  1815 			{
       
  1816 			LOG(_L("CBTInquiryMgr::DoInquiry PublishStatus Idle"));	
       
  1817 			PublishStatus();// make sure the status says we're idle
       
  1818 			}
       
  1819 		return;
       
  1820 		}
       
  1821 
       
  1822 	// If pending on name lookup, we'll do it when that finishes
       
  1823 
       
  1824 	// Cache stale -- update it.
       
  1825 	TInt err = StartHardwareInquiry();
       
  1826 
       
  1827 	if (err == KErrNone)
       
  1828 		{
       
  1829 	 	SetHWState(EInquiry);
       
  1830 		LOG(_L("CBTInquiryMgr::DoInquiry PublishState Inquiry"));
       
  1831 		PublishStatus();
       
  1832 		// Use cache age to estimate time elapsed while inquiring.
       
  1833 		// Synchronise it with the inquiry
       
  1834 		// Stop flusher, Start inquiry wathcdog
       
  1835 		iFlusher->Cancel();
       
  1836 		TCallBack cb(InquiryWatchdog, this);
       
  1837 		iFlusher->Start(KInquiryWatchdogPeriod * 1000000,
       
  1838 						KInquiryWatchdogPeriod * 1000000,
       
  1839 						cb);
       
  1840 		SetCacheAge(iCurrentInquiryIAC, 0);
       
  1841 		iInquirySilenceCount = 0;
       
  1842 		iResultCount = 0;
       
  1843 		}
       
  1844 	else
       
  1845 		{
       
  1846 		// Couldn't start inquiry.
       
  1847 		// Make sure the request is completed.
       
  1848 		iRequestedInquiryIAC = 0;
       
  1849 		InquiryComplete(err, 0);
       
  1850 		LOG(_L("CBTInquiryMgr::DoInquiry PublishState Idle couldn't start inquiry"));
       
  1851 		PublishStatus();
       
  1852 		return;
       
  1853 		}
       
  1854 	}
       
  1855 
       
  1856 void CBTInquiryMgr::ClearCurrentInquiryResults()
       
  1857 	{
       
  1858 	LOG_FUNC
       
  1859 	iCurrentResults.ReturnToFirstResult();
       
  1860 	while (CBTInqResultRef* ref = iCurrentResults.NextResult())
       
  1861 		{
       
  1862 		ref->Result().iFoundDuringCurrentInquiry = EFalse;
       
  1863 		}	
       
  1864 	}
       
  1865 
       
  1866 TInt CBTInquiryMgr::CancelHardwareInquiry()
       
  1867 	{
       
  1868 	LOG_FUNC
       
  1869 	// CancelInquiryL will stop the current inquiry so clear any results that
       
  1870 	// were marked found during the inquiry
       
  1871 	ClearCurrentInquiryResults();
       
  1872 
       
  1873 	TRAPD(err, CancelInquiryL());
       
  1874 	return err;
       
  1875 	}
       
  1876 
       
  1877 TInt CBTInquiryMgr::StartHardwareInquiry()
       
  1878 	{
       
  1879 	LOG_FUNC
       
  1880 	iCurrentInquiryIAC = iRequestedInquiryIAC;
       
  1881 	// attempt to free up baseband space for best performance discovery
       
  1882 	iLinkMgrProtocol.PhysicalLinksMgr().RequireSlotSpace(); // will *eventually* put connections in hold - we dont wait though
       
  1883 	TRAPD(err, StartInquiryL(iCurrentInquiryIAC, KInquiryLength, KInquiryMaxResults));
       
  1884 
       
  1885 	return err;
       
  1886 	}
       
  1887 
       
  1888 
       
  1889 
       
  1890 
       
  1891 void CBTInquiryMgr::DoNameLookup(TBool aInquiryComplete)
       
  1892 /**
       
  1893 This method attempts to issue a name lookup to the HCI
       
  1894 **/
       
  1895 	{
       
  1896 	LOG_FUNC
       
  1897 
       
  1898 	if(iHWState != EIdle || iPendingNameRequests == 0 || iHRs.IsEmpty())
       
  1899 		{
       
  1900 #ifdef _DEBUG
       
  1901 		LOG3(_L("Not starting name lookup. iCurrentInquiryIAC == %d, iHWState == %d, iHostResolverCount == %d"), iCurrentInquiryIAC, iHWState, iNumHRs);
       
  1902 #endif
       
  1903 		/* if hw is idle and the inquiry is ready we are finished
       
  1904 		 and will not get another inquiry call so publish status idle
       
  1905 		 note that if doing 'inquiry with names'
       
  1906 		 in inquiry the aInquiryComplete flag stops state oscilating
       
  1907 		 thostres name request for all devices will still cause this to
       
  1908 		 oscilate because each name request is done individually, at this layer
       
  1909 		 we have no idea whether the test program will ask for another name */	
       
  1910 		if ((iHWState == EIdle) && (aInquiryComplete))
       
  1911 			{
       
  1912 			LOG(_L("CBTInquiryMgr::DoNameLookup inquiry finished with"));
       
  1913 			PublishStatus();
       
  1914 			}			
       
  1915 		// else publish status will be sorted by next inquiry 
       
  1916 		return;
       
  1917 		}
       
  1918 
       
  1919 	iCurrentResults.ReturnToFirstResult();
       
  1920 	CBTInqResultRef *refToGet = NULL;
       
  1921 	while(CBTInqResultRef *ref = iCurrentResults.NextResult())
       
  1922 		{
       
  1923 		CBTInqResultRecord& rec = ref->Result();
       
  1924 		if(rec.IsNameRequestPending())
       
  1925 			{
       
  1926 			if(!iRequestedInquiryIAC ||
       
  1927 			   rec.NameLookupAttempts() < KMaxNameLookupAttemptsDuringInquiry)
       
  1928 				{
       
  1929 				// We want the first record for the current IAC or a record for an explicit name request.
       
  1930 				// Failing that, we'll just have the first record
       
  1931 				if (rec.HasRespondedToIAC(iCurrentInquiryIAC) || rec.IsExplicitNameRequest())
       
  1932 					{
       
  1933 					refToGet = ref;
       
  1934 					break;
       
  1935 					}
       
  1936 				if (!refToGet)
       
  1937 					{
       
  1938 					refToGet = ref;
       
  1939 					}
       
  1940 				}
       
  1941 			}
       
  1942 		}
       
  1943 	if (refToGet)
       
  1944 		{
       
  1945 		CBTInqResultRecord& rec = refToGet->Result();
       
  1946 
       
  1947 		// First set the page timeout, it is a best effort attempt
       
  1948 		iNamePageTimeout = iLinkMgrProtocol.PhysicalLinksMgr().TryToChangePageTimeout(iNamePageTimeout);
       
  1949 
       
  1950 		// Request the name lookup.
       
  1951 		TRAPD(err, LookupNameL(rec.LogEntry()));
       
  1952 
       
  1953 		if (err == KErrNone)
       
  1954 			{
       
  1955 			SetHWState(ENameLookup);
       
  1956 			return;
       
  1957 			}
       
  1958 		else
       
  1959 			{
       
  1960 			// got a synchronous error - put in a blank name
       
  1961 			HandleRemoteNameResult(err, *refToGet, KNullDesC8());
       
  1962 			}
       
  1963 		}
       
  1964 	// Nothing new to do!
       
  1965 	iNewPageRequestsPending = EFalse;
       
  1966 	}
       
  1967 
       
  1968 void CBTInquiryMgr::TryToInterruptInquiryForNameLookup()
       
  1969 	{
       
  1970 	LOG_FUNC
       
  1971 	TInt err = CancelHardwareInquiry();
       
  1972 
       
  1973 	if(err == KErrNone)
       
  1974 		{// Start doing name lookups
       
  1975 		iFlusher->Cancel();	//Stop watchdog, start flusher
       
  1976 	 	SetHWState(EIdle);
       
  1977 		// don't publish status here, namelookup/inquiry will deal with it
       
  1978 		EnableFlusher();
       
  1979 		++iInquiryInteruptions;
       
  1980 		LOG(_L("CBTInquiryMgr::TryToInterruptInquiryForNameLookup asking for another name lookup"));
       
  1981 		DoNameLookup(EFalse);
       
  1982 		DoInquiry(); // <- In case name lookup fails
       
  1983 		}
       
  1984 	}
       
  1985 
       
  1986 // An inelegant workaround called from CLinkMgrProtocol::Error to get round
       
  1987 //  the fact that the stack doesn't (yet) keep track of commands that it has
       
  1988 //  been asked to do. If they aren't completed on a reset due to a
       
  1989 //  KErrHardwareNotFound error then the stack hangs as it waits for the responses.
       
  1990 void CBTInquiryMgr::CompleteCommands(TInt aErr)
       
  1991 	{
       
  1992 	LOG_FUNC
       
  1993 	SetLocalNameComplete(aErr);
       
  1994 	GetLocalNameComplete(aErr, _L8(""));
       
  1995 
       
  1996 	// Reset any inquiry results left over from a previous inquiry
       
  1997 	iCurrentResults.Reset();
       
  1998 	InquiryComplete(aErr, 0);
       
  1999 	}
       
  2000 
       
  2001 
       
  2002 // Check whether the controller supports Extended Inquiry Response by examing
       
  2003 // the supported features mask using Link Manage Protocol
       
  2004 TBool CBTInquiryMgr::IsExtendedInquiryResponseSupported()
       
  2005 	{
       
  2006 	LOG_FUNC
       
  2007 	return iLinkMgrProtocol.IsExtendedInquiryResponseSupportedLocally();
       
  2008 	}
       
  2009 
       
  2010 /******************************************************************************/
       
  2011 /*	If UPDATING THE CACHE, please use one of the "AddEntry..." methods below. */
       
  2012 /******************************************************************************/
       
  2013 CBTInqResultRef* CBTInquiryMgr::FindExistingCacheEntry(const TBTDevAddr& aAddr)
       
  2014 	{
       
  2015 	LOG_FUNC
       
  2016 	return(iCurrentResults.FindEntry(aAddr));
       
  2017 	}
       
  2018 
       
  2019 CBTInqResultRef* CBTInquiryMgr::AddEntryToCache(const TBTDevAddr& aAddr)
       
  2020 	{
       
  2021 	LOG_FUNC
       
  2022 	CBTInqResultRef* ref = FindExistingCacheEntry(aAddr);
       
  2023 	if(ref)
       
  2024 		{// Already in there!
       
  2025 		return ref;
       
  2026 		}
       
  2027 
       
  2028 	CBTInqResultRecord* rec = new CBTInqResultRecord(aAddr);
       
  2029 	if (!rec)
       
  2030 		{
       
  2031 		return 0;
       
  2032 		}
       
  2033 
       
  2034 	ref = iCurrentResults.Add(*rec);
       
  2035 	if (!ref)
       
  2036 		{
       
  2037 		delete rec;
       
  2038 		return 0;
       
  2039 		}
       
  2040 
       
  2041 	//default CBTInqResultRecord values - provided in CBTInqResultRecord constructer (unlike v1)
       
  2042 	//maybe overwritten later
       
  2043 
       
  2044 	EnableFlusher(); // Make sure we're aging entries.
       
  2045 	return ref;
       
  2046 	}
       
  2047 
       
  2048 CBTInqResultRef* CBTInquiryMgr::AddEntryWithJuiceToCache(const TInquiryLogEntry& aEntry)
       
  2049 /**
       
  2050 This method should be used if you are supplying cache with all valid
       
  2051 baseband parameters.
       
  2052 Setting the valid bit in clock offset allows us to tell btman that the clock
       
  2053 offset value, and by inferrence the other juice values are valid -
       
  2054 i.e. have been supplied by the HCI, as opposed to having been supplied
       
  2055 as default.
       
  2056 **/
       
  2057 	{
       
  2058 	LOG_FUNC
       
  2059 	CBTInqResultRef* ref = AddEntryToCache(aEntry.iBdaddr);
       
  2060 
       
  2061 	if (ref)
       
  2062 		{
       
  2063 		CBTInqResultRecord& rec = ref->Result();
       
  2064 		// Update all, and register that values come from HCI
       
  2065 		rec.iJuiceFromHCIMask |= EBluetoothJuice;
       
  2066 		// First fill in the base class members, common to all inquiry results
       
  2067 		*static_cast<TInquiryLogEntry*>(&rec.iEntry) = aEntry;
       
  2068 		// Now complete with extra data depending on the inquiry result type
       
  2069 		switch(aEntry.iSpare)
       
  2070 			{
       
  2071 		case KInqLogEntryStandard:
       
  2072 			break;
       
  2073 		case KInqLogEntryWithEir:
       
  2074 			{
       
  2075 			const TInquiryLogEntryWithEir& entryEir = static_cast<const TInquiryLogEntryWithEir &>(aEntry);
       
  2076 			// Only replace EIR if it contains something, since sometimes EIR transmission fails
       
  2077 			if(entryEir.iExtendedInquiryResponse.Length() != 0)
       
  2078 				{
       
  2079 				rec.iEntry.iExtendedInquiryResponse = entryEir.iExtendedInquiryResponse;
       
  2080 				}
       
  2081 			rec.iJuiceFromHCIMask |= EBluetoothEir;
       
  2082 			// Now check whether we can extract a complete or partial friendly name from the EIR and add it to the cache
       
  2083 			TPtrC8 name;
       
  2084 			TBool complete = ETrue;
       
  2085 			rec.Codec().Set(rec.iEntry.iExtendedInquiryResponse);
       
  2086 			// use EirCodec doing sanity check of the eir data
       
  2087 			TInt error = rec.Codec().DoSanityCheck(rec.iEntry.iExtendedInquiryResponse);
       
  2088 			if(error == KErrNone)
       
  2089 				{
       
  2090 				error = rec.Codec().GetDeviceName(name);
       
  2091 				if(error >= KErrNone)
       
  2092 					{
       
  2093 					if(error == EDataPartial)
       
  2094 						{
       
  2095 						complete = EFalse;
       
  2096 						}
       
  2097 					// Do not overwrite complete names with partial ones
       
  2098 					if(complete || !rec.IsNameValid() || (rec.IsNameValid() && !rec.IsNameComplete()))
       
  2099 						{
       
  2100 						rec.SetName(name);
       
  2101 						rec.SetNameComplete(complete);
       
  2102 						rec.iFlushes = 0;
       
  2103 						rec.SetNameValid(ETrue);
       
  2104 						rec.SetNameRefreshRequested(EFalse);
       
  2105 						}
       
  2106 					}
       
  2107 				}
       
  2108 			}
       
  2109 		// Fall through
       
  2110 		case KInqLogEntryWithRssi:
       
  2111 			{
       
  2112 			const TInquiryLogEntryWithRssi& entryRssi = static_cast<const TInquiryLogEntryWithRssi &>(aEntry);
       
  2113 			rec.iEntry.iRssi = entryRssi.iRssi;
       
  2114 			rec.iJuiceFromHCIMask |= EBluetoothRssi;
       
  2115 			break;
       
  2116 			}
       
  2117 		default:
       
  2118 			__ASSERT_DEBUG(EFalse, Panic(EBTInvalidInquiryLogEntry));
       
  2119 			break;
       
  2120 			}
       
  2121 		// Mark as valid, HCI does not (necessarily) do this for you
       
  2122 		rec.iEntry.iClockOffset |= KHCIClockOffsetValidBit;
       
  2123 		}
       
  2124 
       
  2125 	return ref;
       
  2126 	}
       
  2127 
       
  2128 CBTInqResultRef* CBTInquiryMgr::AddEntryWithCoDToCache(const TBTDevAddr& aAddr, const TUint aCoD)
       
  2129 	{
       
  2130 	LOG_FUNC
       
  2131 	CBTInqResultRef* ref = AddEntryToCache(aAddr);
       
  2132 
       
  2133 	if (ref)
       
  2134 		{
       
  2135 		// Update all, and register that values come from HCI
       
  2136 		ref->Result().iJuiceFromHCIMask |= EBluetoothCoD;
       
  2137 		ref->Result().iEntry.iCoD = aCoD;
       
  2138 		}
       
  2139 
       
  2140 	return ref;
       
  2141 	}
       
  2142 
       
  2143 CBTInqResultRef* CBTInquiryMgr::AddEntryWithClockOffsetToCache(const TBTDevAddr& aAddr, const TBasebandTime aClockOffset)
       
  2144 	{
       
  2145 	LOG_FUNC
       
  2146 	CBTInqResultRef* ref = AddEntryToCache(aAddr);
       
  2147 
       
  2148 	if (ref)
       
  2149 		{
       
  2150 		//update the clock offset - useful for subsequent connections
       
  2151 		// mark as valid
       
  2152 		ref->Result().iJuiceFromHCIMask |= EBluetoothClockOffSet;
       
  2153 		ref->Result().LogEntry().iClockOffset = static_cast<TUint16>(aClockOffset | KHCIClockOffsetValidBit);
       
  2154 		}
       
  2155 
       
  2156 	return ref;
       
  2157 	}
       
  2158 
       
  2159 
       
  2160 TInt CBTInquiryMgr::InquiryWatchdog(TAny* aPtr)
       
  2161 /*
       
  2162 Called second while doing enquiry.
       
  2163 Considers whether to give up enquiry
       
  2164 */
       
  2165 	{
       
  2166 	LOG_STATIC_FUNC
       
  2167 	CBTInquiryMgr& self = *static_cast<CBTInquiryMgr*>(aPtr);
       
  2168 	__ASSERT_DEBUG(self.iHWState == EInquiry, Panic(EHostResolverBadHWState));
       
  2169 	if(self.iResultCount == 0)
       
  2170 		{
       
  2171 		++self.iInquirySilenceCount;
       
  2172 		}
       
  2173 
       
  2174 	if(self.iNewPageRequestsPending
       
  2175 	   && (self.iInquirySilenceCount * KInquiryWatchdogPeriod) > self.iInquiryInteruptions)
       
  2176 		{// Silence, and names are waiting. Defer the inquiry
       
  2177 		self.TryToInterruptInquiryForNameLookup();
       
  2178 		}
       
  2179 
       
  2180 	self.iResultCount = 0;
       
  2181 	return 0;
       
  2182 	}
       
  2183 
       
  2184 TInt CBTInquiryMgr::Flush(TAny* aPtr)
       
  2185 	{
       
  2186 	LOG_STATIC_FUNC
       
  2187 	CBTInquiryMgr& self = *static_cast<CBTInquiryMgr*>(aPtr);
       
  2188 	__ASSERT_DEBUG(self.iHWState != EInquiry, Panic(EHostResolverBadHWState));
       
  2189 	self.DoFlush();
       
  2190 	return 0;
       
  2191 	}
       
  2192 
       
  2193 void CBTInquiryMgr::DoFlush()
       
  2194 	{
       
  2195 	LOG_FUNC
       
  2196 	for (TInt i = 0; i < iCacheAge.Count(); i++)
       
  2197 		{
       
  2198 		++iCacheAge[i].iCacheAge;
       
  2199 		}
       
  2200 	iCurrentResults.ReturnToFirstResult();	
       
  2201 
       
  2202 	while (CBTInqResultRef* ref = iCurrentResults.NextResult())
       
  2203 		{
       
  2204 		CBTInqResultRecord& rec = ref->Result();
       
  2205 		TInt age = rec.IncFlushes();
       
  2206 		if(age >= KRecordStaleAge && rec.NumberOfIACsRespondedTo() > 0)
       
  2207 			{
       
  2208 			// device is around, but not seen for a while
       
  2209 			rec.ClearIACs();
       
  2210 			LOG(_L("CBTInquiryMgr::DoFlush - ClearIACs"));
       
  2211 			}
       
  2212 			
       
  2213 		if(age >= KRecordDeathAge)
       
  2214 			{
       
  2215 			rec.SetNameValid(EFalse);
       
  2216 			LOG(_L("CBTInquiryMgr::DoFlush - age >= KRecordDeathAge setting name valid False"));
       
  2217 			}
       
  2218 			
       
  2219 		if(age >= KRecordDeathAge && rec.NumberOfIACsRespondedTo() == 0 && !rec.IsNameValid() 
       
  2220 			&& (!rec.IsNameRequestPending() || iHRs.IsEmpty())) //Don't flush old record if name pending and HRs present
       
  2221 			{// Record is dead. Delete it
       
  2222 			LOG(_L("CBTInquiryMgr::DoFlush - Deleting reference"));
       
  2223 			delete ref;
       
  2224 			}
       
  2225 		else if(rec.IsNameRefreshRequested() && iHWState == EIdle)
       
  2226 			{// Try to get this name now, perhaps?
       
  2227 			LOG(_L("CBTInquiryMgr::DoFlush - Try to get name straight away"));
       
  2228 			rec.SetNameRefreshRequested(EFalse);
       
  2229 			rec.SetNamePending(ETrue);
       
  2230 			rec.iNameLookupAttempts = 0;
       
  2231 			++iPendingNameRequests;
       
  2232 			LOG(_L("CBTInquiryMgr::DoFlush asking for another name lookup"));
       
  2233 			DoNameLookup(EFalse);
       
  2234 			}
       
  2235 		}
       
  2236 	if (iCurrentResults.IsEmpty())
       
  2237 		{
       
  2238 		iNewPageRequestsPending = EFalse;
       
  2239 		iPendingNameRequests = 0;
       
  2240 		iFlusher->Cancel();
       
  2241 		}
       
  2242 	}
       
  2243 
       
  2244 void CBTInquiryMgr::EnableFlusher()
       
  2245 	{
       
  2246 	LOG_FUNC
       
  2247 	if (iFlusher->IsActive() || iHWState == EInquiry)
       
  2248 		return;
       
  2249 	static const TInt usec2sec = 1000000;
       
  2250 	TCallBack cb(Flush, this);
       
  2251 	iFlusher->Start(usec2sec / 4, // 1/4 sec for initial flush
       
  2252 					KFlushTimeoutSecs * usec2sec,
       
  2253 					cb);
       
  2254 	}
       
  2255 
       
  2256 TInt CBTInquiryMgr::CacheAge(TUint aIAC) const
       
  2257 	{
       
  2258 	TInt ret = KMaxTInt; // If we haven't set a cache age for this IAC, return KMaxTInt
       
  2259 	for (TUint i = 0; i < iCacheAge.Count(); i++)
       
  2260 		{
       
  2261 		if (iCacheAge[i].iIAC == aIAC)
       
  2262 			{
       
  2263 			ret = iCacheAge[i].iCacheAge;
       
  2264 			break;
       
  2265 			}
       
  2266 		}
       
  2267 	return ret;
       
  2268 	}
       
  2269 
       
  2270 void CBTInquiryMgr::SetCacheAge(TUint aIAC, TInt aAge)
       
  2271 	{
       
  2272 	TBool found = EFalse;
       
  2273 	for (TUint i = 0; i < iCacheAge.Count(); i++)
       
  2274 		{
       
  2275 		if (iCacheAge[i].iIAC == aIAC)
       
  2276 			{
       
  2277 			iCacheAge[i].iCacheAge = aAge;
       
  2278 			found = ETrue;
       
  2279 			break;
       
  2280 			}
       
  2281 		}
       
  2282 	if (!found)
       
  2283 		{
       
  2284 		TInquiryCacheAge ageInfo;
       
  2285 		ageInfo.iIAC = aIAC;
       
  2286 		ageInfo.iCacheAge = aAge;
       
  2287 		iCacheAge.Append(ageInfo);
       
  2288 		// If we can't append, there's not a lot we can do - we'll just have
       
  2289 		// to return KMaxTInt when someone asks for the age
       
  2290 		}
       
  2291 	}
       
  2292 
       
  2293 
       
  2294 // -----------------------------------------------------------------------------------------
       
  2295 
       
  2296 void CBTInquiryMgr::StartInquiryL(TUint aIAC, TUint8 aLength, TUint8 aNumResponses)
       
  2297 	{
       
  2298 	LOG_FUNC
       
  2299 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  2300 	CInquiryCommand* cmd = CInquiryCommand::NewL(aIAC, aLength, aNumResponses);
       
  2301 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2302 	}
       
  2303 
       
  2304 void CBTInquiryMgr::CancelInquiryL()
       
  2305 	{
       
  2306 	LOG_FUNC
       
  2307 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  2308 	CInquiryCancelCommand* cmd = CInquiryCancelCommand::NewL();
       
  2309 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2310 	}
       
  2311 
       
  2312 void CBTInquiryMgr::CancelRemoteNameL(const TBTDevAddr& aAddr)
       
  2313 	{
       
  2314 	LOG_FUNC
       
  2315 	CRemoteNameRequestCancelCommand* cmd = CRemoteNameRequestCancelCommand::NewL(aAddr);
       
  2316 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2317 	}
       
  2318 
       
  2319 void CBTInquiryMgr::WriteInquiryModeL(TUint8 aInquiryMode)
       
  2320 	{
       
  2321 	LOG_FUNC
       
  2322 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  2323 	CWriteInquiryModeCommand* cmd = CWriteInquiryModeCommand::NewL(aInquiryMode);
       
  2324 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2325 	}
       
  2326 
       
  2327 /**
       
  2328 This function should be used by the inquiry manager to retrieve remote names.
       
  2329 */
       
  2330 void CBTInquiryMgr::LookupNameL(const TInquiryLogEntry& aEntry)
       
  2331 	{
       
  2332 	LOG_FUNC
       
  2333 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  2334 	CRemoteNameRequestCommand* cmd = CRemoteNameRequestCommand::NewL(aEntry.iBdaddr, aEntry.iPageScanRepetitionMode, aEntry.iPageScanMode, aEntry.iClockOffset);
       
  2335 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2336 	}
       
  2337 
       
  2338 /**
       
  2339 This function should only be used when there is an established physical link (and therefore from
       
  2340 CPhysicalLink only) to retrieve a remote name.
       
  2341 */
       
  2342 void CBTInquiryMgr::ReadRemoteNameL(const TBTDevAddr& aAddr)
       
  2343 	{
       
  2344 	LOG_FUNC
       
  2345 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  2346 	CRemoteNameRequestCommand* cmd = CRemoteNameRequestCommand::NewL(aAddr, 0, 0, 0);
       
  2347 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2348 	}
       
  2349 
       
  2350 void CBTInquiryMgr::ReadLocalNameL()
       
  2351 	{
       
  2352 	LOG_FUNC
       
  2353 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  2354 	CReadLocalNameCommand* cmd = CReadLocalNameCommand::NewL();
       
  2355 	CommandQueue().MhcqAddCommandL(cmd, *this);
       
  2356 	}
       
  2357 
       
  2358 void CBTInquiryMgr::MhcqcCommandErrored(TInt aErrorCode, const CHCICommandBase* aCommand)
       
  2359 	{
       
  2360 	LOG_FUNC
       
  2361 	__ASSERT_DEBUG(aCommand, Panic(EBTInquiryMgrUnmatchedEvent));
       
  2362 	LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode());
       
  2363 	
       
  2364 	if (aCommand->Opcode() == KInquiryOpcode)
       
  2365 		{
       
  2366 		// Clear any pending stuff
       
  2367 		CompleteCommands(aErrorCode);
       
  2368 		// this will also set the state to Idle
       
  2369 		}
       
  2370 	else if (aCommand->Opcode() == KWriteInquiryModeOpcode)
       
  2371 		{
       
  2372 		// command had error before response -- assume not supported
       
  2373 		WriteInquiryModeComplete(EFalse);
       
  2374 		}
       
  2375 	else if (aCommand->Opcode() == KRemoteNameRequestOpcode)
       
  2376 		{
       
  2377 		// command had error before response -- doctor a fake response and process it to restore sanity
       
  2378 		TBuf8<256> fakeEventBuffer;
       
  2379 		const TBTDevAddr remNameReqAddr = static_cast<const CRemoteNameRequestCommand*>(aCommand)->BDADDR();
       
  2380 		TRemoteNameReqCompleteEvent fakeRemoteNameRequestCompleteEvent(EOK, remNameReqAddr, _L8(""), fakeEventBuffer);
       
  2381 		RemoteNameReqCompleteEvent(fakeRemoteNameRequestCompleteEvent);
       
  2382 		// we will not change the state so a running inquiry can complete
       
  2383 		}
       
  2384 	else if (aCommand->Opcode() == KReadLocalNameOpcode)
       
  2385 		{
       
  2386 		// command had error before response -- doctor a fake response and process it to restore sanity
       
  2387 		TBuf8<256> fakeEventBuffer;
       
  2388 		TReadLocalNameCompleteEvent fakeLocalNameCompleteEvent(EUnspecifiedError, 0, _L8(""), fakeEventBuffer);
       
  2389 		ReadLocalNameOpcode(EUnspecifiedError, fakeLocalNameCompleteEvent);
       
  2390 		// this will also set the state to Idle
       
  2391 		}
       
  2392 	
       
  2393 	}
       
  2394 
       
  2395 // From MHCICommandQueueClient
       
  2396 void CBTInquiryMgr::MhcqcCommandEventReceived(const THCIEventBase& aEvent,
       
  2397 											const CHCICommandBase* aRelatedCommand)
       
  2398 	{
       
  2399 	LOG_FUNC
       
  2400 	__ASSERT_DEBUG(aRelatedCommand, Panic(EBTInquiryMgrUnmatchedEvent));
       
  2401 	static_cast<void>(aRelatedCommand);
       
  2402 	switch(aEvent.EventCode())
       
  2403 		{
       
  2404 	case ERemoteNameReqCompleteEvent:
       
  2405 		RemoteNameReqCompleteEvent(aEvent);
       
  2406 		break;
       
  2407 
       
  2408 	case ERemoteHostSupportedFeaturesNotificationEvent:
       
  2409 		RemoteHostSupportedFeaturesNotificationEvent(aEvent);
       
  2410 		break;
       
  2411 
       
  2412 	case EInquiryCompleteEvent:
       
  2413 		InquiryCompleteEvent(aEvent);
       
  2414 		break;
       
  2415 
       
  2416 	case EInquiryResultEvent:
       
  2417 		InquiryResultEvent(aEvent);
       
  2418 		break;
       
  2419 
       
  2420 	case EInquiryResultwithRSSIEvent:
       
  2421 		InquiryResultWithRSSIEvent(aEvent);
       
  2422 		break;
       
  2423 
       
  2424 	case EExtendedInquiryResultEvent:
       
  2425 		ExtendedInquiryResultEvent(aEvent);
       
  2426 		break;
       
  2427 
       
  2428 	case ECommandCompleteEvent:
       
  2429 		CommandCompleteEvent(aEvent);
       
  2430 		break;
       
  2431 
       
  2432 	case ECommandStatusEvent:
       
  2433 		CommandStatusEvent(aEvent, *aRelatedCommand);
       
  2434 		break;
       
  2435 
       
  2436 	default:
       
  2437 		LOG1(_L("Warning!! Unknown Command Event Received (event code:%d)"), aEvent.EventCode());
       
  2438 		__ASSERT_DEBUG(EFalse, Panic(EHCIUnknownCommandEvent));
       
  2439 		break;
       
  2440 		}
       
  2441 	}
       
  2442 
       
  2443 void CBTInquiryMgr::CommandCompleteEvent(const THCIEventBase& aEvent)
       
  2444 	{
       
  2445 	LOG_FUNC
       
  2446 	const THCICommandCompleteEvent& completeEvent = THCICommandCompleteEvent::Cast(aEvent);
       
  2447 	THCIOpcode opcode = completeEvent.CommandOpcode();
       
  2448 	THCIErrorCode hciErr = aEvent.ErrorCode();
       
  2449 
       
  2450 	switch (opcode)
       
  2451 		{
       
  2452 	case KWriteInquiryModeOpcode:
       
  2453 		WriteInquiryModeOpcode(hciErr, aEvent);
       
  2454 		break;
       
  2455 
       
  2456 	case KReadLocalNameOpcode:
       
  2457 		ReadLocalNameOpcode(hciErr, aEvent);
       
  2458 		break;
       
  2459 
       
  2460 	case KInquiryCancelOpcode:
       
  2461 		InquiryCancelOpcode(hciErr, aEvent);
       
  2462 		break;
       
  2463 
       
  2464 	// These commands are expected to not be handled and so can be safely ignored.
       
  2465 	case KRemoteNameRequestCancelOpcode:
       
  2466 		LOG1(_L("ignored Command Complete event (opcode: 0x%04x)"), opcode);
       
  2467 		break;
       
  2468 
       
  2469 	// The commands below would most likely be used by the inquiry manager, however
       
  2470 	// they currently are not used.
       
  2471 	case KPeriodicInquiryModeOpcode:
       
  2472 	case KExitPeriodicInquiryModeOpcode:
       
  2473 	case KReadInquiryScanActivityOpcode:
       
  2474 	case KWriteInquiryScanActivityOpcode:
       
  2475 	case KReadInquiryScanTypeOpcode:
       
  2476 	case KWriteInquiryScanTypeOpcode:
       
  2477 	case KReadInquiryModeOpcode:
       
  2478 		LOG1(_L("Warning!! Unhandled Command Complete Event (opcode:%d)"), opcode);
       
  2479 		break;
       
  2480 
       
  2481 	default:
       
  2482 		LOG2(_L("Error!! Unknown Command complete event! Opcode %d error code %d"), opcode, hciErr);
       
  2483 		__ASSERT_DEBUG(EFalse, Panic(EHCIUnknownCommandCompleteOpcode));
       
  2484 		break;
       
  2485 		}
       
  2486 	}
       
  2487 
       
  2488 void CBTInquiryMgr::CommandStatusEvent(const THCIEventBase& aEvent, const CHCICommandBase& aCommand)
       
  2489 	{
       
  2490 	LOG_FUNC
       
  2491 
       
  2492 	const TCommandStatusEvent& commandStatusEvent = TCommandStatusEvent::Cast(aEvent);
       
  2493 	THCIOpcode opcode = commandStatusEvent.CommandOpcode();
       
  2494 	THCIErrorCode hciErr = commandStatusEvent.ErrorCode();
       
  2495 
       
  2496 	__ASSERT_DEBUG(aCommand.Opcode() == opcode, Panic(EBTInquiryMgrMismatchedStatusEvent));
       
  2497 
       
  2498 	if (hciErr != EOK)
       
  2499 		{
       
  2500 		// got an error
       
  2501 		// map onto the event that would have occurred: some things we will have to let the client work out
       
  2502 		// e.g. they should check error and connection handle etc.
       
  2503 		switch (opcode)
       
  2504 			{
       
  2505 		case KInquiryOpcode:
       
  2506 			InquiryComplete(CHciUtil::SymbianErrorCode(hciErr), 0);
       
  2507 			break;
       
  2508 
       
  2509 		case KRemoteNameRequestOpcode:
       
  2510 				{
       
  2511 				const CRemoteNameRequestCommand& remNameReq = static_cast<const CRemoteNameRequestCommand&>(aCommand);
       
  2512 				TInt err = CHciUtil::SymbianErrorCode(hciErr);
       
  2513 				TBTDevAddr addr = remNameReq.BDADDR();
       
  2514 				TBTDeviceName8 nullDevName(KNullDesC8);
       
  2515 
       
  2516 				RemoteNameResult(err, addr, nullDevName);
       
  2517 				iLinkMgrProtocol.PhysicalLinksMgr().RemoteName(hciErr, addr, nullDevName);
       
  2518 				}
       
  2519 			break;
       
  2520 
       
  2521 		default:
       
  2522 			// Complete any other commands with an error
       
  2523 			CommandCompleteEvent(aEvent);
       
  2524 			break;
       
  2525 			}
       
  2526 		}
       
  2527 	}
       
  2528 
       
  2529 void CBTInquiryMgr::WriteInquiryModeOpcode(THCIErrorCode aHciErr, const THCIEventBase& /*aEvent*/)
       
  2530 	{
       
  2531 	LOG_FUNC
       
  2532 	WriteInquiryModeComplete(aHciErr == EOK);
       
  2533 	}
       
  2534 
       
  2535 void CBTInquiryMgr::ReadLocalNameOpcode(THCIErrorCode aHciErr, const THCIEventBase& aEvent)
       
  2536 	{
       
  2537 	LOG_FUNC
       
  2538 	if (aHciErr == EOK)
       
  2539 		{
       
  2540 		const TReadLocalNameCompleteEvent& readLocalNameCompleteEvent = TReadLocalNameCompleteEvent::Cast(aEvent);
       
  2541 		TPtrC8 localName = readLocalNameCompleteEvent.LocalName();
       
  2542 		
       
  2543 		GetLocalNameComplete(CHciUtil::SymbianErrorCode(aHciErr), localName);
       
  2544 		iLinkMgrProtocol.UpdateLocalDeviceName(localName);
       
  2545 		}
       
  2546 	else
       
  2547 		{
       
  2548 		_LIT8(KNoName, "");
       
  2549 		GetLocalNameComplete(CHciUtil::SymbianErrorCode(aHciErr), KNoName());
       
  2550 		}
       
  2551 	}
       
  2552 
       
  2553 void CBTInquiryMgr::InquiryCancelOpcode(THCIErrorCode aHciErr, const THCIEventBase& /* aEvent */)
       
  2554 	{
       
  2555 	LOG_FUNC
       
  2556 	if (aHciErr == EOK)
       
  2557 		{
       
  2558 		if (iHWState == ECancellingForNewIAC)
       
  2559 			{
       
  2560 			SetHWState(EIdle);
       
  2561 			DoInquiry();
       
  2562 			}
       
  2563 		}
       
  2564 	// If an error comes in, it may be because the inquiry complete came in first. In that case, everything
       
  2565 	// will be handled by the Inquiry complete logic
       
  2566 	}
       
  2567 
       
  2568 // ----------------------------------------------------------------------------
       
  2569 // Event processing functions
       
  2570 // ----------------------------------------------------------------------------
       
  2571 
       
  2572 void CBTInquiryMgr::InquiryCompleteEvent(const THCIEventBase& aEvent)
       
  2573 	{
       
  2574 	LOG_FUNC
       
  2575 	InquiryComplete(CHciUtil::SymbianErrorCode(aEvent.ErrorCode()), 0);
       
  2576 	}
       
  2577 
       
  2578 void CBTInquiryMgr::InquiryResultEvent(const THCIEventBase& aEvent)
       
  2579 	{
       
  2580 	LOG_FUNC
       
  2581 	
       
  2582 	const TInquiryResultEvent& inquiryResultEvent = TInquiryResultEvent::Cast(aEvent);
       
  2583 	TInquiryLogEntry entry;
       
  2584 	TUint responses = inquiryResultEvent.NumResponses();
       
  2585 	
       
  2586 	for (TUint index = 0; index < responses; index++)
       
  2587 		{
       
  2588 		entry.iSpare = KInqLogEntryStandard;
       
  2589 		entry.iPageScanRepetitionMode = inquiryResultEvent.PageScanRepetitionMode(index);
       
  2590 		entry.iPageScanPeriodMode = inquiryResultEvent.Reserved1(index); // v1.1 spec, no meaning in v1.2
       
  2591 		entry.iPageScanMode = inquiryResultEvent.Reserved2(index); // v1.1 spec, no meaning in v1.2
       
  2592 		entry.iClockOffset = inquiryResultEvent.ClockOffset(index);
       
  2593 		entry.iBdaddr = inquiryResultEvent.BDADDR(index);
       
  2594 		entry.iCoD = inquiryResultEvent.ClassOfDevice(index);
       
  2595 		InquiryResult(CHciUtil::SymbianErrorCode(aEvent.ErrorCode()), entry);
       
  2596 		}
       
  2597 	}
       
  2598 
       
  2599 void CBTInquiryMgr::InquiryResultWithRSSIEvent(const THCIEventBase& aEvent)
       
  2600 	{
       
  2601 	LOG_FUNC
       
  2602 	
       
  2603 	const TInquiryResultwithRSSIEvent& inquiryResultwithRSSIEvent = TInquiryResultwithRSSIEvent::Cast(aEvent);
       
  2604 	TInquiryLogEntryWithRssi entry;
       
  2605 	TUint responses = inquiryResultwithRSSIEvent.NumResponses();
       
  2606 	
       
  2607 	for (TUint index = 0; index < responses; index++)
       
  2608 		{
       
  2609 		entry.iSpare = KInqLogEntryWithRssi;
       
  2610 		entry.iPageScanRepetitionMode = inquiryResultwithRSSIEvent.PageScanRepetitionMode(index);
       
  2611 		entry.iPageScanPeriodMode = 0x00;
       
  2612 		entry.iPageScanMode = 0x00;
       
  2613 		entry.iClockOffset = inquiryResultwithRSSIEvent.ClockOffset(index);
       
  2614 		entry.iBdaddr = inquiryResultwithRSSIEvent.BDADDR(index);
       
  2615 		entry.iCoD = inquiryResultwithRSSIEvent.ClassOfDevice(index);
       
  2616 		entry.iRssi = inquiryResultwithRSSIEvent.RSSI(index);
       
  2617 		InquiryResult(CHciUtil::SymbianErrorCode(aEvent.ErrorCode()), entry);
       
  2618 		}
       
  2619 	}
       
  2620 
       
  2621 void CBTInquiryMgr::ExtendedInquiryResultEvent(const THCIEventBase& aEvent)
       
  2622 	{
       
  2623 	LOG_FUNC
       
  2624 	
       
  2625 	const TExtendedInquiryResultEvent& extendedInquiryResultEvent = TExtendedInquiryResultEvent::Cast(aEvent);
       
  2626 	TInquiryLogEntryWithEir entry;
       
  2627 	
       
  2628 	entry.iSpare = KInqLogEntryWithEir;
       
  2629 	entry.iPageScanRepetitionMode = extendedInquiryResultEvent.PageScanRepetitionMode();
       
  2630 	entry.iPageScanPeriodMode = 0x00;
       
  2631 	entry.iPageScanMode = 0x00;
       
  2632 	entry.iClockOffset = extendedInquiryResultEvent.ClockOffset();
       
  2633 	entry.iBdaddr = extendedInquiryResultEvent.BDADDR();
       
  2634 	entry.iCoD = extendedInquiryResultEvent.ClassOfDevice();
       
  2635 	entry.iRssi = extendedInquiryResultEvent.RSSI();
       
  2636 	entry.iExtendedInquiryResponse = extendedInquiryResultEvent.ExtendedInquiryResponse();
       
  2637 	InquiryResult(CHciUtil::SymbianErrorCode(aEvent.ErrorCode()), entry);
       
  2638 	}
       
  2639 
       
  2640 void CBTInquiryMgr::RemoteNameReqCompleteEvent(const THCIEventBase& aEvent)
       
  2641 	{
       
  2642 	LOG_FUNC
       
  2643 	const TRemoteNameReqCompleteEvent& remNameReqCompleteEvent = TRemoteNameReqCompleteEvent::Cast(aEvent);
       
  2644 	THCIErrorCode err = aEvent.ErrorCode();
       
  2645 	const TBTDevAddr addr = remNameReqCompleteEvent.BDADDR();
       
  2646 	TPtrC8 buf = remNameReqCompleteEvent.RemoteName();
       
  2647 	
       
  2648 	//shorten the name to the proper length so that we don't waste memory
       
  2649 	TInt nullTerminator = buf.Locate(0);
       
  2650 	if (nullTerminator == KErrNotFound)
       
  2651 		{
       
  2652 		nullTerminator = buf.Length();
       
  2653 		}
       
  2654 	TPtrC8 remoteName = buf.Left(nullTerminator);
       
  2655 	
       
  2656 	// name requests have two customers...
       
  2657 	// inquiry manager
       
  2658 	RemoteNameResult(CHciUtil::SymbianErrorCode(err), addr, remoteName);
       
  2659 	// phy manager
       
  2660 	iLinkMgrProtocol.PhysicalLinksMgr().RemoteName(err, addr, remoteName);
       
  2661 	}
       
  2662 
       
  2663 void CBTInquiryMgr::RemoteHostSupportedFeaturesNotificationEvent(const THCIEventBase& aEvent)
       
  2664 	{
       
  2665 	LOG_FUNC
       
  2666 	const TRemoteHostSupportedFeaturesNotificationEvent& remHostSupFeatEvent = TRemoteHostSupportedFeaturesNotificationEvent::Cast(aEvent);
       
  2667 	THCIErrorCode err = remHostSupFeatEvent.ErrorCode();
       
  2668 	TBTDevAddr addr = remHostSupFeatEvent.BDADDR();
       
  2669 	TUint64 hostSupFeats = remHostSupFeatEvent.HostSupportedFeatures();
       
  2670 
       
  2671 	RemoteHostSupportedFeatures(CHciUtil::SymbianErrorCode(err), addr, hostSupFeats);
       
  2672 	}
       
  2673 
       
  2674 
       
  2675 #ifdef CONNECTION_PREEMPTS_INQUIRY
       
  2676 // *******************************************************************
       
  2677 // ACL Connecting status subscriber
       
  2678 // *******************************************************************
       
  2679 /*static*/ CConnectingStatusSubscriber* CConnectingStatusSubscriber::NewL(CBTInquiryMgr& aInquiryMgr)
       
  2680 	{
       
  2681 	LOG_STATIC_FUNC
       
  2682 	CConnectingStatusSubscriber* self = new(ELeave) CConnectingStatusSubscriber(aInquiryMgr);
       
  2683 	CleanupStack::PushL(self);
       
  2684 	self->ConstructL();
       
  2685 	CleanupStack::Pop();
       
  2686 	return self;
       
  2687 	}
       
  2688 
       
  2689 CConnectingStatusSubscriber::CConnectingStatusSubscriber(CBTInquiryMgr& aInquiryMgr)
       
  2690 : CActive(CActive::EPriorityStandard), iParent(aInquiryMgr)
       
  2691 	{
       
  2692 	LOG_FUNC
       
  2693 	CActiveScheduler::Add(this);
       
  2694 	}
       
  2695 
       
  2696 CConnectingStatusSubscriber::~CConnectingStatusSubscriber()
       
  2697 	{
       
  2698 	LOG_FUNC
       
  2699 	Cancel();
       
  2700 	iProperty.Close();
       
  2701 	}
       
  2702 
       
  2703 void CConnectingStatusSubscriber::DoCancel()
       
  2704 	{
       
  2705 	LOG_FUNC
       
  2706 	iProperty.Cancel();
       
  2707 	}
       
  2708 
       
  2709 void CConnectingStatusSubscriber::ConstructL()
       
  2710 	{
       
  2711 	LOG_FUNC
       
  2712 	User::LeaveIfError(iProperty.Attach(KPropertyUidBluetoothCategory,
       
  2713 										KPropertyKeyBluetoothGetConnectingStatus));
       
  2714 	Subscribe();
       
  2715 	}
       
  2716 
       
  2717 void CConnectingStatusSubscriber::Subscribe()
       
  2718 	{
       
  2719 	LOG_FUNC
       
  2720 	iProperty.Subscribe(iStatus);
       
  2721 	SetActive();
       
  2722 	}
       
  2723 
       
  2724 /**
       
  2725 This is looking for the connection to complete.  The inquiry must be
       
  2726 synchronously cancelled before the CreateConnection command is issued,
       
  2727 but we can resume it when we get round to it.
       
  2728 */
       
  2729 void CConnectingStatusSubscriber::RunL()
       
  2730 	{
       
  2731 	LOG_FUNC
       
  2732 	// Subscribe to the next change of state.
       
  2733 	Subscribe();
       
  2734 
       
  2735 	TInt isConnecting;
       
  2736 	// If this device is currently connecting an ACL suspend the
       
  2737 	// inquiry.
       
  2738 	iProperty.Get(isConnecting);
       
  2739 	
       
  2740 	if(!isConnecting)
       
  2741 		{
       
  2742 		iParent.Resume();
       
  2743 		}
       
  2744 	}
       
  2745 #endif	// CONNECTION_PREEMPTS_INQUIRY