bluetoothmgmt/bluetoothclientlib/btlib/eir.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothmgmt/bluetoothclientlib/btlib/eir.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,357 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 0
+// 
+//
+
+/**
+ @publishedAll
+ @released
+ @file
+*/
+
+#include <utf.h>
+#include <bluetooth/logger.h>
+#include "bttypes.h" 
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_BTLIB);
+#endif
+
+void Panic(TEirWrapperPanics aCode)
+	{
+	User::Panic(KEirWrapperPanicName, aCode);
+	}
+
+
+// Size of 16/128 bit UUIDs in bytes
+const TUint8 KSizeOf16BitUUID = 2;
+const TUint8 KSizeOf128BitUUID = 16;
+
+// Size of TxPowerLevel data in bytes
+#define KSizeOfTxPowerLevelData 1
+
+
+/** 
+ Constructs an TBluetoothNameRecordWrapper object from an TNameRecord object.
+ The reference of aNameRecord is stored in the object.
+ This will contain sensible data only if KHostResEir was used in the Inquiry
+ @param aNameRecord for Device Name and Extended Inquiry Response 
+ */
+EXPORT_C TBluetoothNameRecordWrapper::TBluetoothNameRecordWrapper(const TNameRecord& aNameRecord)
+: iEirCodec(aNameRecord)
+	{
+	LOG_FUNC
+	}
+
+/**
+ Obtain the Device Name from inquiry response. This may be a complete or partial name depending on what is available.
+ @param aName is where the Device Name converted into Unicode format is to be stored
+ @param aIsComplete indicates whether the name is complete or partial.
+ @return an error code (KErrNotFound means no name is present in this EIR packet)
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetDeviceName(TDes16& aName, TBool& aIsComplete) const
+	{
+	LOG_FUNC
+	TPtrC8 name;
+	aIsComplete = EFalse;
+	TInt error = iEirCodec.GetDeviceName(name);
+	if(error >= KErrNone)
+		{
+		if(error == EDataComplete)
+
+			{
+			aIsComplete = ETrue;
+			}
+		}
+		
+	if(error >= KErrNone)
+		{
+		error = CnvUtfConverter::ConvertToUnicodeFromUtf8(aName, name);
+		}
+		
+	// in case of an error from GetData or conversion, return null name and mark it's partial
+	if(error != KErrNone)
+		{
+		// indicate client the name is partial to invite a name request.
+		aIsComplete = EFalse;
+		aName.Zero();
+		}
+
+	return error;
+	}
+
+/**
+ Retrieve the full list of UUIDs contained in this EIR. Please note that all types of UUID will be merged together in the single array.
+ @param aUuidContainer CUuidContainer object where all UUIDs found are to be stored, including 16, 32 and 128 bit uuids
+ @return an error code
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetServiceClassUuids(RExtendedInquiryResponseUUIDContainer& aEIRContainer) const
+	{
+	LOG_FUNC
+	TPtrC8 uuids;
+	TInt error = KErrNone;
+	// 16 bit UUID
+	error = iEirCodec.GetData(EEirUUID16Complete, uuids);
+	if(error != KErrNone)
+		{
+		// can't find complete tag, try partial one
+		error = iEirCodec.GetData(EEirUUID16Partial, uuids);
+		// find partial tag, set uuid
+		// or we can't find either parital or complete tag, no 16 bit uuid exists in this eir packet
+		// set complete to partial, this indicates the client there might be uuids in sdp database,
+		// so client might want to do a sdp service discovery.
+		aEIRContainer.SetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID16, EFalse);
+		if(error == KErrNone)
+			{
+			// Add the uuid into the container
+			error = AddUuids16(aEIRContainer, uuids);
+			}
+		else
+			{
+			// can't find either parital or complete tag, no 16 bit uuid exists in this eir packet
+			// set complete to partial, this indicates the client there might be uuids in sdp database,
+			// so client might want to do a sdp service discovery.
+			aEIRContainer.SetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID16, EFalse);
+			error = KErrNone;
+			}
+		}
+	else
+		{
+		// find complete tag, set uuid
+		aEIRContainer.SetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID16, ETrue);
+		// Add the uuid into the container
+		error = AddUuids16(aEIRContainer, uuids);
+		}
+
+	// 128 bit UUID
+	if(error == KErrNone)
+		{
+		// There hasn't been any error in previous adding 16 bit UUID action
+		error = iEirCodec.GetData(EEirUUID128Complete, uuids);
+		if(error != KErrNone)
+			{
+			// can't find complete tag, try partial one
+			error = iEirCodec.GetData(EEirUUID128Partial, uuids);
+			// find partial tag, set uuid
+			// or we can't find either parital or complete tag, no 128 bit uuid exists in this eir packet.
+			// set complete to partial, this indicates the client there might be uuids in sdp database,
+			// so client might want to do a sdp service discovery.
+			aEIRContainer.SetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID128, EFalse);
+			if(error == KErrNone)
+				{
+				// Add the uuid into the container
+				error = AddUuids128(aEIRContainer, uuids);
+				}
+			else
+				{
+				// can't find either parital or complete tag, no 128 bit uuid exists in this eir packet.
+				// set complete to partial, this indicates the client there might be uuids in sdp database,
+				// so client might want to do a sdp service discovery.
+				aEIRContainer.SetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID128, EFalse);
+				error = KErrNone;
+				}
+			}
+		else
+			{
+			// find complete tag, set uuid
+			aEIRContainer.SetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID128, ETrue);
+			// Add the uuid into the container
+			error = AddUuids128(aEIRContainer, uuids);
+			}
+		}
+
+	return error;
+	}
+
+/**
+ Retrieve the vendor specific data from this EIR. 
+ @param aDest Array where the vendor specific data is to be stored
+ @return An error code (KErrNotFound means no Manufacturer Specific Data is present in this EIR packet)
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetVendorSpecificData(TDes8& aVendorSpecificData) const
+	{
+	LOG_FUNC
+	TPtrC8 vendorSpecificData;
+	TInt error = iEirCodec.GetData(EEirVendorSpecific, vendorSpecificData);
+	if(error != KErrNone)
+		{
+		vendorSpecificData.Set(KNullDesC8());
+		}
+	else
+		{
+		aVendorSpecificData.Copy(vendorSpecificData);
+		}
+	return error;
+	}
+
+/**
+ Retrieve the Transmission Power Level from EIR. 
+ @param aTxPowerLevel where the Transmission Power Level from this EIR is to be stored
+ @return an error code (KErrNotFound means no Transmission Power Level is present in this EIR packet)
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetTxPowerLevel(TInt8& aTxPowerLevel) const
+	{
+	LOG_FUNC
+	TPtrC8 txPowerLevelPtr;
+	TInt error = iEirCodec.GetData(EEirTxPowerLevel, txPowerLevelPtr);
+	// if txPowerLevelPtr is longer than 1 byte, error KErrCorrupt
+	if(error == KErrNone && (txPowerLevelPtr.Length() != KSizeOfTxPowerLevelData))
+		{
+		error = KErrCorrupt;
+		}
+	else if(error == KErrNone && (txPowerLevelPtr.Length() == KSizeOfTxPowerLevelData))
+		{
+		aTxPowerLevel = static_cast <TInt8>(txPowerLevelPtr[0]);
+		}
+	else
+		{
+		aTxPowerLevel = 0;
+		}
+	return error;
+	}
+
+/**
+ Obtain the Flags from EIR if present. 
+ @param aFlags a descriptor where the Flags is to be stored
+ @return an error code (KErrNotFound means no Flags is present in this EIR packet)
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetFlags(TDes8& aFlags) const
+	{
+	LOG_FUNC
+	TPtrC8 flags;
+	TInt error = iEirCodec.GetData(EEirFlags, flags);
+	if(error != KErrNone)
+		{
+		flags.Set(KNullDesC8());
+		}
+	else
+		{
+		aFlags.Copy(flags);
+		error = KErrNone;
+		}
+	return error;
+	}
+
+/**
+ Obtain the length for Device Name in EIR if present. 
+ This function should be called before GetDeviceName() to initialize size of the buffer,
+ whose reference will be passed into GetDeviceName() as an argument.
+ @return the length of Device Name
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetDeviceNameLength() const
+	{
+	LOG_FUNC
+	TPtrC8 name;
+	TInt ret = iEirCodec.GetDeviceName(name);
+	if(ret >= KErrNone)
+		{
+		ret = name.Length();
+		}
+	else
+		{
+		ret = 0;
+		}
+	return  ret;
+	}
+
+/**
+ Obtain the length for Manufacturer Specific Data in EIR if present. 
+ This function should be called before GetVendorSpecificData() to initialize size of the buffer,
+ whose reference will be passed into GetVendorSpecificData() as an argument.
+ @return the length of Manufacturer Specific Data
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetVendorSpecificDataLength() const
+	{
+	LOG_FUNC
+	TPtrC8 vendorSpecificData;
+	TInt ret = iEirCodec.GetData(EEirVendorSpecific, vendorSpecificData);
+	if(ret == KErrNone)
+		{
+		ret = vendorSpecificData.Length();
+		}
+	else
+		{
+		ret = 0;
+		}
+	return ret;
+	}
+
+/**
+ Obtain the length for Flags in EIR if present. 
+ This function should be called before GetFlags() to initialize size of the buffer,
+ whose reference will be passed into GetFlags() as an argument.
+ @return the length of Flags
+ */
+EXPORT_C TInt TBluetoothNameRecordWrapper::GetFlagsLength() const
+	{
+	LOG_FUNC
+	TPtrC8 flags;
+	TInt ret = iEirCodec.GetData(EEirFlags, flags);
+	if(ret == KErrNone)
+		{
+		ret = flags.Length();
+		}
+	else
+		{
+		ret = 0;
+		}
+	return ret;
+	}
+
+TInt TBluetoothNameRecordWrapper::AddUuids16(RExtendedInquiryResponseUUIDContainer& aEIRContainer, TPtrC8& aUuids) const
+	{
+	TInt error = KErrNone;
+	TInt length = aUuids.Length() / KSizeOf16BitUUID;
+	TUUID uuid;
+	
+	for(TInt i = 0; i < length; i++)
+		{
+		__ASSERT_DEBUG(((aUuids.Length() - i*KSizeOf16BitUUID)% KSizeOf16BitUUID) == 0, Panic(EEirBadUuid16List));
+		TRAP(error, uuid.SetFromLittleEndianL(aUuids.Mid(i*KSizeOf16BitUUID, KSizeOf16BitUUID)));
+		if(error == KErrNone)
+			{
+			error = aEIRContainer.UUIDs().Add(uuid);
+			}
+		else
+			{
+			break;
+			}
+		}
+	
+	return error;
+	}
+
+TInt TBluetoothNameRecordWrapper::AddUuids128(RExtendedInquiryResponseUUIDContainer& aEIRContainer, TPtrC8& aUuids) const
+	{
+	TInt error = KErrNone;
+	TInt length = aUuids.Length() / KSizeOf128BitUUID;
+	TUUID uuid;
+	
+	for(TInt i = 0; i < length; i++)
+		{
+		__ASSERT_DEBUG(((aUuids.Length() - i*KSizeOf128BitUUID)% KSizeOf128BitUUID) == 0, Panic(EEirBadUuid128List));
+		TRAP(error, uuid.SetFromLittleEndianL(aUuids.Mid(i*KSizeOf128BitUUID, KSizeOf128BitUUID)));
+		if(error == KErrNone)
+			{
+			error = aEIRContainer.UUIDs().Add(uuid);
+			}
+		else
+			{
+			break;
+			}
+		}
+	
+	return error;
+	}