kerneltest/e32test/personality/example/init.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/personality/example/init.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,444 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\personality\example\init.cpp
+// Test code for example RTOS personality.
+// 
+//
+
+#include <kernel/kern_priv.h>
+#include <personality/example/personality.h>
+#include <personality/example/personality_int.h>
+#include "ifcldd.h"
+
+#define	OC_TASK			0
+
+#define MSG_ID_INIT		1
+#define MSG_ID_RUN		2
+#define MSG_ID_RUN_P	3
+#define	MSG_ID_RND_ISR	4
+#define MSG_ID_DONE		5
+#define	MSG_ID_DATA		6
+#define	MSG_ID_FLUSH	7
+#define MSG_ID_SEM_RPT	8
+#define MSG_ID_RCV_RPT	9
+#define MSG_ID_TM_RPT	10
+
+typedef struct _random_isr_msg
+	{
+	msghdr			header;
+	unsigned		random_isr_number;
+	unsigned		extra;
+	} random_isr_msg;
+
+typedef struct _data_msg
+	{
+	msghdr			header;
+	int				length;
+	unsigned char	checksum;
+	unsigned char	data[1];
+	} data_msg;
+
+typedef struct _report_msg
+	{
+	msghdr			header;
+	int				pad;
+	unsigned		count;
+	unsigned		ok_count;
+	unsigned		bad_count;
+	} report_msg;
+
+const TInt KMajorVersionNumber=0;
+const TInt KMinorVersionNumber=1;
+const TInt KBuildVersionNumber=1;
+
+void RxMsg(TAny* aPtr);
+
+TPMsgQ ThePMsgQ(&RxMsg, 0, Kern::DfcQue0(), 7);
+
+NONSHARABLE_CLASS(DRtosIfcFactory) : public DLogicalDevice
+	{
+public:
+	DRtosIfcFactory();
+	virtual TInt Install();						//overriding pure virtual
+	virtual void GetCaps(TDes8& aDes) const;	//overriding pure virtual
+	virtual TInt Create(DLogicalChannelBase*& aChannel);	//overriding pure virtual
+	};
+
+class TRxQ
+	{
+public:
+	TRxQ(DThread* aThread) : iFirst(0), iLast(0), iStatus(0), iPtr(0), iThread(aThread) {}
+	TInt QueueReq(TRequestStatus* aStatus, TAny* aPtr);
+	void AddMsg(msghdr* aM);
+	inline TBool MsgPresent() {return iFirst!=NULL;}
+	void CompleteReq();
+	void CancelReq();
+	void Close();
+public:
+	msghdr* iFirst;
+	msghdr* iLast;
+	TRequestStatus* iStatus;
+	TAny* iPtr;
+	DThread* iThread;
+	};
+
+TInt TRxQ::QueueReq(TRequestStatus* aStatus, TAny* aPtr)
+	{
+	if (iStatus)
+		return KErrInUse;
+	iStatus = aStatus;
+	iPtr = aPtr;
+	if (iFirst)
+		CompleteReq();
+	return KErrNone;
+	}
+
+void TRxQ::AddMsg(msghdr* aM)
+	{
+	aM->next = NULL;
+	if (iLast)
+		iLast->next = aM;
+	else
+		iFirst = aM;
+	iLast = aM;
+	if (iStatus)
+		CompleteReq();
+	}
+
+void TRxQ::CompleteReq()
+	{
+	msghdr* m = iFirst;
+	iFirst = m->next;
+	if (!iFirst)
+		iLast = NULL;
+	TInt r = KErrNone;
+	switch (m->msg_id)
+		{
+		case MSG_ID_DATA:
+			{
+			data_msg* dm = (data_msg*)m;
+			r = Kern::ThreadRawWrite(iThread, iPtr, &dm->length, dm->length + 5, iThread);
+			break;
+			}
+		case MSG_ID_SEM_RPT:
+		case MSG_ID_RCV_RPT:
+		case MSG_ID_TM_RPT:
+			{
+			report_msg* rpt = (report_msg*)m;
+			rpt->pad = m->msg_id;
+			r = Kern::ThreadRawWrite(iThread, iPtr, &rpt->pad, sizeof(SReport), iThread);
+			break;
+			}
+		default:
+			break;
+		}
+	free_mem_block(m);
+	Kern::RequestComplete(iThread, iStatus, r);
+	iStatus = NULL;
+	}
+
+void TRxQ::CancelReq()
+	{
+	if (iStatus)
+		Kern::RequestComplete(iThread, iStatus, KErrCancel);
+	iStatus = NULL;
+	}
+
+void TRxQ::Close()
+	{
+	CancelReq();
+	while (iFirst)
+		{
+		msghdr* m = iFirst;
+		iFirst = m->next;
+		free_mem_block(m);
+		}
+	iFirst = NULL;
+	iLast = NULL;
+	}
+
+NONSHARABLE_CLASS(DRtosIfc) : public DLogicalChannel
+	{
+public:
+	DRtosIfc();
+	virtual ~DRtosIfc();
+protected:
+	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	virtual void HandleMsg(TMessageBase* aMsg);
+public:
+	TInt DoControl(TInt aFunc, TAny* a1, TAny* a2);
+	TInt DoRequest(TInt aFunc, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+	void DoCancel(TInt aMask);
+	void HandleRtosMsg(msghdr* aMsg);
+public:
+	DThread* iThread;
+	TRequestStatus* iDoneStatus;
+	TRxQ iRxQ;
+	TRxQ iRptQ;
+	};
+
+void RxMsg(TAny* aPtr)
+	{
+	msghdr* m = ThePMsgQ.Get();
+	((DRtosIfc*)aPtr)->HandleRtosMsg(m);
+	}
+
+TInt EntryPoint()
+	{
+	TPMsgQ::ThePMsgQ = &::ThePMsgQ;
+	init_personality();
+
+	assert(current_task_id() == TASK_ID_UNKNOWN);
+
+	kprintf("Entry point exit");
+
+	return 0;
+	}
+
+void SendInitMsg()
+	{
+	kprintf("Send init msg");
+	msghdr* m = (msghdr*)alloc_mem_block(sizeof(msghdr));
+	m->msg_id = MSG_ID_INIT;
+	int r = send_msg(OC_TASK, m);
+	assert(r == OK);
+	}
+
+void SendFlushMsg()
+	{
+	msghdr* m = (msghdr*)alloc_mem_block(sizeof(msghdr));
+	m->msg_id = MSG_ID_FLUSH;
+	int r = send_msg(OC_TASK, m);
+	assert(r == OK);
+	}
+
+void SendFinishMsg()
+	{
+	msghdr* m = (msghdr*)alloc_mem_block(sizeof(msghdr));
+	m->msg_id = MSG_ID_DONE;
+	int r = send_msg(OC_TASK, m);
+	assert(r == OK);
+	}
+
+DRtosIfcFactory::DRtosIfcFactory()
+	{
+    iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
+    //iParseMask=0;//No units, no info, no PDD
+    //iUnitsMask=0;//Only one thing
+	}
+
+TInt DRtosIfcFactory::Create(DLogicalChannelBase*& aChannel)
+    {
+	aChannel = new DRtosIfc;
+    return aChannel ? KErrNone : KErrNoMemory;
+    }
+
+TInt DRtosIfcFactory::Install()
+	{
+	TInt r = SetName(&KRtosIfcLddName);
+#ifndef __EPOC32__
+	if (r == KErrNone)
+		r = EntryPoint();
+#endif
+	return r;
+	}
+
+void DRtosIfcFactory::GetCaps(TDes8& aDes) const
+    {
+    TCapsRtosIfcV01 b;
+    b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
+    Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
+    }
+
+DRtosIfc::DRtosIfc()
+	:	iRxQ(&Kern::CurrentThread()),
+		iRptQ(&Kern::CurrentThread())
+    {
+	iThread=&Kern::CurrentThread();
+	iThread->Open();
+    }
+
+DRtosIfc::~DRtosIfc()
+	{
+	iRxQ.Close();
+	iRptQ.Close();
+	Kern::SafeClose((DObject*&)iThread, NULL);
+	}
+
+TInt DRtosIfc::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
+//
+// Create channel
+//
+    {
+
+    if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
+    	return KErrNotSupported;
+	if (ThePMsgQ.iPtr)
+		return KErrInUse;
+	SetDfcQ(Kern::DfcQue0());
+	iMsgQ.Receive();
+	ThePMsgQ.iPtr = this;
+	ThePMsgQ.Receive();
+	return KErrNone;
+	}
+
+void DRtosIfc::HandleMsg(TMessageBase* aMsg)
+	{
+	TThreadMessage& m=*(TThreadMessage*)aMsg;
+	TInt id=m.iValue;
+	if (id==(TInt)ECloseMsg)
+		{
+		ThePMsgQ.CancelReceive();
+		ThePMsgQ.iPtr = NULL;
+		m.Complete(KErrNone,EFalse);
+		iMsgQ.CompleteAll(KErrServerTerminated);
+		return;
+		}
+	else if (id==KMaxTInt)
+		{
+		// DoCancel
+		DoCancel(m.Int0());
+		m.Complete(KErrNone,ETrue);
+		return;
+		}
+
+	if (id<0)
+		{
+		// DoRequest
+		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+		TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
+		if (r!=KErrNone)
+			Kern::RequestComplete(iThread,pS,r);
+		m.Complete(KErrNone,ETrue);
+		}
+	else
+		{
+		// DoControl
+		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
+		m.Complete(r,ETrue);
+		}
+	}
+
+TInt DRtosIfc::DoControl(TInt aFunc, TAny* a1, TAny* a2)
+	{
+	(void)a1;
+	(void)a2;
+	TInt r = KErrNone;
+	switch (aFunc)
+		{
+		case RRtosIfc::EControlInit:
+			SendInitMsg();
+			break;
+		case RRtosIfc::EControlFlush:
+			SendFlushMsg();
+			break;
+		case RRtosIfc::EControlFinish:
+			SendFinishMsg();
+			break;
+		case RRtosIfc::EControlSend:
+			{
+			data_msg* dm = (data_msg*)alloc_mem_block(512);
+			TPtr8 lptr(dm->data, 0, 516-sizeof(data_msg));
+			r = Kern::ThreadDesRead(iThread, a1, lptr, 0, 0);
+			if (r == KErrNone)
+				{
+				dm->header.msg_id = MSG_ID_DATA;
+				dm->length = lptr.Length();
+				dm->checksum = 0;
+				send_msg(OC_TASK, &dm->header);
+				}
+			else
+				free_mem_block(dm);
+			break;
+			}
+		default:
+			r = KErrNotSupported;
+			break;
+		}
+	return r;
+	}
+
+TInt DRtosIfc::DoRequest(TInt aFunc, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+	{
+	(void)a1;
+	(void)a2;
+	switch (aFunc)
+		{
+		case RRtosIfc::ERequestWaitInitialTests:
+			iDoneStatus = aStatus;
+			return KErrNone;
+		case RRtosIfc::ERequestReceive:
+			return iRxQ.QueueReq(aStatus, a1);
+		case RRtosIfc::ERequestReport:
+			return iRptQ.QueueReq(aStatus, a1);
+		default:
+			return KErrNotSupported;
+		}
+	}
+
+void DRtosIfc::DoCancel(TInt aMask)
+	{
+	if (aMask & RRtosIfc::ECancelWaitInitialTests)
+		{
+		Kern::RequestComplete(iThread, iDoneStatus, KErrCancel), iDoneStatus=NULL;
+		}
+	if (aMask & RRtosIfc::ECancelReceive)
+		iRxQ.CancelReq();
+	if (aMask & RRtosIfc::ECancelReport)
+		iRptQ.CancelReq();
+	}
+
+void DRtosIfc::HandleRtosMsg(msghdr* aM)
+	{
+	switch (aM->msg_id)
+		{
+		case MSG_ID_DONE:
+			if (iDoneStatus)
+				Kern::RequestComplete(iThread, iDoneStatus, KErrNone), iDoneStatus=NULL;
+			break;
+		case MSG_ID_DATA:
+			iRxQ.AddMsg(aM);
+			aM = NULL;
+			break;
+		case MSG_ID_SEM_RPT:
+		case MSG_ID_RCV_RPT:
+		case MSG_ID_TM_RPT:
+			iRptQ.AddMsg(aM);
+			aM = NULL;
+			break;
+		default:
+			break;
+		}
+	if (aM)
+		free_mem_block(aM);
+	ThePMsgQ.Receive();
+	}
+
+#ifdef __EPOC32__
+DECLARE_STANDARD_EXTENSION()
+	{
+	return EntryPoint();
+	}
+
+DECLARE_EXTENSION_LDD()
+	{
+	return new DRtosIfcFactory;
+	}
+#else
+DECLARE_STANDARD_LDD()
+	{
+	return new DRtosIfcFactory;
+	}
+#endif
+