Update contrib.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\e32test\demandpaging\d_pagingexample_1_post.cpp
15 // Demand paging migration example device driver d_pagingexample_1_post: a DLogicalChannel-dervied
16 // driver, post-migration
20 #include "d_pagingexample.h"
21 #include <kernel/kernel.h>
22 #include <kernel/kern_priv.h>
24 const TInt KDfcQThreadPriority = 25;
25 const TInt KBufferSize = KMaxTransferSize;
31 class DExampleChannel : public DLogicalChannel
34 typedef RPagingExample::TConfigData TConfigData;
35 typedef RPagingExample::TValueStruct TValueStruct;
39 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
40 virtual TInt SendMsg(TMessageBase* aMsg);
41 TInt SendControl(TMessageBase* aMsg);
42 TInt SendRequest(TMessageBase* aMsg);
43 virtual void HandleMsg(TMessageBase* aMsg);
44 TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
45 void DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
46 TInt DoCancel(TUint aMask);
50 void SetConfig(const TConfigData&);
51 TInt PreNotify(TRequestStatus* aStatus);
53 TInt PreAsyncGetValue(TInt* aValue, TRequestStatus* aStatus);
54 void StartAsyncGetValue();
55 TInt PreAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus);
56 void StartAsyncGetValue2();
57 TInt PreRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
59 TInt PreReadDes(TDes8* aDesOut, TRequestStatus* aStatus);
61 TInt PreWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
63 TInt PreWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus);
65 void ReceiveToReadBuffer();
66 void SendFromWriteBuffer();
67 static void AsyncGetValueCompleteDfcFunc(TAny* aPtr);
68 static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr);
69 static void ReceiveCompleteDfcFunc(TAny* aPtr);
70 static void SendCompleteDfcFunc(TAny* aPtr);
71 void CompleteNotify();
72 void CompleteAsyncGetValue();
73 void CompleteAsyncGetValue2();
77 TDynamicDfcQue* iDynamicDfcQ;
82 TClientRequest* iNotifyRequest;
85 TClientDataRequest<TValueStruct>* iAsyncGetValueRequest;
86 NTimer iAsyncGetValueTimer;
87 TDfc iAsyncGetValueDfc;
90 TClientDataRequest2<TInt,TInt>* iAsyncGetValue2Request;
91 NTimer iAsyncGetValue2Timer;
92 TDfc iAsyncGetValue2Dfc;
95 TClientBufferRequest* iReadRequest;
97 TClientBuffer* iClientReadBuffer;
98 TDfc iCompleteReadDfc;
101 TClientBufferRequest* iWriteRequest;
103 TClientBuffer* iClientWriteBuffer;
104 TDfc iCompleteWriteDfc;
105 TUint8 iBuffer[KBufferSize];
108 DExampleChannel::DExampleChannel() :
109 iAsyncGetValueTimer(NULL, this),
110 iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, 0),
111 iAsyncGetValue2Timer(NULL, this),
112 iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, 0),
113 iReadTimer(NULL, this),
114 iCompleteReadDfc(ReceiveCompleteDfcFunc, this, 0),
115 iWriteTimer(NULL, this),
116 iCompleteWriteDfc(SendCompleteDfcFunc, this, 0)
118 iClient = &Kern::CurrentThread();
122 DExampleChannel::~DExampleChannel()
124 Kern::SafeClose((DObject*&)iClient, NULL);
126 iDynamicDfcQ->Destroy();
127 Kern::DestroyClientRequest(iNotifyRequest);
128 Kern::DestroyClientRequest(iAsyncGetValueRequest);
129 Kern::DestroyClientRequest(iAsyncGetValue2Request);
130 Kern::DestroyClientBufferRequest(iReadRequest);
131 Kern::DestroyClientBufferRequest(iWriteRequest);
134 TDfcQue* DExampleChannel::DfcQ()
139 TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
143 r = Kern::CreateClientRequest(iNotifyRequest);
146 r = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
149 r = Kern::CreateClientDataRequest2(iAsyncGetValue2Request);
152 r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
155 r = Kern::CreateClientBufferRequest(iWriteRequest, 1, TClientBufferRequest::EPinVirtual);
159 // create a dynamic DFC queue, which is used for handling client messages and for our own DFCs
160 r = Kern::DynamicDfcQCreate(iDynamicDfcQ, KDfcQThreadPriority, KPagingExample1PostLdd);
164 // todo: this will be the default anyway
165 iDynamicDfcQ->SetRealtimeState(ERealtimeStateOn);
168 iAsyncGetValueDfc.SetDfcQ(DfcQ());
169 iAsyncGetValue2Dfc.SetDfcQ(DfcQ());
170 iCompleteReadDfc.SetDfcQ(DfcQ());
171 iCompleteWriteDfc.SetDfcQ(DfcQ());
176 // override SendMsg method to allow pinning data in the context of the client thread
177 TInt DExampleChannel::SendMsg(TMessageBase* aMsg)
179 TThreadMessage& m=*(TThreadMessage*)aMsg;
182 // we only support one client
183 if (id != (TInt)ECloseMsg && m.Client() != iClient)
184 return KErrAccessDenied;
187 if (id != (TInt)ECloseMsg && id != KMaxTInt)
191 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
192 r = SendRequest(aMsg);
194 Kern::RequestComplete(pS,r);
197 r = SendControl(aMsg);
200 r = DLogicalChannel::SendMsg(aMsg);
205 void DExampleChannel::HandleMsg(TMessageBase* aMsg)
207 TThreadMessage& m=*(TThreadMessage*)aMsg;
210 if (id==(TInt)ECloseMsg)
213 m.Complete(KErrNone,EFalse);
216 else if (id==KMaxTInt)
220 m.Complete(KErrNone,ETrue);
226 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
227 DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
228 m.Complete(KErrNone,ETrue);
233 TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
238 TInt DExampleChannel::SendControl(TMessageBase* aMsg)
240 TThreadMessage& m=*(TThreadMessage*)aMsg;
243 // thread-local copy of configuration data
244 TConfigData kernelConfigBuffer;
245 TAny* userConfigPtr = m.Ptr0();
249 case RPagingExample::ESetConfig:
250 // copy config from client to local buffer in context of client thread
251 umemget32(&kernelConfigBuffer, userConfigPtr, sizeof(TConfigData));
252 // update message to point to kernel-side buffer
253 m.iArg[0] = &kernelConfigBuffer;
256 case RPagingExample::EGetConfig:
257 // update message to point to kernel-side buffer
258 m.iArg[0] = &kernelConfigBuffer;
262 TInt r = DLogicalChannel::SendMsg(aMsg);
268 case RPagingExample::EGetConfig:
269 // copy config from local bufferto client in context of client thread
270 umemput32(userConfigPtr, &kernelConfigBuffer, sizeof(TConfigData));
277 TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
280 TConfigData* configBuffer = (TConfigData*)a1;
283 case RPagingExample::EGetConfig:
284 // copy current config into local buffer in context of DFC thread to avoid potential race conditions
285 *configBuffer = iConfig;
288 case RPagingExample::ESetConfig:
289 // set config from copy in local buffer in context of DFC thread to avoid potential race conditions
290 SetConfig(*configBuffer);
294 r = KErrNotSupported;
299 TInt DExampleChannel::SendRequest(TMessageBase* aMsg)
301 TThreadMessage& m=*(TThreadMessage*)aMsg;
302 TInt function = ~m.iValue;
303 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
307 TInt r = KErrNotSupported;
310 case RPagingExample::ERequestNotify:
314 case RPagingExample::ERequestAsyncGetValue:
315 r = PreAsyncGetValue((TInt*)a1, pS);
318 case RPagingExample::ERequestAsyncGetValue2:
319 r = PreAsyncGetValue2((TInt*)a1, (TInt*)a2, pS);
322 case RPagingExample::ERequestRead:
323 r = PreRead(a1, (TInt)a2, pS);
326 case RPagingExample::ERequestReadDes:
327 r = PreReadDes((TDes8*)a1, pS);
330 case RPagingExample::ERequestWrite:
331 r = PreWrite(a1, (TInt)a2, pS);
334 case RPagingExample::ERequestWriteDes:
335 r = PreWriteDes((TDes8*)a1, pS);
340 r = DLogicalChannel::SendMsg(aMsg);
344 void DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* /*aStatus*/, TAny* /*a1*/, TAny* /*a2*/)
348 case RPagingExample::ERequestNotify:
352 case RPagingExample::ERequestAsyncGetValue:
353 StartAsyncGetValue();
356 case RPagingExample::ERequestAsyncGetValue2:
357 StartAsyncGetValue2();
360 case RPagingExample::ERequestRead:
364 case RPagingExample::ERequestReadDes:
368 case RPagingExample::ERequestWrite:
372 case RPagingExample::ERequestWriteDes:
377 __NK_ASSERT_ALWAYS(EFalse); // we already validated the request number
381 TInt DExampleChannel::DoCancel(TUint /*aMask*/)
383 if (iAsyncGetValueRequest->IsReady())
385 iAsyncGetValueTimer.Cancel();
386 iAsyncGetValueDfc.Cancel();
387 Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrCancel);
390 if (iAsyncGetValue2Request->IsReady())
392 iAsyncGetValue2Timer.Cancel();
393 iAsyncGetValue2Dfc.Cancel();
394 Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrCancel);
397 if (iReadRequest->IsReady())
400 iCompleteReadDfc.Cancel();
401 Kern::QueueBufferRequestComplete(iClient, iReadRequest, KErrCancel);
404 if (iWriteRequest->IsReady())
406 iWriteTimer.Cancel();
407 iCompleteWriteDfc.Cancel();
408 Kern::QueueBufferRequestComplete(iClient, iWriteRequest, KErrCancel);
414 void DExampleChannel::Shutdown()
418 void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
420 iConfig = aNewConfig;
423 TInt DExampleChannel::PreNotify(TRequestStatus* aStatus)
425 return iNotifyRequest->SetStatus(aStatus);
428 void DExampleChannel::StartNotify()
430 CompleteNotify(); // example implementation completes the request immediately
433 void DExampleChannel::CompleteNotify()
435 Kern::QueueRequestComplete(iClient, iNotifyRequest, KErrNone);
438 TInt DExampleChannel::PreAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
440 TInt r = iAsyncGetValueRequest->SetStatus(aStatus);
443 iAsyncGetValueRequest->SetDestPtr(aValue);
447 void DExampleChannel::StartAsyncGetValue()
449 // queue a timer to simulate an asynchronous operation
450 iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
453 void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
455 DExampleChannel* self = (DExampleChannel*)aPtr;
456 self->CompleteAsyncGetValue();
459 void DExampleChannel::CompleteAsyncGetValue()
461 iAsyncGetValueRequest->Data().iValue1 = 1;
462 iAsyncGetValueRequest->Data().iValue2 = _L8("shrt");
463 Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrNone);
466 TInt DExampleChannel::PreAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
468 TInt r = iAsyncGetValue2Request->SetStatus(aStatus);
471 iAsyncGetValue2Request->SetDestPtr1(aValue1);
472 iAsyncGetValue2Request->SetDestPtr2(aValue2);
476 void DExampleChannel::StartAsyncGetValue2()
478 // queue a timer to simulate an asynchronous operation
479 iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
482 void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
484 DExampleChannel* self = (DExampleChannel*)aPtr;
485 self->CompleteAsyncGetValue2();
488 void DExampleChannel::CompleteAsyncGetValue2()
490 iAsyncGetValue2Request->Data1() = 1;
491 iAsyncGetValue2Request->Data2() = 2;
492 Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrNone);
495 TInt DExampleChannel::PreRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
497 // check length argument first
498 if (aLength < 1 || aLength > KBufferSize)
501 // start request setup
502 TInt r = iReadRequest->StartSetup(aStatus);
506 // add client buffer, this does pinning in context of client thread
507 r = iReadRequest->AddBuffer(iClientReadBuffer, (TLinAddr)aBuffer, aLength, ETrue);
511 iReadRequest->EndSetup();
515 void DExampleChannel::StartRead()
517 ReceiveToReadBuffer(); // called in DFC thread as may require serialised access to hardware
520 TInt DExampleChannel::PreReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
522 // start request setup
523 TInt r = iReadRequest->StartSetup(aStatus);
527 // add client descriptor, this does pinning in context of client thread
528 r = iReadRequest->AddBuffer(iClientReadBuffer, aDesOut);
532 // can check length argument here
533 TInt length = iClientReadBuffer->MaxLength();
534 if (length < 1 || length > KBufferSize)
536 // need to reset object so it can be reused
537 iReadRequest->Reset();
541 iReadRequest->EndSetup();
545 void DExampleChannel::StartReadDes()
547 ReceiveToReadBuffer(); // called in DFC thread as may require serialised access to hardware
550 TInt DExampleChannel::PreWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
552 // check length argument first
553 if (aLength < 1 || aLength > KBufferSize)
556 // demonstrate use the single-buffer version of Setup
557 return iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TLinAddr)aBuffer, aLength);
560 void DExampleChannel::StartWrite()
562 SendFromWriteBuffer(); // called in DFC thread as may require serialised access to hardware
565 TInt DExampleChannel::PreWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
567 // demonstrate use the single-buffer version of Setup
568 TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TAny*)aDesIn);
572 // can check length argument here
573 TInt length = iClientWriteBuffer->Length();
574 if (length < 1 || length > KBufferSize)
576 // need to reset object so it can be reused
577 iWriteRequest->Reset();
584 void DExampleChannel::StartWriteDes()
586 SendFromWriteBuffer(); // called in DFC thread as may require serialised access to hardware
589 void DExampleChannel::ReceiveToReadBuffer()
591 // just queue a timer to simulate an asynchronous receive operation
592 // actually will return the previous contents of the buffer
593 iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc);
596 void DExampleChannel::SendFromWriteBuffer()
598 // just queue a timer to simulate an asynchronous send operation
599 iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
602 void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
604 DExampleChannel* self = (DExampleChannel*)aPtr;
605 self->CompleteRead();
608 void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
610 DExampleChannel* self = (DExampleChannel*)aPtr;
611 self->CompleteWrite();
614 void DExampleChannel::CompleteRead()
616 TPtrC8 des(iBuffer, iClientReadBuffer->MaxLength());
617 TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, des, 0, KChunkShiftBy0, iClient);
618 Kern::QueueBufferRequestComplete(iClient, iReadRequest, r);
621 void DExampleChannel::CompleteWrite()
623 TPtr8 des(iBuffer, iClientWriteBuffer->Length());
624 TInt r = Kern::ThreadBufRead(iClient, iClientWriteBuffer, des, 0, KChunkShiftBy0);
625 Kern::QueueBufferRequestComplete(iClient, iWriteRequest, r);
632 class DExampleFactory : public DLogicalDevice
636 virtual TInt Install();
637 virtual void GetCaps(TDes8& aDes) const;
638 virtual TInt Create(DLogicalChannelBase*& aChannel);
641 DExampleFactory::DExampleFactory()
644 iVersion = TVersion(1, 0, 0);
647 TInt DExampleFactory::Install()
649 return SetName(&KPagingExample1PostLdd);
652 void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
654 // not used but required as DLogicalDevice::GetCaps is pure virtual
657 TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
659 aChannel = new DExampleChannel;
660 return aChannel ? KErrNone : KErrNoMemory;
663 DECLARE_STANDARD_LDD()
665 return new DExampleFactory;