diff -r 000000000000 -r a41df078684a kerneltest/e32test/personality/example/init.cpp --- /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 +#include +#include +#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 +