bluetoothmgmt/bluetoothclientlib/avctpservices/avctpreceiver.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothmgmt/bluetoothclientlib/avctpservices/avctpreceiver.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,245 @@
+// 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:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <bluetooth/logger.h>
+#include "avctpreceiver.h"
+#include "avctpcommon.h"
+#include "avctpbody.h"
+#include "avctpPriorities.h"
+#include "avctpserviceutils.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVCTP_SERVICES);
+#endif
+
+using namespace SymbianAvctp;
+
+/**
+two-phase constructor
+@param aAvctpBody The class that provides access to the AVCTP client
+@leave systemwide reason
+@return pointer to newly created object
+@internalTechnology
+*/
+CAvctpReceiver* CAvctpReceiver::NewL(MAvctpEventNotify& aNotify, RSocket& aAvctpSocket, TPid aPid)
+	{
+	LOG_STATIC_FUNC
+
+	CAvctpReceiver* self = CAvctpReceiver::NewLC(aNotify, aAvctpSocket, aPid);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+two-phase constructor, leaves object on cleanupstack
+@param aAvctpBody The class that provides access to the AVCTP client
+@leave systemwide reason
+@return pointer to newly created object
+@internalTechnology
+*/
+CAvctpReceiver* CAvctpReceiver::NewLC(MAvctpEventNotify& aNotify, RSocket& aAvctpSocket, TPid aPid)
+	{
+	LOG_STATIC_FUNC
+
+	CAvctpReceiver* self = new(ELeave) CAvctpReceiver(aNotify, aAvctpSocket, aPid);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+/**
+c'tor
+*/
+CAvctpReceiver::CAvctpReceiver(MAvctpEventNotify& aNotify, RSocket& aAvctpSocket, TPid aPid) : 
+	CActive(KDataPlanePriority), 
+	iNotify(aNotify),
+	iAvctpSocket(aAvctpSocket),
+	iRecvState(EWaitingForPktHeader),
+	iRecvPtr(NULL, 0),
+	iPid(aPid)
+	{
+	LOG_FUNC
+	}
+
+void CAvctpReceiver::ConstructL()
+	{
+	LOG_FUNC
+	iRecvBuf = HBufC8::NewMaxL(ENormalHeaderLength);
+	iRecvBuf->Des().SetMax();
+	CActiveScheduler::Add(this);
+	ReceiveL(EWaitingForPktHeader);
+	}
+
+/**
+d'tor
+*/
+CAvctpReceiver::~CAvctpReceiver()
+	{
+	LOG_FUNC
+
+	Cancel();
+	delete iRecvBuf;
+	}
+
+inline void CAvctpReceiver::NotifyMessageReceived(const TBTDevAddr& aBTDevice,
+									   		  SymbianAvctp::TTransactionLabel aTransactionLabel,
+									   		  SymbianAvctp::TMessageType aType,
+									   		  TBool aIpidBitSet,
+							 		   		  const TDesC8& aMessageInformation)
+	{
+	LOG_FUNC
+	__ASSERT_BTADDR(aBTDevice);
+	SymbianAvctp::AssertValidTransactionLabel(aTransactionLabel);
+	__ASSERT_DEBUG(aType == SymbianAvctp::ECommand || aType == SymbianAvctp::EResponse, Panic(::EAvctpInvalidMessageType));
+	
+	iNotify.MaenMessageReceivedIndicate(aBTDevice, aTransactionLabel, aType, aIpidBitSet, aMessageInformation);
+	}
+	
+//
+// Function that issues RecvFrom 
+
+/**
+Requests data from the Avctp Sap
+When the async Recv completes, iXfrLength will contain the remaining amount of data
+in the same packet that we've not yet got.
+*/
+void CAvctpReceiver::ReceiveL(TRecvState aNextState, TInt aBufLen)
+	{
+	LOG_FUNC
+	//Make sure iRecvBuf isn't NULL before using it
+	if((!iRecvBuf) || (iRecvBuf->Des().MaxLength() < aBufLen)) 
+		{
+		// Don't ReAlloc cause that copies across the old data which we don't want
+		delete iRecvBuf; // free previous data
+		iRecvBuf = NULL;
+		iRecvBuf = HBufC8::NewMaxL(aBufLen);
+		iRecvBuf->Des().SetMax();
+		}
+	iRecvPtr.Set(iRecvBuf->Des().MidTPtr(0, aBufLen));
+	iAvctpSocket.RecvFrom(iRecvPtr, iAddr, KSockReadContinuation, iStatus, iXfrLength);	
+	ChangeState(aNextState);
+	}
+
+//
+// Functions From CActive
+	
+void CAvctpReceiver::DoCancel()
+	{
+	LOG_FUNC
+
+	iAvctpSocket.CancelRecv();
+	}
+
+void CAvctpReceiver::RunL()
+	{
+	LOG_FUNC
+	LOG1(_L("iStatus.Int(): %d"), iStatus.Int())
+	
+	if (iStatus.Int() == KErrNone)
+		{
+		switch (iRecvState)
+			{
+			case EWaitingForPktHeader:
+				SetPacketInfo(iRecvPtr);
+				if (iXfrLength())
+					{
+					ReceiveL(EWaitingForMsgInfo, iXfrLength());												 
+					}
+				else // there was no message data
+					{
+					NotifyMessageReceived(TAvctpSockAddr::Cast(iAddr).BTAddr(), 
+													 iTransactionLabel, 
+													 iMessageType, 
+													 iIpidBitSet, 
+													 KNullDesC8);
+					ReceiveL(EWaitingForPktHeader);	
+					}
+				break;
+				
+			case EWaitingForMsgInfo:
+				NotifyMessageReceived(TAvctpSockAddr::Cast(iAddr).BTAddr(), 
+												 iTransactionLabel, 
+												 iMessageType, 
+												 iIpidBitSet, 
+												 iRecvPtr);
+				ReceiveL(EWaitingForPktHeader);
+				break;		
+					
+			default:
+				__ASSERT_ALWAYS(NULL, Panic(EAvctpUnrecognisedState));
+				break;
+			}
+		}
+	else if (iStatus.Int() != KErrCancel)
+		{
+		iNotify.MaenErrorNotify(TAvctpSockAddr::Cast(iAddr).BTAddr(), iStatus.Int());
+		}
+	// else ignore the KErrCancel since the cancelled request wasn't directly asked for by the client of RAvctp
+	}
+	
+TInt CAvctpReceiver::RunError(TInt aError)
+	{
+	LOG_FUNC
+
+	iNotify.MaenErrorNotify(TAvctpSockAddr::Cast(iAddr).BTAddr(), aError);
+	return KErrNone;	
+	}
+
+//
+// Other Functions
+
+void CAvctpReceiver::ChangeState(TRecvState aNextState)
+	{
+	LOG_FUNC
+	LOG2(_L("current State: %d, aNextState: %d"), iRecvState, aNextState)
+	
+	__ASSERT_DEBUG((iRecvState == EWaitingForPktHeader && aNextState == EWaitingForMsgInfo)   ||
+				   (iRecvState == EWaitingForPktHeader && aNextState == EWaitingForPktHeader) ||
+				   (iRecvState == EWaitingForMsgInfo &&   aNextState == EWaitingForPktHeader),
+				   Panic(EAvctpRecvBadStateTransition));
+	__ASSERT_ALWAYS(!IsActive(), Panic(EAvctpRecvBadStateTransition));
+	iRecvState = aNextState;
+	SetActive();
+	}
+    
+void CAvctpReceiver::SetPacketInfo(TDes8& aHeader)
+	{
+	LOG_FUNC
+
+	__ASSERT_DEBUG(Pid(aHeader) == iPid, Panic(EAvctpIncorrectPid));
+	__ASSERT_DEBUG(PacketType(aHeader) == ENormalPkt, Panic(EAvctpPacketTypeNotNormal));
+				
+	iTransactionLabel = TransactionLabel(aHeader);
+	iMessageType = MessageType(aHeader);
+	iIpidBitSet = !IsValidPid(aHeader);
+	
+  __DEBUG_ONLY
+  		(
+  		TBuf<KBTAddressLength> address;
+  		TAvctpSockAddr::Cast(iAddr).BTAddr().GetReadable(address);
+  		)
+  	
+  	LOG1(_L("BT Device 0x%S"), &address);
+	
+	LOG3(_L("iTransactionLabel: %d, iMessageType: %d, iIpidBitSet: %d"), iTransactionLabel, iMessageType, iIpidBitSet)
+	}
+        	
+// EOF
+