bluetooth/btstack/common/codman.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/common/codman.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,228 @@
+// Copyright (c) 2005-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:
+// Class of Device (CoD) Service Manager.
+// Manages the Service bit settings in the composite CoD word.
+// The CoD is a 24 bit word, of which the upper eleven bits describe the Service class 
+// profiles a Bluetooth device supports. Since these Services can be offered by transitory
+// applications, we need to provide mechanisms that allow applications to set the Service
+// bits accordingly. Bits 2 to 12 are the Service class and these are sub-divided into major 
+// and minor classifications. Bits 0 and 1 are currently always zero.
+// 23                  13 12      8  7         2 1 0
+// |<--- Service class -->|<--- Device class --->
+// [ . . . . . . . ][ . . . . . . . ][ . . . . . .0.0]
+// The Services are identified by the following table.
+// 23        13	
+// v         v
+// Service LimitedDiscoverableMode     00000000001 ......this is not used
+// reserved                            00000000010
+// reserved                            00000000100
+// Service Positioning                 00000001000
+// Service Networking                  00000010000
+// Service Rendering                   00000100000
+// Service Capturing                   00001000000
+// Service ObjectTransfer              00010000000
+// Service Audio                       00100000000
+// Service Telephony                   01000000000
+// Service Information                 10000000000
+// Because the Symbian OS handles data in 32bit and 16bit sizes, the CoD word is always
+// transported using an unsigned 32bit type. The MS byte is ignored. 
+// In order to correctly process the Service bits, they are right-shifted 13 bit positions
+// and then they are managed in a 16 bit type.
+// Its feasible that multiple applications will offer the same service, therefore the 
+// CoD Service Manager must keep a separate count (iServRefCount[]) of each Service bit set 
+// and the bit is only removed from the CoD when the counter is decremented to zero.
+// The practical implementation is that the CSM privately owns an array of eleven counters.
+// Each SAP has an iCodServiceBits (16bit type), inherited from the base class which is a
+// record of the Service bits set by that SAP. So the SAPs are know their individual Service
+// bit settings and the CSM knows the totals.
+// As a further precaution against mis-use, each SAP will be allowed one shot at setting
+// the bits. This is controlled by assigning the msb (of iCodServiceBits) as a flag which
+// will be TRUE when the Service bit(s) have been set. This is defined as KBTCodBitsRegdFlag.
+// The action of the Publish and Suscribe interface (P&S) for writing the CoD remains, but is 
+// now sub-ordinate to the SAP managed Service bits. The P&S execution path has been diverted
+// from Linkmgr to the CSM. The P&S sets the CoD Device class bits as before, but its
+// Service bit(s) are ORed with the SAP settings before writing the CoD.   
+// 
+//
+
+
+#include <bluetooth/logger.h>
+#include "codman.h"
+#include "linkmgr.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_IN_CONN_LISTENER);
+#endif
+
+//------------------------------------------------------------------------//
+//class CBTCodServiceMan
+//------------------------------------------------------------------------//
+
+void Panic(TBTCodPanic aPanic)
+	{
+	LOG_STATIC_FUNC
+	User::Panic(KBTCodPanic, aPanic);
+	}
+
+CBTCodServiceMan* CBTCodServiceMan::NewL()
+	{
+#ifdef __FLOG_ACTIVE
+	CONNECT_LOGGER
+#endif
+	LOG_STATIC_FUNC
+	CBTCodServiceMan* self = new(ELeave) CBTCodServiceMan();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+CBTCodServiceMan::CBTCodServiceMan()
+	{
+	LOG_FUNC
+	iServRefCount.Reset();
+	}
+
+void CBTCodServiceMan::ConstructL()
+	{
+	LOG_FUNC
+	}
+
+CBTCodServiceMan::~CBTCodServiceMan()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(ResolveServiceBits()==NULL, Panic(EBTCodServiceBits));
+#ifdef __FLOG_ACTIVE
+	CLOSE_LOGGER
+#endif
+	}
+
+void CBTCodServiceMan::Initialise()
+	{
+	LOG_FUNC
+	iPandSCod = iLinkMgr->iLocalDeviceSettings.DeviceClass();	// iPandSCod now has valid CoD 
+	}
+
+TInt CBTCodServiceMan::RegisterCodService(TUint16 aCodService)
+/*
+   This method is called via the base class (CBluetoothSAP), when an L2CAPSAP 
+   or RFCommSAP becomes active. It keeps a count of the Service bits being set.
+*/
+	{
+	LOG_FUNC
+	TInt err = KErrNone;
+	TUint index = 0;
+	
+	while (aCodService != 0)
+		{
+		if (aCodService & KBTCodServiceLSB)
+			{
+			iServRefCount[index]++;
+			}
+		index++;
+		aCodService >>= 1;
+		}
+
+	TRAP(err, WriteCoDL());
+	return err;
+	}
+
+	
+TInt CBTCodServiceMan::RemoveCodService(TUint16 aCodService)
+	{
+/*
+   This method is called via the base class (CBluetoothSAP), when an L2CAPSAP 
+   or RFCommSAP closes. It decrements the service bit counters and if any reach
+   zero, the CoD will be written and delete the bit(s).
+*/
+	LOG_FUNC
+	TInt err = KErrNone;
+	TUint index = 0;
+	TBool removeService = EFalse;
+		
+	while (aCodService != 0)
+		{
+		if (aCodService & KBTCodServiceLSB)
+			{
+			__ASSERT_DEBUG(iServRefCount[index] > 0, Panic(EBTCodBadCount));
+			if(iServRefCount[index])
+				{
+				if (--iServRefCount[index] == 0)
+					{
+					removeService = ETrue;
+					}
+				}
+			}
+		aCodService >>= 1;
+		index++;
+		}
+
+	if (removeService)
+		{
+		TRAP(err, WriteCoDL());
+		}
+	return err;
+	}
+	
+	
+TUint16 CBTCodServiceMan::ResolveServiceBits()
+	{
+/*
+   This private method will sweep through the iServRefCounts and return
+   a tally of the Service bit positions currently set.
+*/
+	LOG_FUNC
+	TUint16 serviceBits = 0;
+
+	for (TUint i=0; i<KBTMaxCodServices; i++)
+		{
+		if (iServRefCount[i])
+			{
+			serviceBits |= 1<<i;
+			}
+		}
+	return serviceBits;
+	}
+
+
+TInt CBTCodServiceMan::PandSCodHandler(TUint32 aCod)
+	{
+	LOG_FUNC
+	// The P&S interface wants to write the CoD value
+	TInt err = KErrNone;
+
+	aCod &= KBTCodMask;							// ensure upper unused byte is clear
+	iPandSCod = aCod;							// save new P&S CoD word
+	TRAP(err, WriteCoDL());
+	return err;
+	}
+
+
+void CBTCodServiceMan::WriteCoDL()
+	{
+/*
+   This private method is called whenever SAP services bits require updating.
+   These bits are obtained from the iServRefCounts and ORed with P&S service
+   settings before being written to the CoD.
+*/
+	LOG_FUNC
+	TUint32 sapServiceBits;
+
+	sapServiceBits = ResolveServiceBits();		// sweep through the iServRefCounts 
+	sapServiceBits <<= KBTCodServiceOffset;		// re-position the service bits
+
+	__ASSERT_ALWAYS(iLinkMgr, Panic(EBTCodBadLinkmgr));
+	iLinkMgr->WriteClassOfDeviceL(sapServiceBits | iPandSCod);	// write Cod with managed Service bits 
+	}
+