bluetoothengine/bteng/src/btengsdpdbhandler.cpp
changeset 0 f63038272f30
--- /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
+    }