--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/btservices/BtServicesEng.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,989 @@
+// BtServicesEng.cpp
+//
+// Copyright (c) 2003 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+//#include <qbtselectdlg.h>
+
+#include <e32debug.h>
+
+#include <utf.h>
+#include "BtData.h"
+#include "btserviceseng.h"
+#include <btmanclient.h>
+//#include <MQikListBoxData.h>
+
+const TInt KArrayIncrement = 5;
+const TInt KMaxServiceNameLength = 256;
+const TInt KDefaultLanguage = 0x0100;
+const TInt KIndentationFactor = 3;
+
+_LIT(KTextHexPrefix,"0x");
+
+CBtServicesEng::CBtServicesEng()
+ {
+ iSdpAgent = NULL;
+ iSearchPattern = NULL;
+ iAttributeArray = NULL;
+
+ iView = NULL;
+
+ iAttributeMatchList = NULL;
+ iAttributeBuilder = NULL;
+
+ iUUIDFilter = (KL2CAP);
+ }
+
+CBtServicesEng::~CBtServicesEng()
+ {
+ delete iSdpAgent; // no need to Cancel separately
+ delete iSearchPattern;
+ if (iAttributeArray)
+ {
+ iAttributeArray->Reset();
+ delete iAttributeArray;
+ }
+ iRecordArray.ResetAndDestroy();
+ delete iAttributeMatchList;
+ delete iAttributeBuilder;
+
+ iSocketServ.Close();
+ iUUIDs.Close();
+ iUUIDsAsText.ResetAndDestroy();
+ iUUIDsAsText.Close();
+
+ iErrorCodes.Close();
+ iErrorMessages.ResetAndDestroy();
+ iErrorMessages.Close();
+ }
+
+CBtServicesEng* CBtServicesEng::NewL()
+ {
+ CBtServicesEng* self = new(ELeave) CBtServicesEng();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CBtServicesEng::ConstructL()
+ {
+ //iEikon = CEikonEnv::Static();
+
+ iSearchPattern = CSdpSearchPattern::NewL();
+ iAttributeArray = new(ELeave) CDesCArrayFlat(KArrayIncrement);
+ iAttributeBuilder = CBtAttributeBuilder::NewL(*this);
+
+ //read the available filter UUID and corresponding text
+ TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
+ RDebug::Printf("CBtServicesEng::ConstructL() arrayCount= %d \r\n",
+ arrayCount);
+
+ TInt i;
+ for (i = 0; i < arrayCount; i++)
+ {
+ TUint32 uuid = UuidAsArray[i].uuid;
+ iUUIDs.Append(TUUID(uuid));
+
+ HBufC* textForm = HBufC::NewL(64);
+ RDebug::Printf("i=%d HBufC* textForm = 0x%08x \r\n",
+ i, textForm);
+
+ RDebug::Printf("i=%d HBufC* textForm = 0x%08x \r\n",
+ i, textForm);
+
+ TPtrC UuidText = UuidAsArray[i].txt;
+ RDebug::Print(_L("UuidText: %S \r\n"), &UuidText);
+
+ *textForm = UuidText;
+
+ iUUIDsAsText.Append(textForm);
+ }
+
+ //==================================================
+ /*
+ buf = iEikon->AllocReadResourceAsDes8LC(R_BLUETOOTH_ERROR_MESSAGES);
+ res.SetBuffer(buf);
+ arrayCount = res.ReadInt16();
+ for (i = 0; i < arrayCount; i++)
+ {
+ TInt errorCode = res.ReadInt32();
+ iErrorCodes.Append(errorCode);
+ HBufC* message = res.ReadHBufCL();
+ iErrorMessages.Append(message);
+ }
+ CleanupStack::PopAndDestroy(); // buf
+ */
+
+ User::LeaveIfError(iSocketServ.Connect());
+ }
+
+void CBtServicesEng::ReportMessage(TInt aVerboseLevel, TRefByValue<const TDesC> aFmt, ...)
+ {
+ if (iView)
+ {
+ VA_LIST list;
+ VA_START(list, aFmt);
+ iTextBuf.FormatList(aFmt, list);
+ iView->PrintTextMsg(aVerboseLevel, iTextBuf);
+ }
+ }
+
+//generate a text list of UUID value/string
+void CBtServicesEng::MakeTextUUIDList()
+ {
+ TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
+ TInt i;
+ ReportMessage(0, _L("========================\r\n"));
+ ReportMessage(0, _L("UUID Value | UUID STRING\r\n"));
+ ReportMessage(0, _L("========================\r\n"));
+ for (i = 0; i < arrayCount; i++)
+ {
+ TUint32 uuid = UuidAsArray[i].uuid;
+ TPtrC string = UuidAsArray[i].txt;
+
+ ReportMessage(0, _L("0x%08x | %S\r\n"), uuid, &string);
+ }
+ }
+
+//This function should only be called after NewDeviceSelectedL() asynchrnously completes;
+//generate a text list of services found (handle and name)
+//
+void CBtServicesEng::MakeTextServiceList()
+ {
+ TInt i;
+
+ TPtrC UuidStr = UUIDToString(iUUIDFilter);
+ ReportMessage(0, _L("UUID filter 0x%08x %S\r\n"), iUUIDFilter, &UuidStr);
+
+ TInt HandlesCnt = iRecordArray.Count();
+
+ if (HandlesCnt)
+ {
+ ReportMessage(0, _L("============================\r\n"));
+ ReportMessage(0, _L("ServiceHandle | Service Name\r\n"));
+ ReportMessage(0, _L("============================\r\n"));
+ }
+
+ for (i=0; i<HandlesCnt; i++)
+ {
+ TSdpServRecordHandle Handle = iRecordArray[i]->iHandle;
+ const TDesC& Name = iRecordArray[i]->iServiceName;
+
+ ReportMessage(0, _L("0x%08x | \"%S\"\r\n"), Handle, &Name);
+
+ }
+
+ }
+
+//
+void CBtServicesEng::NewDeviceSelectedL(const TBTDevAddr& aAddress,const TBTDeviceName& aDeviceName)
+ {
+ iDeviceName = aDeviceName;
+ iDeviceAddress = aAddress;
+
+ GetDeviceServicesL();
+ }
+
+/**
+This starts the SDP agent searching for services.
+Firstly, the previous (if any) SDP agent is deleted and a
+new one constructed with the address of the new device. The
+record filter is set based on the UUID filter settings.
+The NextRecordRequestL() function begins the search, with the
+results being received via the MSdpAgentNotifier functions.
+*/
+void CBtServicesEng::GetDeviceServicesL()
+ {
+ if (iSdpAgent)
+ {
+ DeleteSdpAgent();
+ }
+ iSdpAgent = CSdpAgent::NewL(*this, iDeviceAddress); // create new SDP Agent for given device address
+
+ iSearchPattern->Reset();
+ iSearchPattern->AddL(iUUIDFilter);
+ iSdpAgent->SetRecordFilterL(*iSearchPattern);
+
+ iRecordArray.ResetAndDestroy();
+// MQikListBoxModel& model = *this;
+// model.RemoveAllDataL();
+ //iView->ListBox().HandleItemRemovalL();
+ //iView->ListBox().DrawNow();
+
+ /*
+ TGulAlignment position(EHRightVCenter);
+ _LIT(KMsgFindingServices, "Finding services");
+ iView->GetEikonEnv()->BusyMsgL(KMsgFindingServices, position);
+ iView->DimCancelButton(EFalse);
+ iView->DimRefreshButton(ETrue);
+ */
+
+ iSdpAgent->NextRecordRequestL();
+ }
+
+/**
+The Sdp agent initially returns only record handles for each
+service - this function then gets the name attribute for
+each one.
+*/
+void CBtServicesEng::GetServiceNamesL()
+ {
+ if (iHandleCounter < iRecordArray.Count())
+ {
+ TSdpAttributeID attributeID = KSdpAttrIdOffsetServiceName + KDefaultLanguage; // only support default language for SDP
+ iSdpAgent->AttributeRequestL(iRecordArray[iHandleCounter]->iHandle,
+ attributeID);
+
+ ReportMessage(1, _L("Query service name for handle 0x%X...\r\n"),
+ iRecordArray[iHandleCounter]->iHandle );
+ }
+ else
+ {
+ iCurrentAttributeRequest = ENoOutstandingRequests;
+// iView->GetEikonEnv()->BusyMsgCancel();
+// iView->DimCancelButton(ETrue);
+// iView->DimRefreshButton(EFalse);
+
+ if (iView)
+ iView->AsyncCompleted();
+ }
+ }
+
+/**
+Begins getting the full attribute list
+for a given service. Because an MSdpElementBuilder
+pointer is passed in AttributeRequestL(), the SDP agent
+calls the builder functions with each result, rather than
+AttributeRequestResult().
+*/
+void CBtServicesEng::GetAttributesL(TInt aIndex)
+ {
+ iCurrentAttributeRequest = EGettingAllAttributes;
+ iServiceName.Set(iRecordArray[aIndex]->iServiceName);
+ iAttributeArray->Reset();
+ iAttributeBuilder->Reset();
+ if (iAttributeMatchList)
+ {
+ delete iAttributeMatchList;
+ iAttributeMatchList = NULL;
+ }
+ iAttributeMatchList = CSdpAttrIdMatchList::NewL();
+ iAttributeMatchList->AddL(TAttrRange(0, KMaxTUint16)); // getting all attributes
+ iAttributeBuilder->SetHandle(iRecordArray[aIndex]->iHandle);
+ iSdpAgent->AttributeRequestL(iAttributeBuilder, iRecordArray[aIndex]->iHandle, *iAttributeMatchList);
+ }
+
+/**
+this function is supposed to be called
+WITHOUT calling "NewDeviceSelectedL()"
+
+Begins getting the full attribute list
+for a given service. Because an MSdpElementBuilder
+pointer is passed in AttributeRequestL(), the SDP agent
+calls the builder functions with each result, rather than
+AttributeRequestResult().
+*/
+void CBtServicesEng::GetDeviceAttributesL(const TBTDevAddr& aAddress,const TBTDeviceName& aDeviceName, TSdpServRecordHandle aHandle)
+ {
+ iDeviceName = aDeviceName;
+ iDeviceAddress = aAddress;
+ if (iSdpAgent)
+ {
+ DeleteSdpAgent();
+ }
+ iSdpAgent = CSdpAgent::NewL(*this, iDeviceAddress); // create new SDP Agent for given device address
+
+ iCurrentAttributeRequest = EGettingAllAttributes;
+ //iServiceName.Set((*iTextArray)[aIndex]);
+ iAttributeArray->Reset();
+ iAttributeBuilder->Reset();
+ if (iAttributeMatchList)
+ {
+ delete iAttributeMatchList;
+ iAttributeMatchList = NULL;
+ }
+ iAttributeMatchList = CSdpAttrIdMatchList::NewL();
+ iAttributeMatchList->AddL(TAttrRange(0, KMaxTUint16)); // getting all attributes
+ iAttributeBuilder->SetHandle(aHandle);
+ iSdpAgent->AttributeRequestL(iAttributeBuilder, aHandle, *iAttributeMatchList);
+ }
+
+
+void CBtServicesEng::CancelSdpAgent()
+ {
+ if (iSdpAgent)
+ {
+ iSdpAgent->Cancel();
+ }
+ }
+
+void CBtServicesEng::DeleteSdpAgent()
+ {
+ delete iSdpAgent;
+ iSdpAgent = NULL;
+ }
+
+void CBtServicesEng::SetUUIDFilterL(TUint32 aUUID)
+ {
+ iUUIDFilter = aUUID;
+ }
+
+void CBtServicesEng::AppendUUIDText(TDes& aBuf, TUUID aUUID) const
+ {
+ if (aUUID == TUUID(0))
+ {
+ aUUID = TUUID(iUUIDFilter);
+ }
+ TInt i = 0;
+ TInt UuidCount = iUUIDs.Count();
+ for (i = 0; i < UuidCount; i++)
+ {
+ if (iUUIDs[i] == aUUID)
+ {
+ aBuf.Append(*(iUUIDsAsText[i]));
+ return;
+ }
+ }
+ _LIT(KTextUUIDHex,"UUID: 0x");
+ aBuf.Append(KTextUUIDHex);
+
+ const TPtrC8 ptr = aUUID.ShortestForm();
+ TInt ShortestLength = ptr.Length();
+ for (i = 0; i<ShortestLength ; i++) // get shortest form
+ {
+ aBuf.AppendNumFixedWidth(aUUID[i],EHex,2);
+ }
+ }
+
+void CBtServicesEng::DisplayDeviceInfoL()
+ {
+// iView->DisplayDeviceInfoDialogL(iDeviceName,iDeviceAddress,iDeviceClass);
+ }
+
+//display local BT address, device name and class info
+//
+void CBtServicesEng::DisplayLocalInfoL()
+ {
+ /*
+ RSocket l2CapSock;
+ TInt err = l2CapSock.Open(iSocketServ, KBTAddrFamily, KSockSeqPacket, KL2CAP);
+ if (err != KErrNone)
+ {
+ _LIT(KErrorText,"Not supported");
+ TGulAlignment position(EHRightVTop);
+ iView->GetEikonEnv()->InfoMsgWithAlignmentAndDuration(position,KErrorText,KErrorMsgDuration);
+ return;
+ }
+ CleanupClosePushL(l2CapSock);
+ TRequestStatus stat;
+
+ TBTDevAddrPckg addrbuf;
+ l2CapSock.Ioctl(KHCILocalAddressIoctl, stat, &addrbuf, KSolBtHCI); // takes a TBTDevAddrPckg (TPckgBuf<TBTDevAddr>) as documented in 7.0 SDK
+ User::WaitForRequest(stat);
+ User::LeaveIfError(stat.Int());
+
+ THCIDeviceClassBuf classbuf;
+ l2CapSock.Ioctl(KHCIReadDeviceClassIoctl, stat, &classbuf, KSolBtHCI); // takes a THCIDeviceClassBuf (TPckgBuf<THCIDeviceClassIoctl>) as documented in 7.0 SDK
+ User::WaitForRequest(stat);
+ User::LeaveIfError(stat.Int());
+ CleanupStack::PopAndDestroy(); // l2CapSock
+
+ RHostResolver hr;
+ User::LeaveIfError(hr.Open(iSocketServ, KBTAddrFamily, KBTLinkManager));
+ CleanupClosePushL(hr);
+ TBTDeviceName deviceName;
+ User::LeaveIfError(hr.GetHostName(deviceName));
+ CleanupStack::PopAndDestroy();
+
+ TBTDevAddr& deviceAddress = addrbuf();
+ TBTDeviceClass deviceClass(classbuf().iMajorServiceClass, classbuf().iMajorDeviceClass,classbuf().iMinorDeviceClass);
+ */
+
+ RBTRegServ serv;
+ RBTLocalDevice me;
+ User::LeaveIfError(serv.Connect());
+ CleanupClosePushL(serv);
+ User::LeaveIfError(me.Open(serv));
+ CleanupClosePushL(me);
+ TBTLocalDevice dev;
+ User::LeaveIfError(me.Get(dev));
+
+ TBTDeviceName deviceName;
+ deviceName.Copy(dev.DeviceName().Left(deviceName.MaxLength()));
+ TBTDeviceClass deviceClass(dev.DeviceClass());
+ // RBtLocalDevice doesn't seem to return the address
+ //const TBTDevAddr& deviceAddress = dev.Address();
+ TBTDevAddr deviceAddress;
+ TPtr8 ptr(deviceAddress.Des());
+ User::LeaveIfError(RProperty::Get(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress, ptr));
+
+ CleanupStack::PopAndDestroy(2, &serv);
+
+ TBuf<64> ReadableAddr;
+ deviceAddress.GetReadable(ReadableAddr);
+ ReportMessage(0, _L("BTAddress:0x%S, Name:\"%S\", DeviceClass=0x%08x\r\n"),
+ &ReadableAddr, &deviceName, deviceClass.DeviceClass());
+
+ /*
+#if 0 //test code, not used
+ //query further about the services provided by this device
+ RSdp sdp;
+ sdp.Connect();
+ CleanupClosePushL(sdp);
+
+ RSdpDatabase sdpData;
+ sdpData.Open(sdp);
+ CleanupClosePushL(sdpData);
+
+ CleanupStack::PopAndDestroy();
+ CleanupStack::PopAndDestroy();
+#endif
+ */
+ }
+
+
+void CBtServicesEng::SetView(CBtServiceView* apView)
+ {
+ iView = apView;
+ }
+
+
+/*
+CDesCArrayFlat* CBtServicesEng::GetTextArray() const
+ {
+ return iTextArray;
+ }
+*/
+
+/**
+Checks whether bluetooth is enabled by opening a host
+resolver and immediately closing it again.
+*/
+TInt CBtServicesEng::BluetoothReady()
+ {
+ RHostResolver hr;
+ TInt err = hr.Open(iSocketServ, KBTAddrFamily, KBTLinkManager); // just to check if bluetooth is enabled
+ hr.Close();
+ return err;
+ }
+
+TBool CBtServicesEng::GettingAllAttributes() const
+ {
+ return (iCurrentAttributeRequest == EGettingAllAttributes);
+ }
+
+void CBtServicesEng::AddAttributeLineL(const TDesC& aDes)
+ {
+ iAttributeArray->AppendL(aDes);
+ }
+
+void CBtServicesEng::AttributeRequestComplete(TSdpServRecordHandle aHandle, TInt aError)
+ {
+ ReportMessage(1, _L("[AttributeRequestComplete for Handle:0x%X Err:%d]\r\n\r\n"), aHandle, aError);
+
+ if(aError == KErrNone)
+ {
+ TRAP(aError, DoAttributeRequestCompleteL());
+ }
+ if(aError != KErrNone)
+ {
+ SdpCompletedWithError(aError);
+ }
+ }
+
+void CBtServicesEng::DoAttributeRequestCompleteL()
+ {
+ if (iCurrentAttributeRequest == EGettingNamesOnly)
+ {
+ //there are a lot of handles that needs the name, so
+ //need to keep issue requests until all handles are processed,
+ //so the whole asynchronous process is not finished yet
+ iHandleCounter++;
+ GetServiceNamesL();
+ }
+ else if (iCurrentAttributeRequest == EGettingAllAttributes)
+ { // all attributes have been got
+ TInt LineCount = iAttributeArray->Count();
+
+ for (TInt i=0; i<LineCount; i++)
+ {
+ const TDesC& LineString = (*iAttributeArray)[i];
+ ReportMessage(0, _L("%S\r\n"), &LineString);
+ }
+
+// iView->DisplayAttributeDialogL(iAttributeArray, iDeviceName, iServiceName);
+ iCurrentAttributeRequest = ENoOutstandingRequests;
+ if (iView)
+ iView->AsyncCompleted();
+ }
+ }
+
+void CBtServicesEng::AttributeRequestResult(TSdpServRecordHandle aHandle, TSdpAttributeID /*aAttrID*/, CSdpAttrValue* aAttrValue)
+ {
+ ReportMessage(1, _L("[AttributeRequestResult for Handle:0x%X ]\r\n"), aHandle );
+
+ TRAPD(err,DoAttributeRequestResultL(aAttrValue, aHandle)); // passing ownership
+ if (err != KErrNone)
+ {
+ iSdpAgent->Cancel();
+ }
+ }
+
+void CBtServicesEng::DoAttributeRequestResultL(CSdpAttrValue* aAttrValue, TSdpServRecordHandle aHandle)
+ {
+ CleanupStack::PushL(aAttrValue); // taken ownership
+ if (iCurrentAttributeRequest == EGettingNamesOnly)
+ {
+ TBuf16<KMaxServiceNameLength> unicode;
+ CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode,aAttrValue->Des());
+ if (unicode[unicode.Length() - 1] == L'\0')
+ {
+ unicode.Delete(unicode.Length() - 1, 1); // remove NULL-termination
+ }
+ //iView->ListBox().HandleItemAdditionL();
+ TBuf<64> string;
+ string.Copy(unicode);
+
+ //extra check to make sure Handle and Name are paired correctly
+ if (iRecordArray[iHandleCounter]->iHandle != aHandle)
+ User::Panic(_L("Handle not match"), KErrNone);
+
+ iRecordArray[iHandleCounter]->iServiceName = string;
+
+ ReportMessage(1, _L("%S \r\n"), &string);
+/*
+ MQikListBoxModel& model = *this;
+ model.ModelBeginUpdateLC();
+ MQikListBoxData* data = model.NewDataL(EDataNormal);
+ data->AddTextL(unicode, EQikListBoxSlotText1);
+ data->Close();
+ model.ModelEndUpdateL();
+*/
+ }
+
+ CleanupStack::PopAndDestroy(aAttrValue);
+ }
+
+void CBtServicesEng::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt /* aTotalRecordsCount */)
+ {
+ if ((aError == KErrNone) || (aError == KErrEof))
+ {
+ TRAPD(err, DoNextRecordRequestCompleteL(aHandle, aError));
+ if (err != KErrNone)
+ {
+ aError = err;
+ }
+ }
+ if (aError != KErrNone && aError != KErrEof)
+ {
+// iView->GetEikonEnv()->BusyMsgCancel();
+ SdpCompletedWithError(aError);
+ }
+
+ //if aError == KErrEof, that means no more records to read
+
+ }
+
+void CBtServicesEng::DoNextRecordRequestCompleteL(TSdpServRecordHandle aHandle, TInt aError)
+ {
+ if (aError == KErrNone)
+ {
+ ReportMessage(1, _L("Record Handle found 0x%X \r\n"), aHandle );
+
+ CServiceRecordItem* pItem = new CServiceRecordItem;
+ pItem->iHandle = aHandle;
+ iRecordArray.Append(pItem);
+ iSdpAgent->NextRecordRequestL();
+ }
+ else if (aError == KErrEof)
+ //no more records, now query service name for each record found
+ {
+ iHandleCounter = 0;
+ iCurrentAttributeRequest = EGettingNamesOnly;
+
+ //report status
+ TInt RecordCnt = iRecordArray.Count();
+ ReportMessage(1, _L("%d records found, querying service name...\r\n"), RecordCnt);
+ GetServiceNamesL();
+ }
+ }
+
+void CBtServicesEng::SdpCompletedWithError(const TInt aError)
+ {
+
+ HBufC* buf = HBufC::NewLC(KMaxDescriptorLength);
+ TPtr errorText = buf->Des();
+ AppendErrorMessage(aError,errorText);
+// TGulAlignment position(EHRightVTop);
+// iView->GetEikonEnv()->InfoMsgWithAlignmentAndDuration(position,errorText,KErrorMsgDuration);
+ ReportMessage(0, *buf);
+
+ CleanupStack::PopAndDestroy();
+ iSdpAgent->Cancel();
+// iView->DimRefreshButton(EFalse);
+// iView->DimCancelButton(ETrue);
+ if (iView)
+ iView->AsyncCompleted();
+
+ }
+
+void CBtServicesEng::AppendErrorMessage(const TInt aError, TDes& aBuf) const
+ {
+ for (TInt i = 0; i < iErrorCodes.Count(); i++)
+ {
+ if (iErrorCodes[i] == aError)
+ {
+ aBuf.Append(*(iErrorMessages[i]));
+ return;
+ }
+ }
+ _LIT(KErrorTextOther, "Error: ");
+ aBuf.Append(KErrorTextOther);
+ aBuf.AppendNum(aError);
+ }
+
+void CBtServicesEng::Panic(TBtPanicCode aPanicCode)
+ {
+ _LIT(KBtPanicText, "BTSU::Panic ");
+ User::Panic(KBtPanicText, aPanicCode);
+ }
+
+void CBtServicesEng::ReleaseModel()
+ {
+ // Do nothing, list box does not own us
+ }
+
+//static
+//search the Uuid value, and return a text string of its name
+TPtrC CBtServicesEng::UUIDToString(TUint32 aUuidValue)
+ {
+ //read the available filter UUID and corresponding text
+ TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
+ TInt i;
+ for (i = 0; i < arrayCount; i++)
+ {
+ TUint32 uuid = UuidAsArray[i].uuid;
+ if (uuid == aUuidValue)
+ return (UuidAsArray[i].txt);
+ }
+ return _L("");
+ }
+
+//static
+//search through the value, and return the UUID value if there is one match
+//aUuidValue: [out] the found result
+TBool CBtServicesEng::StringToUUID(TDesC& aString, TUint32& aUuidValue)
+ {
+ //read the available filter UUID and corresponding text
+ TInt arrayCount = sizeof(UuidAsArray) / sizeof(TUUidPair);
+ TInt i;
+ for (i = 0; i < arrayCount; i++)
+ {
+ TUint32 uuid = UuidAsArray[i].uuid;
+ if (aString == UuidAsArray[i].txt)
+ {
+ aUuidValue = uuid;
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+
+///////////////////////////////////////
+// CBtAttributeBuilder functions
+///////////////////////////////////////
+
+CBtAttributeBuilder* CBtAttributeBuilder::NewL(CBtServicesEng& aEngine)
+ {
+ CBtAttributeBuilder* self = new(ELeave) CBtAttributeBuilder(aEngine);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CBtAttributeBuilder::CBtAttributeBuilder(CBtServicesEng& aEngine)
+: iEngine(aEngine)
+ {
+ }
+
+void CBtAttributeBuilder::ConstructL()
+ {
+/*
+ HBufC8* buf = CEikonEnv::Static()->AllocReadResourceAsDes8LC(R_ATTR_ID_MNEMONICS);
+
+ TResourceReader res;
+ res.SetBuffer(buf);
+
+ TInt arrayCount = res.ReadInt16();
+ for (TInt i = 0; i < arrayCount; i++)
+ {
+ TUint attrID = res.ReadUint32();
+ iAttrIDs.Append(attrID);
+ HBufC* mnemonic = res.ReadHBufCL();
+ iAttrMnemonics.Append(mnemonic);
+ }
+ CleanupStack::PopAndDestroy(); // buf
+*/
+ }
+
+CBtAttributeBuilder::~CBtAttributeBuilder()
+ {
+ iAttrIDs.Close();
+ iAttrMnemonics.ResetAndDestroy();
+ iAttrMnemonics.Close();
+ }
+
+void CBtAttributeBuilder::Reset()
+ {
+ iIndentation = 0;
+ iCurrentLine.Zero();
+ }
+
+void CBtAttributeBuilder::SetHandle(TSdpServRecordHandle aHandle)
+ {
+ iHandle = aHandle;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildUnknownL(TUint8 aType, TUint8 /* aSizeDesc */, const TDesC8& /* aData */)
+ {
+ if (iStatus == EExpectingAttrID)
+ {
+ _LIT(KErrorText,"**Error: Unexpected UNKNOWN");
+ iCurrentLine.Append(KErrorText);
+ }
+ else
+ {
+ _LIT(KTextUnknown,"UNKNOWN");
+ iCurrentLine.Append(KTextUnknown);
+ iCurrentLine.AppendNum((TInt) aType);
+ }
+ LineFinishedL();
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildNilL()
+ {
+ if (iStatus == EExpectingAttrID)
+ {
+ _LIT(KErrorText,"**Error: Unexpected NIL");
+ iCurrentLine.Append(KErrorText);
+ }
+ else
+ {
+ _LIT(KTextNULL,"NULL");
+ iCurrentLine.Append(KTextNULL);
+ }
+ LineFinishedL();
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildUintL(const TDesC8& aUint)
+ {
+
+ if (iStatus == EExpectingAttrValue)
+ {
+ iCurrentLine.Append(KTextHexPrefix);
+ for (TInt i = 0; i < aUint.Length(); i++)
+ {
+ iCurrentLine.AppendNumFixedWidth(aUint[i], EHex,2);
+ }
+ LineFinishedL();
+ }
+ else if (iStatus == EExpectingAttrID)
+ {
+ TUint value = 0;
+ for (TInt i = 0; i < aUint.Length(); i++)
+ {
+ value <<= 8;
+ value += aUint[i];
+ }
+ AppendAttrMnemonic(iCurrentLine,value);
+ iStatus = EExpectingAttrValue;
+ }
+
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildIntL(const TDesC8& aInt)
+ {
+ if (iStatus == EExpectingAttrID)
+ {
+ _LIT(KErrorText,"**Error: Unexpected Int");
+ iCurrentLine.Append(KErrorText);
+ }
+ else
+ {
+ iCurrentLine.Append(KTextHexPrefix);
+ for (TInt i = 0; i < aInt.Length(); i++)
+ {
+ iCurrentLine.AppendNumFixedWidth(aInt[i], EHex,2);
+ }
+ }
+ LineFinishedL();
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildUUIDL(const TUUID& aUUID)
+ {
+ if (iStatus == EExpectingAttrID)
+ {
+ _LIT(KErrorText,"**Error: Unexpected UUID");
+ iCurrentLine.Append(KErrorText);
+ }
+ else
+ {
+ iEngine.AppendUUIDText(iCurrentLine,aUUID);
+ }
+ LineFinishedL();
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildBooleanL(TBool aBool)
+ {
+ if (iStatus == EExpectingAttrID)
+ {
+ _LIT(KErrorText,"**Error: Unexpected Boolean");
+ iCurrentLine.Append(KErrorText);
+ }
+ else
+ {
+ if (aBool)
+ {
+ _LIT(KTextTrue,"TRUE");
+ iCurrentLine.Append(KTextTrue);
+ }
+ else
+ {
+ _LIT(KTextFalse,"FALSE");
+ iCurrentLine.Append(KTextFalse);
+ }
+ }
+ LineFinishedL();
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildStringL(const TDesC8& aString)
+ {
+ if (iStatus == EExpectingAttrID)
+ {
+ _LIT(KErrorText,"**Error: Unexpected String");
+ iCurrentLine.Append(KErrorText);
+ }
+ else
+ {
+ TBuf16<KMaxDescriptorLength> unicode;
+ CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode,aString);
+ if (unicode[unicode.Length() - 1] == NULL)
+ {
+ unicode.Delete(unicode.Length() - 1, 1); // remove NULL-termination
+ }
+ iCurrentLine.Append(unicode);
+ }
+ LineFinishedL();
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildDESL()
+ {
+ if (iIndentation == 1)
+ {
+ iEngine.AddAttributeLineL(iCurrentLine);
+ }
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildDEAL()
+ {
+ _LIT(KTextDEAL,"Data Element Alternate List");
+ iCurrentLine.Append(KTextDEAL);
+ iEngine.AddAttributeLineL(iCurrentLine);
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::StartListL()
+ {
+ iIndentation++;
+ iCurrentLine.Zero();
+ __ASSERT_ALWAYS(iIndentation > 0, CBtServicesEng::Panic(EBtIndentationZeroInStartList));
+ iCurrentLine.AppendFill(' ', (iIndentation - 1) * KIndentationFactor);
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::EndListL()
+ {
+ _LIT(KTextEndListDashes,"--------");
+ iCurrentLine.Append(KTextEndListDashes);
+ iEngine.AddAttributeLineL(iCurrentLine);
+ iIndentation--;
+ iCurrentLine.Zero();
+ if (iIndentation)
+ {
+ iCurrentLine.AppendFill(' ', (iIndentation - 1) * KIndentationFactor); // in this case indentation has already been checked to be greater than zero
+ }
+ if (iIndentation == 1)
+ {
+ iStatus = EExpectingAttrID;
+ }
+ return this;
+ }
+
+MSdpElementBuilder* CBtAttributeBuilder::BuildURLL(const TDesC8& aURL)
+ {
+ TBuf16<KMaxDescriptorLength> unicode;
+ CnvUtfConverter::ConvertToUnicodeFromUtf8(unicode,aURL);
+ iCurrentLine.Append(unicode);
+ LineFinishedL();
+ return this;
+ }
+
+void CBtAttributeBuilder::AppendAttrMnemonic(TDes& aBuf, TUint aAttrID) const
+ {
+ for (TInt i = 0; i < iAttrIDs.Count(); i++)
+ {
+ if (iAttrIDs[i] == aAttrID)
+ {
+ aBuf.Append(*(iAttrMnemonics[i]));
+ return;
+ }
+ }
+ if (aAttrID == 0x0200 && iHandle == 0)
+ {
+ _LIT(KVersionNoPrefix,"VersionNo.: ");
+ aBuf.Append(KVersionNoPrefix);
+ }
+ else if (aAttrID == 0x0201 && iHandle == 0)
+ {
+ _LIT(KDatabaseStatePrefix,"DatabaseState: ");
+ aBuf.Append(KDatabaseStatePrefix);
+ }
+ else
+ {
+ _LIT(KTextAttrIDHex,"AttrID 0x");
+ aBuf.Append(KTextAttrIDHex);
+ aBuf.AppendNum(aAttrID,EHex);
+ _LIT(KTextColonSpace,": ");
+ aBuf.Append(KTextColonSpace);
+ }
+ }
+
+void CBtAttributeBuilder::LineFinishedL()
+ {
+ iEngine.AddAttributeLineL(iCurrentLine);
+ iCurrentLine.Zero();
+ __ASSERT_ALWAYS(iIndentation > 0, CBtServicesEng::Panic(EBtIndentationZeroInLineFinished));
+ iCurrentLine.AppendFill(' ', (iIndentation - 1) * KIndentationFactor);
+ if (iIndentation == 1)
+ {
+ iStatus = EExpectingAttrID;
+ }
+ }