dbgagents/trkagent/xtidriver/TrkXtiDriver.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgagents/trkagent/xtidriver/TrkXtiDriver.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,364 @@
+/*
+* Copyright (c) 2007 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: 
+*
+*/
+
+
+#ifdef __WINS__
+#error - this driver cannot be built for emulation
+#endif
+
+#include <e32def.h>
+#include <e32cmn.h>
+#include <kernel.h>
+#include <kern_priv.h>
+#include <arm.h>
+
+#include "TrkXtiComm.h"
+#include "TrkXtiDriver.h"
+
+#define KTrkAppSecurUid 0x200170BB
+#define KTrkExeSecurUid 0x200159E2
+
+//
+// Static function definitions
+//
+
+
+//
+//
+// DTrkXtiDriverFactory implementation
+//
+//
+
+//
+// DTrkXtiDriverFactory constructor
+//
+DTrkXtiDriverFactory::DTrkXtiDriverFactory()
+{
+    iVersion = TVersion(KMajorXtiVersionNumber, KMinorXtiVersionNumber, KBuildXtiVersionNumber);    
+}
+
+//
+// DTrkXtiDriverFactory::Create
+//
+TInt DTrkXtiDriverFactory::Create(DLogicalChannelBase*& aChannel)
+{
+	if (iOpenChannels != 0)
+		return KErrInUse; // a channel is already open
+	
+	aChannel = new DTrkXtiChannel(this);
+	
+	return aChannel ? KErrNone : KErrNoMemory;
+}
+
+//
+// DTrkXtiDriverFactory::Install
+//
+TInt DTrkXtiDriverFactory::Install()
+{
+    return(SetName(&KTrkXtiDriverName));
+}
+
+//
+// DTrkXtiDriverFactory::Install
+//
+void DTrkXtiDriverFactory::GetCaps(TDes8& aDes) const
+{
+    TCapsTrkXtiDriver b;
+    b.iVersion = TVersion(KMajorXtiVersionNumber, KMinorXtiVersionNumber, KBuildXtiVersionNumber);
+    
+    Kern::InfoCopy(aDes,(TUint8*)&b, sizeof(b));
+}
+
+
+//
+//
+// DTrkXtiChannel implementation
+//
+//
+
+//
+// DTrkXtiChannel constructor
+//
+DTrkXtiChannel::DTrkXtiChannel(DLogicalDevice* aLogicalDevice)
+					: iRxPendingMsg(EFalse),
+					  iInterruptId(76)
+{
+	
+	LOG_MSG("DTrkXtiChannel::DTrkXtiChannel()");
+
+	iDevice = aLogicalDevice;
+	
+	iClientThread = &Kern::CurrentThread();
+	TInt err = iClientThread->Open();	
+	
+	
+	LOG_MSG("DTrkXtiChannel::DTrkXtiChannel() End"); 
+}
+
+//
+// DTrkXtiChannel destructor
+//
+DTrkXtiChannel::~DTrkXtiChannel()
+{
+	LOG_MSG("DTrkXtiChannel::~DTrkXtiChannel()");
+	
+	Kern::SafeClose((DObject*&)iClientThread, NULL);
+	
+	if (iLock)
+		iLock->Close(NULL);	
+}
+
+//
+// DTrkXtiChannel::DoCreate
+//
+TInt DTrkXtiChannel::DoCreate(TInt /*aUnit*/, const TDesC* /*anInfo*/, const TVersion& aVer)
+{
+	LOG_MSG("DTrkXtiChannel::DoCreate()");
+
+  	if (!Kern::QueryVersionSupported(TVersion(KMajorXtiVersionNumber, KMinorXtiVersionNumber, KBuildXtiVersionNumber), aVer))
+		return KErrNotSupported; 
+
+	//Setup the driver for receiving client messages
+	iDFCQue = NULL;
+	TBuf8<KMaxInfoName> xtiDFC = _L8("XTI DFC");;
+	
+	TInt err = Kern::DfcQCreate(iDFCQue, 27, &xtiDFC);
+	if (err == KErrNone)
+	{
+		SetDfcQ(iDFCQue);
+	}
+	else
+	{
+		SetDfcQ(Kern::DfcQue0());
+	}
+
+	iMsgQ.Receive();  	
+	
+	// create subscriber and subscribe to receive trk messages from TraceCore
+	iTrkXtiSubscriber = new DTrkXtiSubscriber;
+ 	if (!iTrkXtiSubscriber)
+		return KErrNoMemory;
+ 	
+	err = iTrkXtiSubscriber->Create(this, iClientThread);
+	if (err != KErrNone)
+		return err;
+	
+	err = Kern::SemaphoreCreate(iLock, _L("TrkXtiDriverWriteLock"), 1 /* Initial count */);
+	if (err != KErrNone)
+		return err;
+
+	return KErrNone;
+}
+
+//
+// DTrkXtiChannel::DoCancel
+//
+void DTrkXtiChannel::DoCancel(TInt aReqNo)
+{
+	LOG_MSG("DTrkXtiChannel::DoCancel()");
+	
+	switch(aReqNo)
+	{
+		case RTrkXtiDriver::ERequestReadCancel:
+		{
+			Kern::RequestComplete(iClientThread, iRxRequestStatus, KErrCancel);
+			iRxClientBuffer = NULL;
+			iRxRequestStatus = NULL;
+			iRxClientBufferLength = 0;
+		}
+		break;
+	}
+
+}
+
+//
+// DTrkXtiChannel::DoRequest
+//
+void DTrkXtiChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+{
+	LOG_MSG("DTrkXtiChannel::DoRequest()");
+		
+	switch(aReqNo)
+	{
+		case RTrkXtiDriver::ERequestRead:
+		{
+			iRxRequestStatus = aStatus;
+			iRxClientBuffer = a1;
+			iRxClientBufferLength = (TUint32)a2;
+			
+			if (iRxPendingMsg)
+			{
+				TInt err = Kern::ThreadDesWrite(iClientThread, iRxClientBuffer, iRxPendingMsgBuffer, 0, KChunkShiftBy0, iClientThread);
+				Kern::RequestComplete(iClientThread, iRxRequestStatus, err);
+		
+				iRxRequestStatus = NULL;
+				iRxPendingMsg = EFalse;
+			}
+
+			break;
+		}		
+		default:
+			Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
+	}
+}
+
+//
+// DTrkXtiChannel::DoControl
+//
+TInt DTrkXtiChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+{
+	LOG_MSG("DTrkXtiChannel::DoControl()");
+	
+	TInt err = KErrNone;
+	
+	switch(aFunction)
+	{
+		case RTrkXtiDriver::EControlWrite:
+		{
+			//lock the Semaphore so that write doesn't happen when a write is already in progress.
+			Kern::SemaphoreWait(*iLock);
+			err = DoWrite((TUint32)a1, a2);			
+			Kern::SemaphoreSignal(*iLock);			
+			break;
+		}
+		default:
+		{
+			return KErrGeneral;
+		}
+
+	}
+	if (KErrNone != err)
+	{
+		LOG_MSG2("Error %d from control function", err);
+	}
+	return err;
+}
+
+//
+// DTrkXtiChannel::HandleMsg
+//
+void DTrkXtiChannel::HandleMsg(TMessageBase* aMsg)
+{
+	LOG_MSG("DTrkXtiChannel::HandleMsg()");
+	
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+
+
+	if (id == (TInt)ECloseMsg)
+	{
+        if (iTrkXtiSubscriber)
+        {
+            Kern::SemaphoreWait(*iLock);
+            delete iTrkXtiSubscriber;
+            iTrkXtiSubscriber = NULL;   
+            Kern::SemaphoreSignal(*iLock);              
+        }
+		m.Complete(KErrNone, EFalse);
+		return;
+	}
+
+	if (id == KMaxTInt)
+	{
+		// DoCancel
+		DoCancel(m.Int0());
+		m.Complete(KErrNone, ETrue); 
+		return;
+	}
+
+	if (id < 0)
+	{
+		// DoRequest
+		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
+		DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
+		m.Complete(KErrNone, ETrue);
+	}
+	else
+	{
+		// DoControl
+		TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
+		m.Complete(err, ETrue);
+	}
+}
+
+//
+// DTrkXtiChannel::DoWrite
+//
+TInt DTrkXtiChannel::DoWrite(TUint32 aLength, TAny* a2)
+{
+	LOG_MSG("DTrkXtiChannel::DoWrite()");
+
+	TInt err = KErrNone;
+
+	err = Kern::ThreadDesRead(iClientThread, a2, iTxBuffer, 0, KChunkShiftBy0);
+
+	if (err == KErrNone)
+	{	
+		err = WriteXtiChannel(iTxBuffer);
+	}
+	return err;
+}
+
+//
+// DTrkXtiChannel::WriteXtiChannel
+//
+// This function writes all the data in the descriptor in one message
+TInt DTrkXtiChannel::WriteXtiChannel(TDesC8& aDes)
+{
+	TInt err = KErrNone;
+		err = iTrkXtiSubscriber->Send(aDes);
+
+	return err;
+}
+
+
+
+
+
+//
+// DTrkXtiChannel::DoCompleteRx
+//
+void DTrkXtiChannel::DoCompleteRx(const TDesC8& aMessage)
+{
+	LOG_MSG("DTrkXtiChannel::DoCompleteRx()");
+
+	// If there is a pending read request, complete the request with this message.
+	// Otherwise store the message, ideally we should queue the messages, but having 
+	// a large buffer is failing to initialize at the startup.
+	// For now, we will just store only one message
+	// If for some reason, TRK is waiting on something and doesn't read for a while, 
+	// then its possible that we will loose messages. 
+	Kern::SemaphoreWait(*iLock);
+	if (iRxRequestStatus)
+	{
+		TInt err = Kern::ThreadDesWrite(iClientThread, iRxClientBuffer, aMessage, 0, KChunkShiftBy0, iClientThread);
+		Kern::RequestComplete(iClientThread, iRxRequestStatus, err);
+		
+		iRxRequestStatus = NULL;
+	}
+	else if (!iRxPendingMsg)
+	{
+		iRxPendingMsgBuffer.Copy(aMessage);
+		iRxPendingMsg = ETrue;
+	}
+	Kern::SemaphoreSignal(*iLock);
+}
+
+DECLARE_STANDARD_LDD()
+{
+    return new DTrkXtiDriverFactory;
+}