diff -r 000000000000 -r f63038272f30 bluetoothengine/bteng/src/btengsdpdbhandler.cpp --- /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 +#include +#include +#include +#include + +#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 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 buf( aReader.ReadUint16() ); + if( iVendorId && aAttrId == EVendorID ) + { + buf = TSdpIntBuf( iVendorId ); + iVendorId = 0; // Reset vendor ID + } + if( iProductId && aAttrId == EProductID ) + { + buf = TSdpIntBuf( iProductId ); + iProductId = 0; // Reset vendor ID + } + aAttrVal = CSdpAttrValueUint::NewUintL( buf ); + } + break; + case EElemTypeLong: + { + TSdpIntBuf 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 buf( aReader.ReadUint8() ); + if( iChannel && aAttrId == EProtocolDescriptorList ) + { + buf = TSdpIntBuf( 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 + }