sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\misc\d_ipccpy.cpp sl@0: // LDD for testing IPC copy functions sl@0: // sl@0: // sl@0: sl@0: #include "platform.h" sl@0: #include sl@0: #include "d_ipccpy.h" sl@0: sl@0: const TInt KMajorVersionNumber=0; sl@0: const TInt KMinorVersionNumber=1; sl@0: const TInt KBuildVersionNumber=1; sl@0: sl@0: const TInt KBigBufferSize = 65536; sl@0: sl@0: _LIT(KDIpcCpyPanicCategory,"DIpcCpy"); sl@0: sl@0: class DIpcCpyFactory : public DLogicalDevice sl@0: // sl@0: // IPC copy LDD factory sl@0: // sl@0: { sl@0: public: sl@0: DIpcCpyFactory(); sl@0: ~DIpcCpyFactory(); sl@0: virtual TInt Install(); //overriding pure virtual sl@0: virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual sl@0: virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual sl@0: sl@0: private: sl@0: TDynamicDfcQue* iDfcQ; sl@0: }; sl@0: sl@0: class DIpcCpy : public DLogicalChannel sl@0: // sl@0: // Millisecond timer LDD channel sl@0: // sl@0: { sl@0: public: sl@0: DIpcCpy(TDfcQue* aDfcQ); sl@0: virtual ~DIpcCpy(); sl@0: protected: sl@0: virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); sl@0: virtual TInt Request(TInt aFunc, TAny* a1, TAny* a2); sl@0: virtual void HandleMsg(TMessageBase* aMsg); sl@0: public: sl@0: void TimerExpired(); sl@0: TInt CreateHardwareChunks(TPtr8& aUserDes); sl@0: sl@0: // Panic reasons sl@0: enum TPanic sl@0: { sl@0: ERequestAlreadyPending = 1 sl@0: }; sl@0: public: sl@0: DThread* iThread; sl@0: TClientRequest* iAsyncRequest; sl@0: TAny* iDest; sl@0: TInt iSeqNum; sl@0: NTimer iTimer; sl@0: TDfc iDfc; sl@0: TUint8 iBuffer[260]; sl@0: TUint8* iBigBuffer; sl@0: #ifdef __EPOC32__ sl@0: DPlatChunkHw* iHwChunks[RIpcCpy::ENumHwChunkTypes]; sl@0: #endif sl@0: TLinAddr iHwChunkLinAddrs[RIpcCpy::ENumHwChunkTypes]; sl@0: }; sl@0: sl@0: DECLARE_STANDARD_LDD() sl@0: { sl@0: return new DIpcCpyFactory; sl@0: } sl@0: sl@0: DIpcCpyFactory::DIpcCpyFactory() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); sl@0: //iParseMask=0;//No units, no info, no PDD sl@0: //iUnitsMask=0;//Only one thing sl@0: } sl@0: sl@0: DIpcCpyFactory::~DIpcCpyFactory() sl@0: // sl@0: // Destructor sl@0: // sl@0: { sl@0: if (iDfcQ) sl@0: iDfcQ->Destroy(); sl@0: } sl@0: sl@0: TInt DIpcCpyFactory::Create(DLogicalChannelBase*& aChannel) sl@0: // sl@0: // Create a new DIpcCpy on this logical device sl@0: // sl@0: { sl@0: aChannel=new DIpcCpy(iDfcQ); sl@0: return aChannel?KErrNone:KErrNoMemory; sl@0: } sl@0: sl@0: const TInt KIpcCpyThreadPriority = 27; sl@0: _LIT(KIpcCpyThread,"IpcCpyThread"); sl@0: sl@0: TInt DIpcCpyFactory::Install() sl@0: // sl@0: // Install the LDD - overriding pure virtual sl@0: // sl@0: { sl@0: // Allocate a kernel thread to run the DFC sl@0: TInt r = Kern::DynamicDfcQCreate(iDfcQ, KIpcCpyThreadPriority, KIpcCpyThread); sl@0: sl@0: #ifdef CPU_AFFINITY_ANY sl@0: NKern::ThreadSetCpuAffinity((NThread*)(iDfcQ->iThread), KCpuAffinityAny); sl@0: #endif sl@0: sl@0: if (r != KErrNone) sl@0: return r; sl@0: sl@0: return SetName(&KIpcCpyLddName); sl@0: } sl@0: sl@0: void DIpcCpyFactory::GetCaps(TDes8& aDes) const sl@0: // sl@0: // Get capabilities - overriding pure virtual sl@0: // sl@0: { sl@0: TCapsIpcCpyV01 b; sl@0: b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); sl@0: Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b)); sl@0: } sl@0: sl@0: void timerExpired(TAny* aPtr) sl@0: { sl@0: DIpcCpy* p=(DIpcCpy*)aPtr; sl@0: p->iDfc.Add(); sl@0: } sl@0: sl@0: void dfcFn(TAny* aPtr) sl@0: { sl@0: DIpcCpy* p=(DIpcCpy*)aPtr; sl@0: p->TimerExpired(); sl@0: } sl@0: sl@0: DIpcCpy::DIpcCpy(TDfcQue* aDfcQ) sl@0: // sl@0: // Constructor sl@0: // sl@0: : iTimer(timerExpired,this), sl@0: iDfc(dfcFn,this,aDfcQ,1) sl@0: { sl@0: iThread=&Kern::CurrentThread(); sl@0: iThread->Open(); sl@0: // iSeqNum=0; sl@0: // iDest=NULL; sl@0: SetDfcQ(aDfcQ); sl@0: } sl@0: sl@0: DIpcCpy::~DIpcCpy() sl@0: { sl@0: if (iAsyncRequest) sl@0: { sl@0: Kern::QueueRequestComplete(iThread, iAsyncRequest, KErrCancel); // does nothing if request not pending sl@0: Kern::DestroyClientRequest(iAsyncRequest); sl@0: } sl@0: Kern::Free(iBigBuffer); sl@0: Kern::SafeClose((DObject*&)iThread, NULL); sl@0: sl@0: #ifdef __EPOC32__ sl@0: for(TInt i=0; iLinearAddress(); sl@0: } sl@0: else if (r==KErrNotSupported) //ARMv6K && ARMv7 do not support EMapAttrUserRo sl@0: { sl@0: iHwChunkLinAddrs[i] = 0; sl@0: r = KErrNone; sl@0: } sl@0: else sl@0: { sl@0: Epoc::FreePhysicalRam(phys,size); sl@0: NKern::ThreadLeaveCS(); sl@0: return r; sl@0: } sl@0: sl@0: } sl@0: NKern::ThreadLeaveCS(); sl@0: return r; sl@0: #endif sl@0: } sl@0: sl@0: sl@0: TInt DIpcCpy::Request(TInt aFunc, TAny* a1, TAny* a2) sl@0: { sl@0: if (aFunc == RIpcCpy::EControlBigRead) sl@0: { sl@0: TUint size = (TUint)a2; sl@0: if (size > (TUint)KBigBufferSize) sl@0: return KErrOverflow; sl@0: kumemput(a1, iBigBuffer, size); sl@0: return KErrNone; sl@0: } sl@0: else if (aFunc == RIpcCpy::EControlBigWrite) sl@0: { sl@0: TUint size = (TUint)a2; sl@0: if (size > (TUint)KBigBufferSize) sl@0: return KErrOverflow; sl@0: kumemget(iBigBuffer, a1, size); sl@0: return KErrNone; sl@0: } sl@0: else if (aFunc == RIpcCpy::EControlHardwareChunks) sl@0: { sl@0: TPtr8 des(0,0,0); sl@0: kumemget(&des,a2,sizeof(TPtr8)); sl@0: TInt r=CreateHardwareChunks(des); sl@0: if(r==KErrNone) sl@0: kumemput(a1, iHwChunkLinAddrs, sizeof(iHwChunkLinAddrs)); sl@0: return r; sl@0: } sl@0: return DLogicalChannel::Request(aFunc, a1, a2); sl@0: } sl@0: sl@0: void DIpcCpy::HandleMsg(TMessageBase* aMsg) sl@0: { sl@0: TInt r=KErrNone; sl@0: TThreadMessage& m=*(TThreadMessage*)aMsg; sl@0: TInt id=m.iValue; sl@0: if (id==(TInt)ECloseMsg) sl@0: { sl@0: iTimer.Cancel(); sl@0: iDfc.Cancel(); sl@0: m.Complete(KErrNone,EFalse); sl@0: iMsgQ.CompleteAll(KErrServerTerminated); sl@0: return; sl@0: } sl@0: else if (id<0) sl@0: { sl@0: TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); sl@0: if (iAsyncRequest->SetStatus(pS) != KErrNone) sl@0: Kern::ThreadKill(iThread,EExitPanic,ERequestAlreadyPending,KDIpcCpyPanicCategory); sl@0: sl@0: if (id==~RIpcCpy::ERequestIpcCpy) sl@0: { sl@0: iDest=m.Ptr1(); sl@0: iTimer.OneShot(1); sl@0: } sl@0: else sl@0: { sl@0: r=KErrNotSupported; sl@0: } sl@0: sl@0: if(r!=KErrNone) sl@0: { sl@0: Kern::QueueRequestComplete(iThread, iAsyncRequest, r); sl@0: r = KErrNone; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: r=KErrNotSupported; sl@0: } sl@0: sl@0: m.Complete(r,ETrue); sl@0: } sl@0: sl@0: void DIpcCpy::TimerExpired() sl@0: { sl@0: TInt src_offset=iSeqNum&3; sl@0: TInt dest_offset=(iSeqNum>>2)&3; sl@0: TInt length=(iSeqNum>>4)+1; sl@0: TInt i; sl@0: for (i=src_offset; i