--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bteng/src/btengsdpdbhandler.cpp Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,398 @@
+/*
+* Copyright (c) 2006 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: Helper class for SDP database management.
+*
+*/
+
+
+
+#include <btsdp.h>
+#include <btengsdp.rsg>
+#include <barsread.h>
+#include <barsc.h>
+#include <data_caging_path_literals.hrh>
+
+#include "btengsdpdbhandler.h"
+#include "btengsdp.hrh"
+#include "debug.h"
+
+_LIT( KBTEngSdpResourceFile, "btengsdp.rsc");
+_LIT( KDriveZ, "z:");
+_LIT8( KHex, "0x");
+const TInt KMaxServiceDesLength = 64;
+const TInt KNumberOfChars = 8;
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor
+// ---------------------------------------------------------------------------
+//
+CBTEngSdpDbHandler::CBTEngSdpDbHandler()
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd-phase constructor
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::ConstructL()
+ {
+ TRACE_FUNC_ENTRY
+ User::LeaveIfError( iSdp.Connect() );
+ User::LeaveIfError( iDb.Open( iSdp ) );
+ TRACE_FUNC_EXIT
+ }
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CBTEngSdpDbHandler* CBTEngSdpDbHandler::NewL()
+ {
+ CBTEngSdpDbHandler* self = new( ELeave ) CBTEngSdpDbHandler();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CBTEngSdpDbHandler::~CBTEngSdpDbHandler()
+ {
+ iDb.Close(); // This should have no effect if the handle is null.
+ iSdp.Close();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Register SDP record for the specified service containing the specified
+// protocol channel in the protocol descriptor list.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::RegisterSdpRecordL( const TUUID& aService,
+ TInt aChannel, TSdpServRecordHandle& aHandle )
+ {
+ TRACE_FUNC_ARG( ( _L( "channel: %d" ), aChannel ) )
+ iChannel = aChannel;
+ RegisterSdpRecordL( aService, aHandle );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Register SDP record for the specified service containing the specified
+// VendorID and ProductID for the relevant attributes (mainly for DI profile).
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::RegisterSdpRecordL( const TUUID& aService,
+ TInt aVendorId, TInt aProductId, TSdpServRecordHandle& aHandle )
+ {
+ TRACE_FUNC_ARG( ( _L( "vendor ID: %d: product ID: %d" ),
+ aVendorId, aProductId ) )
+ iVendorId = aVendorId;
+ iProductId = aProductId;
+ RegisterSdpRecordL( aService, aHandle );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Register SDP record for the specified service.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::RegisterSdpRecordL( const TUUID& aService,
+ TSdpServRecordHandle& aHandle )
+ {
+ TResourceReader reader;
+ HBufC8* record = NULL;
+ TBuf8<KMaxServiceDesLength> serviceBuf( KHex );
+ TPtrC8 ptr = aService.ShortestForm();
+ if( ptr.Length() <= 4 )
+ {
+ // Short form UUID (16 or 32 bytes).
+ TUint service = SdpUtil::GetUint( ptr );
+ serviceBuf.AppendNum( service, EHex );
+ }
+ else
+ {
+ // Long form UUID (128 bytes).
+ TUint64 serviceLo = 0;
+ TUint64 serviceHi = 0;
+ SdpUtil::GetUint128( ptr, serviceLo, serviceHi );
+ // The numbers need to have a fixed width (including leading zeros)
+ // and AppendNumFixedWidth is only avaliable with TUint32.
+ serviceBuf.AppendNumFixedWidth( I64HIGH(serviceHi), EHex, KNumberOfChars );
+ serviceBuf.AppendNumFixedWidth( I64LOW(serviceHi), EHex, KNumberOfChars );
+ serviceBuf.AppendNumFixedWidth( I64HIGH(serviceLo), EHex, KNumberOfChars );
+ serviceBuf.AppendNumFixedWidth( I64LOW(serviceLo), EHex, KNumberOfChars );
+ }
+
+ // Read the record from resource file.
+ ReadRecordResourceL( serviceBuf, reader, record );
+ CleanupStack::PushL( record );
+
+ iDb.CreateServiceRecordL( TUUID( 0 ), aHandle );
+ CSdpAttrValue* attrVal = NULL;
+ TUint attrCount = reader.ReadUint16();
+ for( TInt i = 0; i < attrCount; i++ )
+ {
+ TUint16 attrId = reader.ReadUint16();
+ BuildAttributeLC( attrVal, reader, attrId );
+ if( attrVal )
+ {
+ iDb.UpdateAttributeL( aHandle, attrId, *attrVal );
+ CleanupStack::PopAndDestroy( attrVal );
+ attrVal = NULL;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( record );
+ TRACE_FUNC_EXIT
+ }
+
+
+// ---------------------------------------------------------------------------
+// Delete the SDP record for the specified record handle.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::DeleteSdpRecordL( const TSdpServRecordHandle aHandle )
+ {
+ TRACE_FUNC_ENTRY
+ if( aHandle )
+ {
+ iDb.DeleteRecordL( aHandle );
+ }
+ else
+ {
+ User::Leave( KErrBadHandle );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+
+// ---------------------------------------------------------------------------
+// Build an SDP attribute.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::BuildAttributeLC( CSdpAttrValue*& aAttrVal,
+ TResourceReader& aReader, TInt aAttrId )
+ {
+ // Read the attribute type and ID
+ TUint attrType = aReader.ReadUint8();
+ if( attrType == EElemTypeList )
+ {
+ BuildAttrDesLC( aAttrVal, aReader, aAttrId );
+ }
+ else
+ {
+ BuildAttrValueLC( aAttrVal, aReader, attrType, aAttrId );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Build an SDP attribute for a concrete attribute type.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::BuildAttrValueLC( CSdpAttrValue*& aAttrVal,
+ TResourceReader& aReader, TUint aAttrType, TInt aAttrId )
+ {
+ TRACE_FUNC_ENTRY
+ switch( aAttrType )
+ {
+ case EElemTypeWord:
+ {
+ TSdpIntBuf<TUint16> buf( aReader.ReadUint16() );
+ if( iVendorId && aAttrId == EVendorID )
+ {
+ buf = TSdpIntBuf<TUint16>( iVendorId );
+ iVendorId = 0; // Reset vendor ID
+ }
+ if( iProductId && aAttrId == EProductID )
+ {
+ buf = TSdpIntBuf<TUint16>( iProductId );
+ iProductId = 0; // Reset vendor ID
+ }
+ aAttrVal = CSdpAttrValueUint::NewUintL( buf );
+ }
+ break;
+ case EElemTypeLong:
+ {
+ TSdpIntBuf<TUint32> buf( aReader.ReadUint32() );
+ aAttrVal = CSdpAttrValueUint::NewUintL( buf );
+ }
+ break;
+ case EElemTypeUUID:
+ {
+ TUUID uuid( aReader.ReadUint32() );
+ aAttrVal = CSdpAttrValueUUID::NewUUIDL( uuid );
+ }
+ break;
+ case EElemTypeUUID128:
+ {
+ TUUID uuid;
+ uuid.SetL( aReader.ReadTPtrC8() );
+ aAttrVal = CSdpAttrValueUUID::NewUUIDL( uuid );
+ }
+ break;
+ case EElemTypeText:
+ {
+ TPtrC8 ptr = aReader.ReadTPtrC8();
+ aAttrVal = CSdpAttrValueString::NewStringL( ptr );
+ }
+ break;
+ case EElemTypeByte:
+ {
+ TSdpIntBuf<TUint8> buf( aReader.ReadUint8() );
+ if( iChannel && aAttrId == EProtocolDescriptorList )
+ {
+ buf = TSdpIntBuf<TUint8>( iChannel );
+ iChannel = 0; // Reset channel number
+ }
+ aAttrVal = CSdpAttrValueUint::NewUintL( buf );
+ }
+ break;
+ case EElemTypeList:
+ {
+ BuildAttrDesLC( aAttrVal, aReader, aAttrId );
+ }
+ break;
+ case EElemTypeLong64:
+ {
+ TPtrC8 ptr = aReader.ReadTPtrC8();
+ aAttrVal = CSdpAttrValueUint::NewUintL(ptr);
+ break;
+ }
+ case EElemTypeBool:
+ {
+ TBool boolVal = (TBool) aReader.ReadUint8();
+ aAttrVal = CSdpAttrValueBoolean::NewBoolL( boolVal );
+ break;
+ }
+ case EElemTypeLink:
+ default:
+ break;
+ }
+ if( aAttrVal )
+ {
+ CleanupStack::PushL( aAttrVal );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Build an SDP Data Elelement Sequence attribute (i.e. a sequence of
+// concrete attributes or lists).
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::BuildAttrDesLC( CSdpAttrValue*& aAttrVal,
+ TResourceReader& aReader, TInt aAttrId )
+ {
+ TRACE_FUNC_ENTRY
+ TUint elementCount = aReader.ReadUint16();
+ MSdpElementBuilder* builder = NULL;
+ if( !aAttrVal )
+ {
+ // This is the first element of the attribute.
+ aAttrVal = CSdpAttrValueDES::NewDESL( NULL );
+ builder = ( (CSdpAttrValueDES*) aAttrVal )->StartListL();
+ }
+ else
+ {
+ // This is a nested DES. This means that the parent element is
+ // also a DES. Append this DES to the parent.
+ builder = ( (CSdpAttrValueDES*) aAttrVal )->BuildDESL();
+ builder = builder->StartListL();
+ }
+
+ CleanupStack::PushL( aAttrVal );
+ while( elementCount > 0 )
+ {
+ // Build the list; this can result in another call to this function
+ // to build a nested list.
+ CSdpAttrValue* element = NULL;
+ BuildAttributeLC( element, aReader, aAttrId );
+ if( element )
+ {
+ CleanupStack::Pop( element ); // Ownership will be passed to DES.
+ CSdpAttrValueDES* list = (CSdpAttrValueDES*) builder;
+ list->AppendValueL( element );
+ }
+ elementCount--;
+ }
+ builder = builder->EndListL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Read the service record from the resource file containing all BT Engine's
+// service record definitions.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSdpDbHandler::ReadRecordResourceL( const TDesC8& aService,
+ TResourceReader& aReader, HBufC8*& aRecordBuf )
+ {
+ TRACE_FUNC_ENTRY
+ // Find and open resource file
+ TFileName fileName( KDriveZ );
+ fileName.Append( KDC_RESOURCE_FILES_DIR );
+ fileName.Append( KBTEngSdpResourceFile );
+ RFs fsSession;
+ User::LeaveIfError( fsSession.Connect() );
+ CleanupClosePushL( fsSession );
+ RResourceFile resourceFile;
+ resourceFile.OpenL( fsSession, fileName );
+ CleanupClosePushL( resourceFile );
+
+ // Read the array containing the mappings of UUID to resource definitions.
+ HBufC8* buf = resourceFile.AllocReadLC( R_SERVICE_RECORD_LIST );
+ aReader.SetBuffer( buf );
+ CDesC8ArrayFlat* serviceIdArray = aReader.ReadDesC8ArrayL();
+ CleanupStack::PushL( serviceIdArray );
+
+ // Find the requested service record.
+ TInt pos = KErrNotFound;
+ for( TInt i = 0; i < serviceIdArray->Count(); i++ )
+ {
+ // CompareF is case insensitive comparison
+ if( aService.CompareF( (*serviceIdArray)[i] ) == 0 )
+ {
+ pos = i;
+ break;
+ }
+ }
+ if( pos < 0 )
+ {
+ // The record is not found from the resource file.
+ User::Leave( pos );
+ }
+
+ // Read the service record resource in a buffer to pass back.
+ aReader.Advance( 2 * pos + 2 ); // 16bit LINK
+ TUint resourceId = aReader.ReadUint16();
+ aRecordBuf = resourceFile.AllocReadL( resourceId );
+ aReader.SetBuffer( aRecordBuf );
+
+ CleanupStack::PopAndDestroy( serviceIdArray );
+ CleanupStack::PopAndDestroy( buf );
+ CleanupStack::PopAndDestroy( &resourceFile );
+ CleanupStack::PopAndDestroy( &fsSession );
+ TRACE_FUNC_EXIT
+ }