commands/btservices/BtServicesEng.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // BtServicesEng.cpp
       
     2 // 
       
     3 // Copyright (c) 2003 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 //#include <qbtselectdlg.h>
       
    14 
       
    15 #include <e32debug.h>
       
    16 
       
    17 #include <utf.h>
       
    18 #include "BtData.h"
       
    19 #include "btserviceseng.h"
       
    20 #include <btmanclient.h>
       
    21 //#include <MQikListBoxData.h>
       
    22 
       
    23 const TInt KArrayIncrement = 5;
       
    24 const TInt KMaxServiceNameLength = 256;
       
    25 const TInt KDefaultLanguage = 0x0100;
       
    26 const TInt KIndentationFactor = 3;
       
    27 
       
    28 _LIT(KTextHexPrefix,"0x");
       
    29 
       
    30 CBtServicesEng::CBtServicesEng()
       
    31 	{
       
    32 	iSdpAgent = NULL;
       
    33 	iSearchPattern = NULL;
       
    34 	iAttributeArray = NULL;
       
    35 	
       
    36 	iView = NULL;
       
    37 	
       
    38 	iAttributeMatchList = NULL;
       
    39 	iAttributeBuilder = NULL;
       
    40 	
       
    41 	iUUIDFilter = (KL2CAP);
       
    42 	}
       
    43 
       
    44 CBtServicesEng::~CBtServicesEng()
       
    45 	{
       
    46 	delete iSdpAgent; // no need to Cancel separately
       
    47 	delete iSearchPattern;
       
    48 	if (iAttributeArray)
       
    49 		{
       
    50 		iAttributeArray->Reset();
       
    51 		delete iAttributeArray;
       
    52 		}
       
    53 	iRecordArray.ResetAndDestroy();
       
    54 	delete iAttributeMatchList;
       
    55 	delete iAttributeBuilder;
       
    56 
       
    57 	iSocketServ.Close();
       
    58 	iUUIDs.Close();
       
    59 	iUUIDsAsText.ResetAndDestroy();
       
    60 	iUUIDsAsText.Close();
       
    61 
       
    62 	iErrorCodes.Close();
       
    63 	iErrorMessages.ResetAndDestroy();
       
    64 	iErrorMessages.Close();
       
    65 	}
       
    66 
       
    67 CBtServicesEng* CBtServicesEng::NewL()
       
    68 	{
       
    69 	CBtServicesEng* self = new(ELeave) CBtServicesEng();
       
    70 	CleanupStack::PushL(self);
       
    71 	self->ConstructL();
       
    72 	CleanupStack::Pop(self);
       
    73 	return self;
       
    74 	}
       
    75 
       
    76 void CBtServicesEng::ConstructL()
       
    77 	{
       
    78 	//iEikon = CEikonEnv::Static();
       
    79 
       
    80 	iSearchPattern = CSdpSearchPattern::NewL();
       
    81 	iAttributeArray = new(ELeave) CDesCArrayFlat(KArrayIncrement);
       
    82 	iAttributeBuilder = CBtAttributeBuilder::NewL(*this);
       
    83 
       
    84 	//read the available filter UUID and corresponding text
       
    85 	TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
       
    86 	RDebug::Printf("CBtServicesEng::ConstructL() arrayCount= %d \r\n", 
       
    87 			arrayCount);
       
    88 	
       
    89 	TInt i;
       
    90 	for (i = 0; i < arrayCount; i++)
       
    91 		{
       
    92 		TUint32 uuid = UuidAsArray[i].uuid;
       
    93 		iUUIDs.Append(TUUID(uuid));
       
    94 		
       
    95 		HBufC* textForm = HBufC::NewL(64);
       
    96 		RDebug::Printf("i=%d HBufC* textForm = 0x%08x \r\n", 
       
    97 				i, textForm);
       
    98 
       
    99 		RDebug::Printf("i=%d HBufC* textForm = 0x%08x \r\n", 
       
   100 				i, textForm);
       
   101 	
       
   102 		TPtrC UuidText = UuidAsArray[i].txt;
       
   103 		RDebug::Print(_L("UuidText: %S \r\n"), &UuidText);
       
   104 
       
   105 		*textForm = UuidText;
       
   106 				
       
   107 		iUUIDsAsText.Append(textForm);
       
   108 		}
       
   109 
       
   110 	//==================================================
       
   111 	/*
       
   112 	buf = iEikon->AllocReadResourceAsDes8LC(R_BLUETOOTH_ERROR_MESSAGES);
       
   113 	res.SetBuffer(buf);
       
   114 	arrayCount = res.ReadInt16();
       
   115 	for (i = 0; i < arrayCount; i++)
       
   116 		{
       
   117 		TInt errorCode = res.ReadInt32();
       
   118 		iErrorCodes.Append(errorCode);
       
   119 		HBufC* message = res.ReadHBufCL();
       
   120 		iErrorMessages.Append(message);
       
   121 		}
       
   122 	CleanupStack::PopAndDestroy(); // buf
       
   123 	*/
       
   124 
       
   125 	User::LeaveIfError(iSocketServ.Connect());
       
   126 	}
       
   127 
       
   128 void CBtServicesEng::ReportMessage(TInt aVerboseLevel, TRefByValue<const TDesC> aFmt, ...)
       
   129 	{
       
   130 	if (iView)
       
   131 		{
       
   132 		VA_LIST list;
       
   133 		VA_START(list, aFmt);
       
   134 		iTextBuf.FormatList(aFmt, list);
       
   135 		iView->PrintTextMsg(aVerboseLevel, iTextBuf);
       
   136 		}
       
   137 	}
       
   138 
       
   139 //generate a text list of UUID value/string
       
   140 void CBtServicesEng::MakeTextUUIDList()
       
   141 	{
       
   142 	TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
       
   143 	TInt i;
       
   144 	ReportMessage(0, _L("========================\r\n"));	
       
   145 	ReportMessage(0, _L("UUID Value | UUID STRING\r\n"));	
       
   146 	ReportMessage(0, _L("========================\r\n"));	
       
   147 	for (i = 0; i < arrayCount; i++)
       
   148 		{
       
   149 		TUint32 uuid = UuidAsArray[i].uuid;
       
   150 		TPtrC string = UuidAsArray[i].txt;
       
   151 		
       
   152 		ReportMessage(0, _L("0x%08x | %S\r\n"), uuid, &string);
       
   153 		}
       
   154 	}
       
   155 
       
   156 //This function should only be called after NewDeviceSelectedL() asynchrnously completes; 
       
   157 //generate a text list of services found (handle and name)
       
   158 //
       
   159 void CBtServicesEng::MakeTextServiceList()
       
   160 	{
       
   161 	TInt i;
       
   162 	
       
   163 	TPtrC UuidStr = UUIDToString(iUUIDFilter);
       
   164 	ReportMessage(0, _L("UUID filter 0x%08x %S\r\n"), iUUIDFilter, &UuidStr);			
       
   165 	
       
   166 	TInt HandlesCnt = iRecordArray.Count();
       
   167 	
       
   168 	if (HandlesCnt)
       
   169 		{
       
   170 		ReportMessage(0, _L("============================\r\n"));		
       
   171 		ReportMessage(0, _L("ServiceHandle | Service Name\r\n"));		
       
   172 		ReportMessage(0, _L("============================\r\n"));		
       
   173 		}
       
   174 	
       
   175 	for (i=0; i<HandlesCnt; i++)
       
   176 		{
       
   177 		TSdpServRecordHandle Handle = iRecordArray[i]->iHandle;
       
   178 		const TDesC& Name = iRecordArray[i]->iServiceName;
       
   179 		
       
   180 		ReportMessage(0, _L("0x%08x    | \"%S\"\r\n"), Handle, &Name);
       
   181 		
       
   182 		}
       
   183 		
       
   184 	}
       
   185 
       
   186 //
       
   187 void CBtServicesEng::NewDeviceSelectedL(const TBTDevAddr& aAddress,const TBTDeviceName& aDeviceName)
       
   188 	{
       
   189 	iDeviceName = aDeviceName;
       
   190 	iDeviceAddress = aAddress;
       
   191 
       
   192 	GetDeviceServicesL();
       
   193 	}
       
   194 
       
   195 /**
       
   196 This starts the SDP agent searching for services.
       
   197 Firstly, the previous (if any) SDP agent is deleted and a
       
   198 new one constructed with the address of the new device. The
       
   199 record filter is set based on the UUID filter settings.
       
   200 The NextRecordRequestL() function begins the search, with the
       
   201 results being received via the MSdpAgentNotifier functions.
       
   202 */
       
   203 void CBtServicesEng::GetDeviceServicesL()
       
   204 	{
       
   205 	if (iSdpAgent)
       
   206 		{
       
   207 		DeleteSdpAgent();
       
   208 		}
       
   209 	iSdpAgent = CSdpAgent::NewL(*this, iDeviceAddress); // create new SDP Agent for given device address
       
   210 
       
   211 	iSearchPattern->Reset();
       
   212 	iSearchPattern->AddL(iUUIDFilter);
       
   213 	iSdpAgent->SetRecordFilterL(*iSearchPattern);
       
   214 
       
   215 	iRecordArray.ResetAndDestroy();
       
   216 //	MQikListBoxModel& model = *this;
       
   217 //	model.RemoveAllDataL();
       
   218 	//iView->ListBox().HandleItemRemovalL();
       
   219 	//iView->ListBox().DrawNow();
       
   220 
       
   221 	/*
       
   222 	TGulAlignment position(EHRightVCenter);
       
   223 	_LIT(KMsgFindingServices, "Finding services");
       
   224 	iView->GetEikonEnv()->BusyMsgL(KMsgFindingServices, position);
       
   225 	iView->DimCancelButton(EFalse);
       
   226 	iView->DimRefreshButton(ETrue);
       
   227 	 */
       
   228 	
       
   229 	iSdpAgent->NextRecordRequestL();
       
   230 	}
       
   231 
       
   232 /**
       
   233 The Sdp agent initially returns only record handles for each
       
   234 service - this function then gets the name attribute for
       
   235 each one.
       
   236 */
       
   237 void CBtServicesEng::GetServiceNamesL()
       
   238 	{
       
   239 	if (iHandleCounter < iRecordArray.Count())
       
   240 		{
       
   241 		TSdpAttributeID attributeID = KSdpAttrIdOffsetServiceName + KDefaultLanguage; // only support default language for SDP
       
   242 		iSdpAgent->AttributeRequestL(iRecordArray[iHandleCounter]->iHandle, 
       
   243 				attributeID);
       
   244 				
       
   245 		ReportMessage(1, _L("Query service name for handle 0x%X...\r\n"), 
       
   246 				iRecordArray[iHandleCounter]->iHandle );
       
   247 		}
       
   248 	else
       
   249 		{
       
   250 		iCurrentAttributeRequest = ENoOutstandingRequests;		
       
   251 //		iView->GetEikonEnv()->BusyMsgCancel();
       
   252 //		iView->DimCancelButton(ETrue);
       
   253 //		iView->DimRefreshButton(EFalse);
       
   254 		
       
   255 		if (iView)
       
   256 			iView->AsyncCompleted();
       
   257 		}
       
   258 	}
       
   259 
       
   260 /**
       
   261 Begins getting the full attribute list
       
   262 for a given service. Because an MSdpElementBuilder
       
   263 pointer is passed in AttributeRequestL(), the SDP agent
       
   264 calls the builder functions with each result, rather than
       
   265 AttributeRequestResult(). 
       
   266 */
       
   267 void CBtServicesEng::GetAttributesL(TInt aIndex)
       
   268 	{
       
   269 	iCurrentAttributeRequest = EGettingAllAttributes;
       
   270 	iServiceName.Set(iRecordArray[aIndex]->iServiceName);
       
   271 	iAttributeArray->Reset();
       
   272 	iAttributeBuilder->Reset();
       
   273 	if (iAttributeMatchList)
       
   274 		{
       
   275 		delete iAttributeMatchList;
       
   276 		iAttributeMatchList = NULL;
       
   277 		}
       
   278 	iAttributeMatchList = CSdpAttrIdMatchList::NewL();
       
   279 	iAttributeMatchList->AddL(TAttrRange(0, KMaxTUint16)); // getting all attributes
       
   280 	iAttributeBuilder->SetHandle(iRecordArray[aIndex]->iHandle);
       
   281 	iSdpAgent->AttributeRequestL(iAttributeBuilder, iRecordArray[aIndex]->iHandle, *iAttributeMatchList);
       
   282 	}
       
   283 
       
   284 /**
       
   285 this function is supposed to be called 
       
   286 WITHOUT calling "NewDeviceSelectedL()"
       
   287 
       
   288 Begins getting the full attribute list
       
   289 for a given service. Because an MSdpElementBuilder
       
   290 pointer is passed in AttributeRequestL(), the SDP agent
       
   291 calls the builder functions with each result, rather than
       
   292 AttributeRequestResult(). 
       
   293 */
       
   294 void CBtServicesEng::GetDeviceAttributesL(const TBTDevAddr& aAddress,const TBTDeviceName& aDeviceName, TSdpServRecordHandle aHandle)
       
   295 	{
       
   296 	iDeviceName = aDeviceName;
       
   297 	iDeviceAddress = aAddress;
       
   298 	if (iSdpAgent)
       
   299 		{
       
   300 		DeleteSdpAgent();
       
   301 		}
       
   302 	iSdpAgent = CSdpAgent::NewL(*this, iDeviceAddress); // create new SDP Agent for given device address
       
   303 		
       
   304 	iCurrentAttributeRequest = EGettingAllAttributes;
       
   305 	//iServiceName.Set((*iTextArray)[aIndex]);
       
   306 	iAttributeArray->Reset();
       
   307 	iAttributeBuilder->Reset();
       
   308 	if (iAttributeMatchList)
       
   309 		{
       
   310 		delete iAttributeMatchList;
       
   311 		iAttributeMatchList = NULL;
       
   312 		}
       
   313 	iAttributeMatchList = CSdpAttrIdMatchList::NewL();
       
   314 	iAttributeMatchList->AddL(TAttrRange(0, KMaxTUint16)); // getting all attributes
       
   315 	iAttributeBuilder->SetHandle(aHandle);
       
   316 	iSdpAgent->AttributeRequestL(iAttributeBuilder, aHandle, *iAttributeMatchList);
       
   317 	}
       
   318 
       
   319 
       
   320 void CBtServicesEng::CancelSdpAgent()
       
   321 	{
       
   322 	if (iSdpAgent)
       
   323 		{
       
   324 		iSdpAgent->Cancel();
       
   325 		}
       
   326 	}
       
   327 
       
   328 void CBtServicesEng::DeleteSdpAgent()
       
   329 	{
       
   330 	delete iSdpAgent;
       
   331 	iSdpAgent = NULL;
       
   332 	}
       
   333 
       
   334 void CBtServicesEng::SetUUIDFilterL(TUint32 aUUID)
       
   335 	{
       
   336 	iUUIDFilter = aUUID;
       
   337 	}
       
   338 
       
   339 void CBtServicesEng::AppendUUIDText(TDes& aBuf, TUUID aUUID) const
       
   340 	{
       
   341 	if (aUUID == TUUID(0))
       
   342 		{
       
   343 		aUUID = TUUID(iUUIDFilter);
       
   344 		}
       
   345 	TInt i = 0;
       
   346 	TInt UuidCount = iUUIDs.Count();
       
   347 	for (i = 0; i < UuidCount; i++)
       
   348 		{
       
   349 		if (iUUIDs[i] == aUUID)
       
   350 			{
       
   351 			aBuf.Append(*(iUUIDsAsText[i]));
       
   352 			return;
       
   353 			}
       
   354 		}
       
   355 	_LIT(KTextUUIDHex,"UUID: 0x");
       
   356 	aBuf.Append(KTextUUIDHex);
       
   357 	
       
   358 	const TPtrC8 ptr = aUUID.ShortestForm();
       
   359 	TInt ShortestLength = ptr.Length();
       
   360 	for (i = 0; i<ShortestLength ; i++) // get shortest form
       
   361 		{
       
   362 		aBuf.AppendNumFixedWidth(aUUID[i],EHex,2);
       
   363 		}
       
   364 	}
       
   365 
       
   366 void CBtServicesEng::DisplayDeviceInfoL()
       
   367 	{
       
   368 //	iView->DisplayDeviceInfoDialogL(iDeviceName,iDeviceAddress,iDeviceClass);
       
   369 	}
       
   370 
       
   371 //display local BT address, device name and class info
       
   372 //
       
   373 void CBtServicesEng::DisplayLocalInfoL()
       
   374 	{
       
   375 	/*
       
   376 	RSocket l2CapSock;
       
   377 	TInt err = l2CapSock.Open(iSocketServ, KBTAddrFamily, KSockSeqPacket, KL2CAP);
       
   378 	if (err != KErrNone)
       
   379 		{
       
   380 		_LIT(KErrorText,"Not supported");
       
   381 		TGulAlignment position(EHRightVTop);
       
   382 		iView->GetEikonEnv()->InfoMsgWithAlignmentAndDuration(position,KErrorText,KErrorMsgDuration);
       
   383 		return;
       
   384 		}
       
   385 	CleanupClosePushL(l2CapSock);
       
   386 	TRequestStatus stat;
       
   387 	
       
   388 	TBTDevAddrPckg addrbuf;
       
   389 	l2CapSock.Ioctl(KHCILocalAddressIoctl, stat, &addrbuf, KSolBtHCI); // takes a TBTDevAddrPckg (TPckgBuf<TBTDevAddr>) as documented in 7.0 SDK
       
   390 	User::WaitForRequest(stat);
       
   391 	User::LeaveIfError(stat.Int());
       
   392 
       
   393 	THCIDeviceClassBuf classbuf;
       
   394 	l2CapSock.Ioctl(KHCIReadDeviceClassIoctl, stat, &classbuf, KSolBtHCI); // takes a THCIDeviceClassBuf (TPckgBuf<THCIDeviceClassIoctl>) as documented in 7.0 SDK
       
   395 	User::WaitForRequest(stat);
       
   396 	User::LeaveIfError(stat.Int());
       
   397 	CleanupStack::PopAndDestroy(); // l2CapSock
       
   398 
       
   399 	RHostResolver hr;
       
   400 	User::LeaveIfError(hr.Open(iSocketServ, KBTAddrFamily, KBTLinkManager));
       
   401 	CleanupClosePushL(hr);
       
   402 	TBTDeviceName deviceName;
       
   403 	User::LeaveIfError(hr.GetHostName(deviceName));
       
   404 	CleanupStack::PopAndDestroy();
       
   405 
       
   406 	TBTDevAddr& deviceAddress = addrbuf();
       
   407 	TBTDeviceClass deviceClass(classbuf().iMajorServiceClass, classbuf().iMajorDeviceClass,classbuf().iMinorDeviceClass);
       
   408 	*/
       
   409 
       
   410 	RBTRegServ serv;
       
   411 	RBTLocalDevice me;
       
   412 	User::LeaveIfError(serv.Connect());
       
   413 	CleanupClosePushL(serv);
       
   414 	User::LeaveIfError(me.Open(serv));
       
   415 	CleanupClosePushL(me);
       
   416 	TBTLocalDevice dev;
       
   417 	User::LeaveIfError(me.Get(dev));
       
   418 
       
   419 	TBTDeviceName deviceName;
       
   420 	deviceName.Copy(dev.DeviceName().Left(deviceName.MaxLength()));
       
   421 	TBTDeviceClass deviceClass(dev.DeviceClass());
       
   422 	// RBtLocalDevice doesn't seem to return the address
       
   423 	//const TBTDevAddr& deviceAddress = dev.Address();
       
   424 	TBTDevAddr deviceAddress;
       
   425 	TPtr8 ptr(deviceAddress.Des());
       
   426 	User::LeaveIfError(RProperty::Get(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress, ptr));
       
   427 
       
   428 	CleanupStack::PopAndDestroy(2, &serv);
       
   429 	
       
   430 	TBuf<64> ReadableAddr;
       
   431 	deviceAddress.GetReadable(ReadableAddr);
       
   432 	ReportMessage(0, _L("BTAddress:0x%S, Name:\"%S\", DeviceClass=0x%08x\r\n"), 
       
   433 			&ReadableAddr, &deviceName, deviceClass.DeviceClass());
       
   434 
       
   435 	/*
       
   436 #if 0 //test code, not used	
       
   437 	//query further about the services provided by this device
       
   438 	RSdp sdp;
       
   439 	sdp.Connect();
       
   440 	CleanupClosePushL(sdp);
       
   441 		
       
   442 	RSdpDatabase sdpData;
       
   443 	sdpData.Open(sdp);
       
   444 	CleanupClosePushL(sdpData);				
       
   445 
       
   446 	CleanupStack::PopAndDestroy();
       
   447 	CleanupStack::PopAndDestroy();
       
   448 #endif	
       
   449 	*/
       
   450 	}
       
   451 
       
   452 
       
   453 void CBtServicesEng::SetView(CBtServiceView* apView)
       
   454 	{
       
   455 	iView = apView;
       
   456 	}
       
   457 	
       
   458 
       
   459 /*
       
   460 CDesCArrayFlat* CBtServicesEng::GetTextArray() const
       
   461 	{
       
   462 	return iTextArray;
       
   463 	}
       
   464 */
       
   465 
       
   466 /**
       
   467 Checks whether bluetooth is enabled by opening a host
       
   468 resolver and immediately closing it again.
       
   469 */
       
   470 TInt CBtServicesEng::BluetoothReady()
       
   471 	{
       
   472 	RHostResolver hr;
       
   473 	TInt err = hr.Open(iSocketServ, KBTAddrFamily, KBTLinkManager); // just to check if bluetooth is enabled
       
   474 	hr.Close();
       
   475 	return err;
       
   476 	}
       
   477 
       
   478 TBool CBtServicesEng::GettingAllAttributes() const
       
   479 	{
       
   480 	return (iCurrentAttributeRequest == EGettingAllAttributes);
       
   481 	}
       
   482 
       
   483 void CBtServicesEng::AddAttributeLineL(const TDesC& aDes)
       
   484 	{
       
   485 	iAttributeArray->AppendL(aDes);
       
   486 	}
       
   487 
       
   488 void CBtServicesEng::AttributeRequestComplete(TSdpServRecordHandle  aHandle, TInt aError)
       
   489 	{
       
   490 	ReportMessage(1, _L("[AttributeRequestComplete for Handle:0x%X Err:%d]\r\n\r\n"), aHandle, aError);
       
   491 	
       
   492 	if(aError == KErrNone)
       
   493 		{
       
   494 		TRAP(aError, DoAttributeRequestCompleteL());
       
   495 		}
       
   496 	if(aError != KErrNone)
       
   497 		{
       
   498 		SdpCompletedWithError(aError);
       
   499 		}
       
   500 	}
       
   501 
       
   502 void CBtServicesEng::DoAttributeRequestCompleteL()
       
   503 	{
       
   504 	if (iCurrentAttributeRequest == EGettingNamesOnly)
       
   505 		{
       
   506 		//there are a lot of handles that needs the name, so 
       
   507 		//need to keep issue requests until all handles are processed,
       
   508 		//so the whole asynchronous process is not finished yet
       
   509 		iHandleCounter++;
       
   510 		GetServiceNamesL();
       
   511 		}
       
   512 	else if (iCurrentAttributeRequest == EGettingAllAttributes)
       
   513 		{ // all attributes have been got
       
   514 		TInt LineCount = iAttributeArray->Count();
       
   515 		
       
   516 		for (TInt i=0; i<LineCount; i++)
       
   517 			{
       
   518 			const TDesC& LineString = (*iAttributeArray)[i];						
       
   519 			ReportMessage(0, _L("%S\r\n"), &LineString);
       
   520 			}
       
   521 		
       
   522 //		iView->DisplayAttributeDialogL(iAttributeArray, iDeviceName, iServiceName);
       
   523 		iCurrentAttributeRequest = ENoOutstandingRequests;
       
   524 		if (iView)
       
   525 			iView->AsyncCompleted();
       
   526 		}
       
   527 	}
       
   528 
       
   529 void CBtServicesEng::AttributeRequestResult(TSdpServRecordHandle aHandle, TSdpAttributeID /*aAttrID*/, CSdpAttrValue* aAttrValue)
       
   530 	{
       
   531 	ReportMessage(1, _L("[AttributeRequestResult for Handle:0x%X ]\r\n"), aHandle );
       
   532 
       
   533 	TRAPD(err,DoAttributeRequestResultL(aAttrValue, aHandle)); // passing ownership
       
   534 	if (err != KErrNone)
       
   535 		{
       
   536 		iSdpAgent->Cancel();
       
   537 		}
       
   538 	}
       
   539 	
       
   540 void CBtServicesEng::DoAttributeRequestResultL(CSdpAttrValue* aAttrValue, TSdpServRecordHandle aHandle)
       
   541 	{
       
   542 	CleanupStack::PushL(aAttrValue); // taken ownership
       
   543 	if (iCurrentAttributeRequest == EGettingNamesOnly) 
       
   544 		{		 
       
   545 		TBuf16<KMaxServiceNameLength> unicode;
       
   546 		CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode,aAttrValue->Des());
       
   547 		if (unicode[unicode.Length() - 1] == L'\0')
       
   548 			{
       
   549 			unicode.Delete(unicode.Length() - 1, 1); // remove NULL-termination
       
   550 			}
       
   551 		//iView->ListBox().HandleItemAdditionL();
       
   552 		TBuf<64> string;
       
   553 		string.Copy(unicode);
       
   554 		
       
   555 		//extra check to make sure Handle and Name are paired correctly
       
   556 		if (iRecordArray[iHandleCounter]->iHandle != aHandle)
       
   557 			User::Panic(_L("Handle not match"), KErrNone);
       
   558 		
       
   559 		iRecordArray[iHandleCounter]->iServiceName = string;
       
   560 		
       
   561 		ReportMessage(1, _L("%S \r\n"), &string);		
       
   562 /*		
       
   563 		MQikListBoxModel& model = *this;
       
   564 		model.ModelBeginUpdateLC();
       
   565 		MQikListBoxData* data = model.NewDataL(EDataNormal);
       
   566 		data->AddTextL(unicode, EQikListBoxSlotText1);
       
   567 		data->Close();
       
   568 		model.ModelEndUpdateL();
       
   569 */		
       
   570 		}
       
   571 
       
   572 	CleanupStack::PopAndDestroy(aAttrValue);  
       
   573 	}
       
   574 
       
   575 void CBtServicesEng::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt /* aTotalRecordsCount */)
       
   576 	{
       
   577 	if ((aError == KErrNone) || (aError == KErrEof))
       
   578 		{
       
   579 		TRAPD(err, DoNextRecordRequestCompleteL(aHandle, aError));
       
   580 		if (err != KErrNone)
       
   581 			{
       
   582 			aError = err;
       
   583 			}
       
   584 		}
       
   585 	if (aError != KErrNone && aError != KErrEof)
       
   586 		{
       
   587 //		iView->GetEikonEnv()->BusyMsgCancel();
       
   588 		SdpCompletedWithError(aError);
       
   589 		}
       
   590 	
       
   591 	//if aError == KErrEof, that means no more records to read
       
   592 	
       
   593 	}
       
   594 
       
   595 void CBtServicesEng::DoNextRecordRequestCompleteL(TSdpServRecordHandle aHandle, TInt aError)
       
   596 	{
       
   597 	if (aError == KErrNone)    
       
   598 		{
       
   599 		ReportMessage(1, _L("Record Handle found 0x%X \r\n"), aHandle );
       
   600 		
       
   601 		CServiceRecordItem* pItem = new CServiceRecordItem;
       
   602 		pItem->iHandle = aHandle;		
       
   603 		iRecordArray.Append(pItem);
       
   604 		iSdpAgent->NextRecordRequestL();
       
   605 		}
       
   606 	else if (aError == KErrEof)
       
   607 		//no more records, now query service name for each record found 
       
   608 		{
       
   609 		iHandleCounter = 0;
       
   610 		iCurrentAttributeRequest = EGettingNamesOnly;
       
   611 		
       
   612 		//report status
       
   613 		TInt RecordCnt = iRecordArray.Count();		
       
   614 		ReportMessage(1, _L("%d records found, querying service name...\r\n"), RecordCnt);
       
   615 		GetServiceNamesL();
       
   616 		}
       
   617 	}
       
   618 
       
   619 void CBtServicesEng::SdpCompletedWithError(const TInt aError)
       
   620 	{
       
   621 	
       
   622 	HBufC* buf = HBufC::NewLC(KMaxDescriptorLength);
       
   623 	TPtr errorText = buf->Des();
       
   624 	AppendErrorMessage(aError,errorText);
       
   625 //	TGulAlignment position(EHRightVTop);
       
   626 //	iView->GetEikonEnv()->InfoMsgWithAlignmentAndDuration(position,errorText,KErrorMsgDuration);
       
   627 	ReportMessage(0, *buf);
       
   628 	
       
   629 	CleanupStack::PopAndDestroy();
       
   630 	iSdpAgent->Cancel();
       
   631 //	iView->DimRefreshButton(EFalse);
       
   632 //	iView->DimCancelButton(ETrue);
       
   633 	if (iView)
       
   634 		iView->AsyncCompleted();
       
   635 	
       
   636 	}
       
   637 
       
   638 void CBtServicesEng::AppendErrorMessage(const TInt aError, TDes& aBuf) const
       
   639 	{
       
   640 	for (TInt i = 0; i < iErrorCodes.Count(); i++)
       
   641 		{
       
   642 		if (iErrorCodes[i] == aError)
       
   643 			{
       
   644 			aBuf.Append(*(iErrorMessages[i]));
       
   645 			return;
       
   646 			}
       
   647 		}
       
   648 	_LIT(KErrorTextOther, "Error: ");
       
   649 	aBuf.Append(KErrorTextOther);
       
   650 	aBuf.AppendNum(aError);
       
   651 	}
       
   652 
       
   653 void CBtServicesEng::Panic(TBtPanicCode aPanicCode)
       
   654 	{
       
   655 	_LIT(KBtPanicText, "BTSU::Panic ");
       
   656 	User::Panic(KBtPanicText, aPanicCode);
       
   657 	}
       
   658 
       
   659 void CBtServicesEng::ReleaseModel()
       
   660 	{
       
   661 	// Do nothing, list box does not own us
       
   662 	}
       
   663 
       
   664 //static
       
   665 //search the Uuid value, and return a text string of its name
       
   666 TPtrC CBtServicesEng::UUIDToString(TUint32 aUuidValue)
       
   667 	{
       
   668 	//read the available filter UUID and corresponding text
       
   669 	TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
       
   670 	TInt i;
       
   671 	for (i = 0; i < arrayCount; i++)
       
   672 		{
       
   673 		TUint32 uuid = UuidAsArray[i].uuid;
       
   674 		if (uuid == aUuidValue)
       
   675 			return (UuidAsArray[i].txt);
       
   676 		}
       
   677 	return _L("");
       
   678 	}
       
   679 
       
   680 //static
       
   681 //search through the value, and return the UUID value if there is one match
       
   682 //aUuidValue: [out] the found result
       
   683 TBool CBtServicesEng::StringToUUID(TDesC& aString, TUint32& aUuidValue)
       
   684 	{
       
   685 	//read the available filter UUID and corresponding text
       
   686 	TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
       
   687 	TInt i;
       
   688 	for (i = 0; i < arrayCount; i++)
       
   689 		{
       
   690 		TUint32 uuid = UuidAsArray[i].uuid;
       
   691 		if (aString == UuidAsArray[i].txt)
       
   692 			{
       
   693 			aUuidValue = uuid;
       
   694 			return ETrue;
       
   695 			}			
       
   696 		}
       
   697 	return EFalse;
       
   698 	}
       
   699 
       
   700 
       
   701 ///////////////////////////////////////
       
   702 // CBtAttributeBuilder functions
       
   703 ///////////////////////////////////////
       
   704 
       
   705 CBtAttributeBuilder* CBtAttributeBuilder::NewL(CBtServicesEng& aEngine)
       
   706 	{
       
   707 	CBtAttributeBuilder* self = new(ELeave) CBtAttributeBuilder(aEngine);
       
   708 	CleanupStack::PushL(self);
       
   709 	self->ConstructL();
       
   710 	CleanupStack::Pop(self);
       
   711 	return self;
       
   712 	}
       
   713 
       
   714 CBtAttributeBuilder::CBtAttributeBuilder(CBtServicesEng& aEngine)
       
   715 : iEngine(aEngine)
       
   716 	{
       
   717 	}
       
   718 
       
   719 void CBtAttributeBuilder::ConstructL()
       
   720 	{
       
   721 /*	
       
   722 	HBufC8* buf = CEikonEnv::Static()->AllocReadResourceAsDes8LC(R_ATTR_ID_MNEMONICS);
       
   723 
       
   724 	TResourceReader res;
       
   725 	res.SetBuffer(buf);
       
   726 
       
   727 	TInt arrayCount = res.ReadInt16();
       
   728 	for (TInt i = 0; i < arrayCount; i++)
       
   729 		{
       
   730 		TUint attrID = res.ReadUint32();
       
   731 		iAttrIDs.Append(attrID);
       
   732 		HBufC* mnemonic = res.ReadHBufCL();
       
   733 		iAttrMnemonics.Append(mnemonic);
       
   734 		}
       
   735 	CleanupStack::PopAndDestroy(); // buf
       
   736 */	
       
   737 	}
       
   738 
       
   739 CBtAttributeBuilder::~CBtAttributeBuilder()
       
   740 	{
       
   741 	iAttrIDs.Close();
       
   742 	iAttrMnemonics.ResetAndDestroy();
       
   743 	iAttrMnemonics.Close();
       
   744 	}
       
   745 
       
   746 void CBtAttributeBuilder::Reset()
       
   747 	{
       
   748 	iIndentation = 0;
       
   749 	iCurrentLine.Zero();
       
   750 	}
       
   751 
       
   752 void CBtAttributeBuilder::SetHandle(TSdpServRecordHandle aHandle)
       
   753 	{
       
   754 	iHandle = aHandle;
       
   755 	}
       
   756 
       
   757 MSdpElementBuilder* CBtAttributeBuilder::BuildUnknownL(TUint8 aType, TUint8 /* aSizeDesc */, const TDesC8& /* aData */)
       
   758 	{
       
   759 	if (iStatus == EExpectingAttrID)
       
   760 		{
       
   761 		_LIT(KErrorText,"**Error: Unexpected UNKNOWN");
       
   762 		iCurrentLine.Append(KErrorText);
       
   763 		}
       
   764 	else
       
   765 		{
       
   766 		_LIT(KTextUnknown,"UNKNOWN");
       
   767 		iCurrentLine.Append(KTextUnknown);
       
   768 		iCurrentLine.AppendNum((TInt) aType);
       
   769 		}		
       
   770 	LineFinishedL();
       
   771 	return this;
       
   772 	}
       
   773 
       
   774 MSdpElementBuilder* CBtAttributeBuilder::BuildNilL()
       
   775 	{
       
   776 	if (iStatus == EExpectingAttrID)
       
   777 		{
       
   778 		_LIT(KErrorText,"**Error: Unexpected NIL");
       
   779 		iCurrentLine.Append(KErrorText);
       
   780 		}
       
   781 	else
       
   782 		{
       
   783 		_LIT(KTextNULL,"NULL");
       
   784 		iCurrentLine.Append(KTextNULL);
       
   785 		}
       
   786 	LineFinishedL();
       
   787 	return this;
       
   788 	}
       
   789 
       
   790 MSdpElementBuilder* CBtAttributeBuilder::BuildUintL(const TDesC8& aUint)
       
   791 	{
       
   792 
       
   793 	if (iStatus == EExpectingAttrValue)
       
   794 		{
       
   795 		iCurrentLine.Append(KTextHexPrefix);
       
   796 		for (TInt i = 0; i < aUint.Length(); i++)
       
   797 			{
       
   798 			iCurrentLine.AppendNumFixedWidth(aUint[i], EHex,2);
       
   799 			}
       
   800 		LineFinishedL();
       
   801 		}
       
   802 	else if (iStatus == EExpectingAttrID)
       
   803 		{
       
   804 		TUint value = 0;
       
   805 		for (TInt i = 0; i < aUint.Length(); i++)
       
   806 			{
       
   807 			value <<= 8;
       
   808 			value += aUint[i];
       
   809 			}
       
   810 		AppendAttrMnemonic(iCurrentLine,value);
       
   811 		iStatus = EExpectingAttrValue;
       
   812 		}
       
   813 
       
   814 	return this;
       
   815 	}
       
   816 
       
   817 MSdpElementBuilder* CBtAttributeBuilder::BuildIntL(const TDesC8& aInt)
       
   818 	{
       
   819 	if (iStatus == EExpectingAttrID)
       
   820 		{
       
   821 		_LIT(KErrorText,"**Error: Unexpected Int");
       
   822 		iCurrentLine.Append(KErrorText);
       
   823 		}
       
   824 	else
       
   825 		{
       
   826 		iCurrentLine.Append(KTextHexPrefix);
       
   827 		for (TInt i = 0; i < aInt.Length(); i++)
       
   828 			{
       
   829 			iCurrentLine.AppendNumFixedWidth(aInt[i], EHex,2);
       
   830 			}
       
   831 		}
       
   832 	LineFinishedL();
       
   833 	return this;
       
   834 	}
       
   835 
       
   836 MSdpElementBuilder* CBtAttributeBuilder::BuildUUIDL(const TUUID& aUUID)
       
   837 	{
       
   838 	if (iStatus == EExpectingAttrID)
       
   839 		{
       
   840 		_LIT(KErrorText,"**Error: Unexpected UUID");
       
   841 		iCurrentLine.Append(KErrorText);
       
   842 		}
       
   843 	else
       
   844 		{
       
   845 		iEngine.AppendUUIDText(iCurrentLine,aUUID);
       
   846 		}
       
   847 	LineFinishedL();
       
   848 	return this;
       
   849 	}
       
   850 
       
   851 MSdpElementBuilder* CBtAttributeBuilder::BuildBooleanL(TBool aBool)
       
   852 	{
       
   853 	if (iStatus == EExpectingAttrID)
       
   854 		{
       
   855 		_LIT(KErrorText,"**Error: Unexpected Boolean");
       
   856 		iCurrentLine.Append(KErrorText);
       
   857 		}
       
   858 	else
       
   859 		{
       
   860 		if (aBool)
       
   861 			{
       
   862 			_LIT(KTextTrue,"TRUE");
       
   863 			iCurrentLine.Append(KTextTrue);
       
   864 			}
       
   865 		else
       
   866 			{
       
   867 			_LIT(KTextFalse,"FALSE");
       
   868 			iCurrentLine.Append(KTextFalse);
       
   869 			}
       
   870 		}
       
   871 	LineFinishedL();
       
   872 	return this;
       
   873 	}
       
   874 
       
   875 MSdpElementBuilder* CBtAttributeBuilder::BuildStringL(const TDesC8& aString)
       
   876 	{
       
   877 	if (iStatus == EExpectingAttrID)
       
   878 		{
       
   879 		_LIT(KErrorText,"**Error: Unexpected String");
       
   880 		iCurrentLine.Append(KErrorText);
       
   881 		}
       
   882 	else
       
   883 		{
       
   884 		TBuf16<KMaxDescriptorLength> unicode;
       
   885 		CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode,aString);
       
   886 		if (unicode[unicode.Length() - 1] == NULL)
       
   887 			{
       
   888 			unicode.Delete(unicode.Length() - 1, 1); // remove NULL-termination
       
   889 			}
       
   890 		iCurrentLine.Append(unicode);
       
   891 		}
       
   892 	LineFinishedL();
       
   893 	return this;
       
   894 	}
       
   895 
       
   896 MSdpElementBuilder* CBtAttributeBuilder::BuildDESL()
       
   897 	{
       
   898 	if (iIndentation == 1)
       
   899 		{
       
   900 		iEngine.AddAttributeLineL(iCurrentLine);
       
   901 		}
       
   902 	return this;
       
   903 	}
       
   904 
       
   905 MSdpElementBuilder* CBtAttributeBuilder::BuildDEAL()
       
   906 	{
       
   907 	_LIT(KTextDEAL,"Data Element Alternate List");
       
   908 	iCurrentLine.Append(KTextDEAL);
       
   909 	iEngine.AddAttributeLineL(iCurrentLine);
       
   910 	return this;
       
   911 	}
       
   912 
       
   913 MSdpElementBuilder* CBtAttributeBuilder::StartListL()
       
   914 	{
       
   915 	iIndentation++;
       
   916 	iCurrentLine.Zero();
       
   917 	__ASSERT_ALWAYS(iIndentation > 0, CBtServicesEng::Panic(EBtIndentationZeroInStartList));
       
   918 	iCurrentLine.AppendFill(' ', (iIndentation - 1) * KIndentationFactor);
       
   919 	return this;
       
   920 	}
       
   921 
       
   922 MSdpElementBuilder* CBtAttributeBuilder::EndListL()
       
   923 	{
       
   924 	_LIT(KTextEndListDashes,"--------");
       
   925 	iCurrentLine.Append(KTextEndListDashes);
       
   926 	iEngine.AddAttributeLineL(iCurrentLine);
       
   927 	iIndentation--;
       
   928 	iCurrentLine.Zero();
       
   929 	if (iIndentation)
       
   930 		{
       
   931 		iCurrentLine.AppendFill(' ', (iIndentation - 1) * KIndentationFactor); // in this case indentation has already been checked to be greater than zero
       
   932 		}
       
   933 	if (iIndentation == 1)
       
   934 		{
       
   935 		iStatus = EExpectingAttrID;
       
   936 		}
       
   937 	return this;
       
   938 	}
       
   939 
       
   940 MSdpElementBuilder* CBtAttributeBuilder::BuildURLL(const TDesC8& aURL)
       
   941 	{
       
   942 	TBuf16<KMaxDescriptorLength> unicode;
       
   943 	CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode,aURL);
       
   944 	iCurrentLine.Append(unicode);
       
   945 	LineFinishedL();
       
   946 	return this;
       
   947 	}
       
   948 
       
   949 void CBtAttributeBuilder::AppendAttrMnemonic(TDes& aBuf, TUint aAttrID) const
       
   950 	{
       
   951 	for (TInt i = 0; i < iAttrIDs.Count(); i++)
       
   952 		{
       
   953 		if (iAttrIDs[i] == aAttrID)
       
   954 			{
       
   955 			aBuf.Append(*(iAttrMnemonics[i]));
       
   956 			return;
       
   957 			}
       
   958 		}
       
   959 	if (aAttrID == 0x0200 && iHandle == 0)
       
   960 		{
       
   961 		_LIT(KVersionNoPrefix,"VersionNo.: ");
       
   962 		aBuf.Append(KVersionNoPrefix);
       
   963 		}
       
   964 	else if (aAttrID == 0x0201 && iHandle == 0)
       
   965 		{
       
   966 		_LIT(KDatabaseStatePrefix,"DatabaseState: ");
       
   967 		aBuf.Append(KDatabaseStatePrefix);
       
   968 		}
       
   969 	else
       
   970 		{
       
   971 		_LIT(KTextAttrIDHex,"AttrID 0x");
       
   972 		aBuf.Append(KTextAttrIDHex);
       
   973 		aBuf.AppendNum(aAttrID,EHex);
       
   974 		_LIT(KTextColonSpace,": ");
       
   975 		aBuf.Append(KTextColonSpace);
       
   976 		}
       
   977 	}
       
   978 
       
   979 void CBtAttributeBuilder::LineFinishedL()
       
   980 	{
       
   981 	iEngine.AddAttributeLineL(iCurrentLine);
       
   982 	iCurrentLine.Zero();
       
   983 	__ASSERT_ALWAYS(iIndentation > 0, CBtServicesEng::Panic(EBtIndentationZeroInLineFinished));
       
   984 	iCurrentLine.AppendFill(' ', (iIndentation - 1) * KIndentationFactor);
       
   985 	if (iIndentation == 1)
       
   986 		{
       
   987 		iStatus = EExpectingAttrID;
       
   988 		}
       
   989 	}