sl@0: // Copyright (c) 2008-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: // e32\e32test\demandpaging\d_pagingexample_1_pre.cpp sl@0: // Demand paging migration example device driver d_pagingexample_1_pre: a DLogicalChannel-dervied sl@0: // driver, pre-migration sl@0: // sl@0: // sl@0: sl@0: #include "d_pagingexample.h" sl@0: #include sl@0: #include sl@0: sl@0: const TInt KDfcQThreadPriority = 25; sl@0: const TInt KBufferSize = KMaxTransferSize; sl@0: sl@0: // sl@0: // Logical channel sl@0: // sl@0: sl@0: class DExampleChannel : public DLogicalChannel sl@0: { sl@0: public: sl@0: typedef RPagingExample::TConfigData TConfigData; sl@0: typedef RPagingExample::TValueStruct TValueStruct; sl@0: public: sl@0: DExampleChannel(); sl@0: ~DExampleChannel(); sl@0: virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); sl@0: virtual void HandleMsg(TMessageBase* aMsg); sl@0: TInt DoControl(TInt aFunction, TAny* a1, TAny* a2); sl@0: TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2); sl@0: TInt DoCancel(TUint aMask); sl@0: private: sl@0: TDfcQue* DfcQ(); sl@0: void Shutdown(); sl@0: void SetConfig(const TConfigData&); sl@0: TInt StartNotify(TRequestStatus* aStatus); sl@0: TInt StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus); sl@0: TInt StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus); sl@0: TInt StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus); sl@0: TInt StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus); sl@0: TInt StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus); sl@0: TInt StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus); sl@0: void ReceiveToReadBuffer(); sl@0: void SendFromWriteBuffer(); sl@0: static void AsyncGetValueCompleteDfcFunc(TAny* aPtr); sl@0: static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr); sl@0: static void ReceiveCompleteDfcFunc(TAny* aPtr); sl@0: static void SendCompleteDfcFunc(TAny* aPtr); sl@0: void CompleteNotify(); sl@0: void CompleteAsyncGetValue(); sl@0: void CompleteAsyncGetValue2(); sl@0: void CompleteRead(); sl@0: void CompleteWrite(); sl@0: private: sl@0: TDynamicDfcQue* iDynamicDfcQ; sl@0: TConfigData iConfig; sl@0: DThread* iClient; sl@0: sl@0: // Notify sl@0: TRequestStatus* iNotifyStatus; sl@0: sl@0: // Async get value sl@0: TRequestStatus* iAsyncGetValueStatus; sl@0: TInt* iAsyncGetValueDest; sl@0: NTimer iAsyncGetValueTimer; sl@0: TDfc iAsyncGetValueDfc; sl@0: sl@0: // Async get value 2 sl@0: TRequestStatus* iAsyncGetValue2Status; sl@0: TInt* iAsyncGetValue2Dest1; sl@0: TInt* iAsyncGetValue2Dest2; sl@0: NTimer iAsyncGetValue2Timer; sl@0: TDfc iAsyncGetValue2Dfc; sl@0: sl@0: // Read sl@0: TRequestStatus* iReadStatus; sl@0: NTimer iReadTimer; sl@0: TAny* iReadDest; sl@0: TInt iReadLength; sl@0: TDes8* iReadDes; sl@0: TDfc iCompleteReadDfc; sl@0: sl@0: // Write sl@0: TRequestStatus* iWriteStatus; sl@0: NTimer iWriteTimer; sl@0: TAny* iWriteSrc; sl@0: TInt iWriteLength; sl@0: const TDesC8* iWriteDes; sl@0: TDfc iCompleteWriteDfc; sl@0: TUint8 iBuffer[KBufferSize]; sl@0: }; sl@0: sl@0: DExampleChannel::DExampleChannel() : sl@0: iAsyncGetValueTimer(NULL, this), sl@0: iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, 0), sl@0: iAsyncGetValue2Timer(NULL, this), sl@0: iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, 0), sl@0: iReadTimer(NULL, this), sl@0: iCompleteReadDfc(ReceiveCompleteDfcFunc, this, 0), sl@0: iWriteTimer(NULL, this), sl@0: iCompleteWriteDfc(SendCompleteDfcFunc, this, 0) sl@0: { sl@0: iClient = &Kern::CurrentThread(); sl@0: iClient->Open(); sl@0: } sl@0: sl@0: DExampleChannel::~DExampleChannel() sl@0: { sl@0: Kern::SafeClose((DObject*&)iClient, NULL); sl@0: if (iDynamicDfcQ) sl@0: iDynamicDfcQ->Destroy(); sl@0: } sl@0: sl@0: TDfcQue* DExampleChannel::DfcQ() sl@0: { sl@0: return iDynamicDfcQ; sl@0: } sl@0: sl@0: TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/) sl@0: { sl@0: // Existing drivers may use the kernel global DFC queue, but for testing purposes we actually sl@0: // allocate our own so we can control its realtime state. sl@0: TInt r = Kern::DynamicDfcQCreate(iDynamicDfcQ, KDfcQThreadPriority, KPagingExample1PreLdd); sl@0: if (r != KErrNone) sl@0: return r; sl@0: iDynamicDfcQ->SetRealtimeState(ERealtimeStateWarn); sl@0: sl@0: SetDfcQ(DfcQ()); sl@0: iAsyncGetValueDfc.SetDfcQ(DfcQ()); sl@0: iAsyncGetValue2Dfc.SetDfcQ(DfcQ()); sl@0: iCompleteReadDfc.SetDfcQ(DfcQ()); sl@0: iCompleteWriteDfc.SetDfcQ(DfcQ()); sl@0: iMsgQ.Receive(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DExampleChannel::HandleMsg(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m=*(TThreadMessage*)aMsg; sl@0: TInt id=m.iValue; sl@0: sl@0: if (id==(TInt)ECloseMsg) sl@0: { sl@0: Shutdown(); sl@0: m.Complete(KErrNone,EFalse); sl@0: return; sl@0: } sl@0: sl@0: // we only support one client sl@0: if (m.Client() != iClient) sl@0: { sl@0: m.Complete(KErrAccessDenied,ETrue); sl@0: return; sl@0: } sl@0: sl@0: if (id==KMaxTInt) sl@0: { sl@0: // DoCancel sl@0: DoCancel(m.Int0()); sl@0: m.Complete(KErrNone,ETrue); sl@0: return; sl@0: } sl@0: else if (id<0) sl@0: { sl@0: // DoRequest sl@0: TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); sl@0: TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2()); sl@0: if (r!=KErrNone) sl@0: Kern::RequestComplete(m.Client(),pS,r); sl@0: m.Complete(KErrNone,ETrue); sl@0: } sl@0: else sl@0: { sl@0: // DoControl sl@0: TInt r=DoControl(id,m.Ptr0(),m.Ptr1()); sl@0: m.Complete(r,ETrue); sl@0: } sl@0: } sl@0: sl@0: TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/) sl@0: { sl@0: TInt r = KErrNone; sl@0: switch (aFunction) sl@0: { sl@0: case RPagingExample::ESetRealtimeState: sl@0: iDynamicDfcQ->SetRealtimeState(a1 ? ERealtimeStateOn : ERealtimeStateWarn); sl@0: break; sl@0: sl@0: case RPagingExample::EGetConfig: sl@0: r = Kern::ThreadRawWrite(iClient, a1, (TAny*)&iConfig, sizeof(TConfigData), iClient); sl@0: break; sl@0: sl@0: case RPagingExample::ESetConfig: sl@0: { sl@0: TConfigData newConfig; sl@0: r = Kern::ThreadRawRead(iClient, a1, &newConfig, sizeof(TConfigData)); sl@0: if (r == KErrNone) sl@0: SetConfig(newConfig); sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: r = KErrNotSupported; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2) sl@0: { sl@0: TInt r = KErrNotSupported; sl@0: switch (aFunction) sl@0: { sl@0: case RPagingExample::ERequestNotify: sl@0: r = StartNotify(aStatus); sl@0: break; sl@0: sl@0: case RPagingExample::ERequestAsyncGetValue: sl@0: r = StartAsyncGetValue((TInt*)a1, aStatus); sl@0: break; sl@0: sl@0: case RPagingExample::ERequestAsyncGetValue2: sl@0: r = StartAsyncGetValue2((TInt*)a1, (TInt*)a2, aStatus); sl@0: break; sl@0: sl@0: case RPagingExample::ERequestRead: sl@0: r = StartRead(a1, (TInt)a2, aStatus); sl@0: break; sl@0: sl@0: case RPagingExample::ERequestReadDes: sl@0: r = StartReadDes((TDes8*)a1, aStatus); sl@0: break; sl@0: sl@0: case RPagingExample::ERequestWrite: sl@0: r = StartWrite(a1, (TInt)a2, aStatus); sl@0: break; sl@0: sl@0: case RPagingExample::ERequestWriteDes: sl@0: r = StartWriteDes((TDes8*)a1, aStatus); sl@0: break; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DExampleChannel::DoCancel(TUint /*aMask*/) sl@0: { sl@0: if (iAsyncGetValueStatus) sl@0: { sl@0: iAsyncGetValueTimer.Cancel(); sl@0: iAsyncGetValueDfc.Cancel(); sl@0: Kern::RequestComplete(iClient, iAsyncGetValueStatus, KErrCancel); sl@0: } sl@0: sl@0: if (iAsyncGetValue2Status) sl@0: { sl@0: iAsyncGetValue2Timer.Cancel(); sl@0: iAsyncGetValue2Dfc.Cancel(); sl@0: Kern::RequestComplete(iClient, iAsyncGetValue2Status, KErrCancel); sl@0: } sl@0: sl@0: if (iReadStatus) sl@0: { sl@0: iReadTimer.Cancel(); sl@0: iCompleteReadDfc.Cancel(); sl@0: Kern::RequestComplete(iClient, iReadStatus, KErrCancel); sl@0: } sl@0: sl@0: if (iWriteStatus) sl@0: { sl@0: iWriteTimer.Cancel(); sl@0: iCompleteWriteDfc.Cancel(); sl@0: Kern::RequestComplete(iClient, iWriteStatus, KErrCancel); sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DExampleChannel::Shutdown() sl@0: { sl@0: } sl@0: sl@0: void DExampleChannel::SetConfig(const TConfigData& aNewConfig) sl@0: { sl@0: iConfig = aNewConfig; sl@0: } sl@0: sl@0: TInt DExampleChannel::StartNotify(TRequestStatus* aStatus) sl@0: { sl@0: iNotifyStatus = aStatus; sl@0: CompleteNotify(); // example implementation completes the request immediately sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DExampleChannel::CompleteNotify() sl@0: { sl@0: Kern::RequestComplete(iClient, iNotifyStatus, KErrNone); sl@0: } sl@0: sl@0: TInt DExampleChannel::StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus) sl@0: { sl@0: iAsyncGetValueDest = aValue; sl@0: iAsyncGetValueStatus = aStatus; sl@0: sl@0: // queue a timer to simulate an asynchronous operation sl@0: iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr) sl@0: { sl@0: DExampleChannel* self = (DExampleChannel*)aPtr; sl@0: self->CompleteAsyncGetValue(); sl@0: } sl@0: sl@0: void DExampleChannel::CompleteAsyncGetValue() sl@0: { sl@0: TValueStruct value; sl@0: value.iValue1 = 1; sl@0: value.iValue2 = _L8("shrt"); sl@0: TInt r = Kern::ThreadRawWrite(iClient, iAsyncGetValueDest, (TAny*)&value, sizeof(TValueStruct), iClient); sl@0: Kern::RequestComplete(iClient, iAsyncGetValueStatus, r); sl@0: } sl@0: sl@0: TInt DExampleChannel::StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus) sl@0: { sl@0: iAsyncGetValue2Dest1 = aValue1; sl@0: iAsyncGetValue2Dest2 = aValue2; sl@0: iAsyncGetValue2Status = aStatus; sl@0: sl@0: // queue a timer to simulate an asynchronous operation sl@0: iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr) sl@0: { sl@0: DExampleChannel* self = (DExampleChannel*)aPtr; sl@0: self->CompleteAsyncGetValue2(); sl@0: } sl@0: sl@0: void DExampleChannel::CompleteAsyncGetValue2() sl@0: { sl@0: TInt value1 = 1; sl@0: TInt value2 = 2; sl@0: TInt r = Kern::ThreadRawWrite(iClient, iAsyncGetValue2Dest1, (TAny*)&value1, sizeof(TInt), iClient); sl@0: if (r == KErrNone) sl@0: r = Kern::ThreadRawWrite(iClient, iAsyncGetValue2Dest2, (TAny*)&value2, sizeof(TInt), iClient); sl@0: Kern::RequestComplete(iClient, iAsyncGetValue2Status, r); sl@0: } sl@0: sl@0: TInt DExampleChannel::StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus) sl@0: { sl@0: if (iReadStatus) sl@0: return KErrInUse; sl@0: if (aLength < 1 || aLength > KBufferSize) sl@0: return KErrArgument; sl@0: iReadStatus = aStatus; sl@0: iReadDest = aBuffer; sl@0: iReadLength = aLength; sl@0: ReceiveToReadBuffer(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DExampleChannel::StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus) sl@0: { sl@0: if (iReadStatus) sl@0: return KErrInUse; sl@0: TInt r = Kern::ThreadGetDesMaxLength(iClient, aDesOut); sl@0: if (r < 0) sl@0: return r; sl@0: TInt length = r; sl@0: if (length < 1 || length > KBufferSize) sl@0: return KErrArgument; sl@0: iReadStatus = aStatus; sl@0: iReadDes = aDesOut; sl@0: iReadLength = length; sl@0: ReceiveToReadBuffer(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DExampleChannel::StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus) sl@0: { sl@0: if (iWriteStatus) sl@0: return KErrInUse; sl@0: if (aLength < 1 || aLength > KBufferSize) sl@0: return KErrArgument; sl@0: iWriteStatus = aStatus; sl@0: iWriteSrc = aBuffer; sl@0: iWriteLength = aLength; sl@0: SendFromWriteBuffer(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DExampleChannel::StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus) sl@0: { sl@0: if (iWriteStatus) sl@0: return KErrInUse; sl@0: TInt r = Kern::ThreadGetDesLength(iClient, aDesIn); sl@0: if (r < 0) sl@0: return r; sl@0: TInt length = r; sl@0: if (length < 1 || length > KBufferSize) sl@0: return KErrArgument; sl@0: iWriteStatus = aStatus; sl@0: iWriteLength = length; sl@0: iWriteDes = aDesIn; sl@0: SendFromWriteBuffer(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DExampleChannel::ReceiveToReadBuffer() sl@0: { sl@0: // just queue a timer to simulate an asynchronous receive operation sl@0: // actually will return the previous contents of the buffer sl@0: iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc); sl@0: } sl@0: sl@0: void DExampleChannel::SendFromWriteBuffer() sl@0: { sl@0: // just queue a timer to simulate an asynchronous send operation sl@0: iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc); sl@0: } sl@0: sl@0: void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr) sl@0: { sl@0: DExampleChannel* self = (DExampleChannel*)aPtr; sl@0: self->CompleteRead(); sl@0: } sl@0: sl@0: void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr) sl@0: { sl@0: DExampleChannel* self = (DExampleChannel*)aPtr; sl@0: self->CompleteWrite(); sl@0: } sl@0: sl@0: void DExampleChannel::CompleteRead() sl@0: { sl@0: TInt r; sl@0: if (iReadDest) sl@0: { sl@0: r = Kern::ThreadRawWrite(iClient, iReadDest, iBuffer, iReadLength, iClient); sl@0: iReadDest = NULL; sl@0: } sl@0: else sl@0: { sl@0: TPtrC8 des(iBuffer, iReadLength); sl@0: r = Kern::ThreadDesWrite(iClient, iReadDes, des, 0, KChunkShiftBy0, iClient); sl@0: iReadDes = NULL; sl@0: } sl@0: sl@0: iReadLength = 0; sl@0: Kern::RequestComplete(iClient, iReadStatus, r); sl@0: } sl@0: sl@0: void DExampleChannel::CompleteWrite() sl@0: { sl@0: TInt r; sl@0: if (iWriteSrc) sl@0: { sl@0: r = Kern::ThreadRawRead(iClient, iWriteSrc, iBuffer, iWriteLength); sl@0: iWriteSrc = NULL; sl@0: } sl@0: else sl@0: { sl@0: TPtr8 des(iBuffer, iWriteLength); sl@0: r = Kern::ThreadDesRead(iClient, iWriteDes, des, 0); sl@0: iWriteDes = NULL; sl@0: } sl@0: sl@0: iWriteLength = 0; sl@0: Kern::RequestComplete(iClient, iWriteStatus, r); sl@0: } sl@0: sl@0: // sl@0: // Logical device sl@0: // sl@0: sl@0: class DExampleFactory : public DLogicalDevice sl@0: { sl@0: public: sl@0: DExampleFactory(); sl@0: virtual TInt Install(); sl@0: virtual void GetCaps(TDes8& aDes) const; sl@0: virtual TInt Create(DLogicalChannelBase*& aChannel); sl@0: }; sl@0: sl@0: DExampleFactory::DExampleFactory() sl@0: { sl@0: iParseMask = 0; sl@0: iVersion = TVersion(1, 0, 0); sl@0: } sl@0: sl@0: TInt DExampleFactory::Install() sl@0: { sl@0: return SetName(&KPagingExample1PreLdd); sl@0: } sl@0: sl@0: void DExampleFactory::GetCaps(TDes8& /*aDes*/) const sl@0: { sl@0: // not used but required as DLogicalDevice::GetCaps is pure virtual sl@0: } sl@0: sl@0: TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel) sl@0: { sl@0: aChannel = new DExampleChannel; sl@0: return aChannel ? KErrNone : KErrNoMemory; sl@0: } sl@0: sl@0: DECLARE_STANDARD_LDD() sl@0: { sl@0: return new DExampleFactory; sl@0: }