kerneltest/e32test/demandpaging/d_pagingexample_1_post.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    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
       
    17 // 
       
    18 //
       
    19 
       
    20 #include "d_pagingexample.h"
       
    21 #include <kernel/kernel.h>
       
    22 #include <kernel/kern_priv.h>
       
    23 
       
    24 const TInt KDfcQThreadPriority = 25;
       
    25 const TInt KBufferSize = KMaxTransferSize;
       
    26 
       
    27 //
       
    28 // Logical channel
       
    29 //
       
    30 
       
    31 class DExampleChannel : public DLogicalChannel
       
    32 	{
       
    33 public:
       
    34 	typedef RPagingExample::TConfigData TConfigData;
       
    35 	typedef RPagingExample::TValueStruct TValueStruct;
       
    36 public:
       
    37 	DExampleChannel();
       
    38 	~DExampleChannel();
       
    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);
       
    47 private:
       
    48 	TDfcQue* DfcQ();
       
    49 	void Shutdown();
       
    50 	void SetConfig(const TConfigData&);
       
    51 	TInt PreNotify(TRequestStatus* aStatus);
       
    52 	void StartNotify();
       
    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);
       
    58 	void StartRead();
       
    59 	TInt PreReadDes(TDes8* aDesOut, TRequestStatus* aStatus);
       
    60 	void StartReadDes();
       
    61 	TInt PreWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
       
    62 	void StartWrite();
       
    63 	TInt PreWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus);
       
    64 	void StartWriteDes();
       
    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();
       
    74 	void CompleteRead();
       
    75 	void CompleteWrite();
       
    76 private:
       
    77 	TDynamicDfcQue* iDynamicDfcQ;
       
    78 	TConfigData iConfig;
       
    79 	DThread* iClient;
       
    80 	
       
    81 	// Notify
       
    82 	TClientRequest* iNotifyRequest;
       
    83 	
       
    84 	// Async get value
       
    85 	TClientDataRequest<TValueStruct>* iAsyncGetValueRequest;
       
    86 	NTimer iAsyncGetValueTimer;
       
    87 	TDfc iAsyncGetValueDfc;
       
    88 	
       
    89 	// Async get value 2
       
    90 	TClientDataRequest2<TInt,TInt>* iAsyncGetValue2Request;
       
    91 	NTimer iAsyncGetValue2Timer;
       
    92 	TDfc iAsyncGetValue2Dfc;
       
    93 	
       
    94 	// Read
       
    95 	TClientBufferRequest* iReadRequest;
       
    96 	NTimer iReadTimer;
       
    97 	TClientBuffer* iClientReadBuffer;
       
    98 	TDfc iCompleteReadDfc;
       
    99 	
       
   100 	// Write
       
   101 	TClientBufferRequest* iWriteRequest;
       
   102 	NTimer iWriteTimer;
       
   103 	TClientBuffer* iClientWriteBuffer;
       
   104 	TDfc iCompleteWriteDfc;
       
   105 	TUint8 iBuffer[KBufferSize];
       
   106 	};
       
   107 
       
   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)
       
   117 	{
       
   118 	iClient = &Kern::CurrentThread();
       
   119 	iClient->Open();
       
   120 	}
       
   121 
       
   122 DExampleChannel::~DExampleChannel()
       
   123 	{
       
   124 	Kern::SafeClose((DObject*&)iClient, NULL);
       
   125 	if (iDynamicDfcQ)
       
   126 		iDynamicDfcQ->Destroy();
       
   127 	Kern::DestroyClientRequest(iNotifyRequest);
       
   128 	Kern::DestroyClientRequest(iAsyncGetValueRequest);
       
   129 	Kern::DestroyClientRequest(iAsyncGetValue2Request);
       
   130 	Kern::DestroyClientBufferRequest(iReadRequest);
       
   131 	Kern::DestroyClientBufferRequest(iWriteRequest);
       
   132 	}
       
   133 
       
   134 TDfcQue* DExampleChannel::DfcQ()
       
   135 	{
       
   136 	return iDynamicDfcQ;
       
   137 	}
       
   138 
       
   139 TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
       
   140 	{
       
   141 	TInt r;
       
   142 	
       
   143 	r = Kern::CreateClientRequest(iNotifyRequest);
       
   144 	if (r != KErrNone)
       
   145 		return r;
       
   146 	r = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
       
   147 	if (r != KErrNone)
       
   148 		return r;
       
   149 	r = Kern::CreateClientDataRequest2(iAsyncGetValue2Request);
       
   150 	if (r != KErrNone)
       
   151 		return r;
       
   152 	r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
       
   153 	if (r != KErrNone)
       
   154 		return r;
       
   155 	r = Kern::CreateClientBufferRequest(iWriteRequest, 1, TClientBufferRequest::EPinVirtual);
       
   156 	if (r != KErrNone)
       
   157 		return r;
       
   158 	
       
   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);
       
   161 	if (r != KErrNone)
       
   162 		return r;
       
   163 
       
   164 	// todo: this will be the default anyway
       
   165 	iDynamicDfcQ->SetRealtimeState(ERealtimeStateOn);
       
   166 	
       
   167 	SetDfcQ(DfcQ());
       
   168 	iAsyncGetValueDfc.SetDfcQ(DfcQ());
       
   169 	iAsyncGetValue2Dfc.SetDfcQ(DfcQ());
       
   170 	iCompleteReadDfc.SetDfcQ(DfcQ());
       
   171 	iCompleteWriteDfc.SetDfcQ(DfcQ());
       
   172 	iMsgQ.Receive();
       
   173 	return KErrNone;
       
   174 	}
       
   175 
       
   176 // override SendMsg method to allow pinning data in the context of the client thread
       
   177 TInt DExampleChannel::SendMsg(TMessageBase* aMsg)
       
   178 	{
       
   179 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   180     TInt id = m.iValue;
       
   181 
       
   182 	// we only support one client
       
   183 	if (id != (TInt)ECloseMsg && m.Client() != iClient)
       
   184 		return KErrAccessDenied;
       
   185 	
       
   186 	TInt r = KErrNone;
       
   187 	if (id != (TInt)ECloseMsg && id != KMaxTInt)
       
   188 		{
       
   189 		if (id<0)
       
   190 			{
       
   191 			TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   192 			r = SendRequest(aMsg);
       
   193 			if (r != KErrNone)
       
   194 				Kern::RequestComplete(pS,r);
       
   195 			}
       
   196 		else
       
   197 			r = SendControl(aMsg);
       
   198 		}
       
   199 	else
       
   200 		r = DLogicalChannel::SendMsg(aMsg);
       
   201 	
       
   202 	return r;
       
   203 	}
       
   204 
       
   205 void DExampleChannel::HandleMsg(TMessageBase* aMsg)
       
   206 	{
       
   207 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   208     TInt id=m.iValue;
       
   209 	
       
   210 	if (id==(TInt)ECloseMsg)
       
   211 		{
       
   212 		Shutdown();
       
   213 		m.Complete(KErrNone,EFalse);
       
   214 		return;
       
   215 		}
       
   216     else if (id==KMaxTInt)
       
   217 		{
       
   218 		// DoCancel
       
   219 		DoCancel(m.Int0());
       
   220 		m.Complete(KErrNone,ETrue);
       
   221 		return;
       
   222 		}
       
   223     else if (id<0)
       
   224 		{
       
   225 		// DoRequest
       
   226 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   227 		DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
       
   228 		m.Complete(KErrNone,ETrue);
       
   229 		}
       
   230     else
       
   231 		{
       
   232 		// DoControl
       
   233 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   234 		m.Complete(r,ETrue);
       
   235 		}
       
   236 	}
       
   237 	
       
   238 TInt DExampleChannel::SendControl(TMessageBase* aMsg)
       
   239 	{
       
   240 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   241     TInt id=m.iValue;
       
   242 
       
   243 	// thread-local copy of configuration data
       
   244 	TConfigData kernelConfigBuffer;
       
   245 	TAny* userConfigPtr = m.Ptr0();
       
   246 	
       
   247 	switch (id)
       
   248 		{
       
   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;
       
   254 			break;
       
   255 			
       
   256 		case RPagingExample::EGetConfig:
       
   257 			// update message to point to kernel-side buffer
       
   258 			m.iArg[0] = &kernelConfigBuffer;
       
   259 			break;
       
   260 		}
       
   261 
       
   262 	TInt r = DLogicalChannel::SendMsg(aMsg);
       
   263 	if (r != KErrNone)
       
   264 		return r;
       
   265 
       
   266 	switch (id)
       
   267 		{
       
   268 		case RPagingExample::EGetConfig:
       
   269 			// copy config from local bufferto client in context of client thread
       
   270 			umemput32(userConfigPtr, &kernelConfigBuffer, sizeof(TConfigData));
       
   271 			break;
       
   272 		}
       
   273 
       
   274 	return r;
       
   275 	}
       
   276 
       
   277 TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
       
   278 	{
       
   279 	TInt r = KErrNone;
       
   280 	TConfigData* configBuffer = (TConfigData*)a1;
       
   281 	switch (aFunction)
       
   282 		{
       
   283 		case RPagingExample::EGetConfig:
       
   284 			// copy current config into local buffer in context of DFC thread to avoid potential race conditions
       
   285 			*configBuffer = iConfig;
       
   286 			break;
       
   287 
       
   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);
       
   291 			break;
       
   292 
       
   293 		default:
       
   294 			r = KErrNotSupported;
       
   295 		}
       
   296 	return r;
       
   297 	}
       
   298 
       
   299 TInt DExampleChannel::SendRequest(TMessageBase* aMsg)
       
   300 	{
       
   301 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   302     TInt function = ~m.iValue;
       
   303 	TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   304 	TAny* a1 = m.Ptr1();
       
   305 	TAny* a2 = m.Ptr2();
       
   306 		
       
   307 	TInt r = KErrNotSupported;
       
   308 	switch (function)
       
   309 		{
       
   310 		case RPagingExample::ERequestNotify:
       
   311 			r = PreNotify(pS);
       
   312 			break;
       
   313 
       
   314 		case RPagingExample::ERequestAsyncGetValue:
       
   315 			r = PreAsyncGetValue((TInt*)a1, pS);
       
   316 			break;
       
   317 
       
   318 		case RPagingExample::ERequestAsyncGetValue2:
       
   319 			r = PreAsyncGetValue2((TInt*)a1, (TInt*)a2, pS);
       
   320 			break;
       
   321 			
       
   322 		case RPagingExample::ERequestRead:
       
   323 			r = PreRead(a1, (TInt)a2, pS);
       
   324 			break;
       
   325 			
       
   326 		case RPagingExample::ERequestReadDes:
       
   327 			r = PreReadDes((TDes8*)a1, pS);
       
   328 			break;
       
   329 
       
   330 		case RPagingExample::ERequestWrite:
       
   331 			r = PreWrite(a1, (TInt)a2, pS);
       
   332 			break;
       
   333 			
       
   334 		case RPagingExample::ERequestWriteDes:
       
   335 			r = PreWriteDes((TDes8*)a1, pS);
       
   336 			break;
       
   337 		}
       
   338 
       
   339 	if (r == KErrNone)
       
   340 		r = DLogicalChannel::SendMsg(aMsg);
       
   341 	return r;
       
   342 	}
       
   343 
       
   344 void DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* /*aStatus*/, TAny* /*a1*/, TAny* /*a2*/)
       
   345 	{
       
   346 	switch (aFunction)
       
   347 		{
       
   348 		case RPagingExample::ERequestNotify:
       
   349 			StartNotify();
       
   350 			break;
       
   351 			
       
   352 		case RPagingExample::ERequestAsyncGetValue:
       
   353 			StartAsyncGetValue();
       
   354 			break;
       
   355 			
       
   356 		case RPagingExample::ERequestAsyncGetValue2:
       
   357 			StartAsyncGetValue2();
       
   358 			break;
       
   359 			
       
   360 		case RPagingExample::ERequestRead:
       
   361 			StartRead();
       
   362 			break;
       
   363 			
       
   364 		case RPagingExample::ERequestReadDes:
       
   365 			StartReadDes();
       
   366 			break;
       
   367 
       
   368 		case RPagingExample::ERequestWrite:
       
   369 			StartWrite();
       
   370 			break;
       
   371 			
       
   372 		case RPagingExample::ERequestWriteDes:
       
   373 			StartWriteDes();
       
   374 			break;
       
   375 
       
   376 		default:
       
   377 			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
       
   378 		}
       
   379 	}
       
   380 
       
   381 TInt DExampleChannel::DoCancel(TUint /*aMask*/)
       
   382 	{
       
   383 	if (iAsyncGetValueRequest->IsReady())	
       
   384 		{
       
   385 		iAsyncGetValueTimer.Cancel();
       
   386 		iAsyncGetValueDfc.Cancel();
       
   387 		Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrCancel);
       
   388 		}
       
   389 	
       
   390 	if (iAsyncGetValue2Request->IsReady())
       
   391 		{
       
   392 		iAsyncGetValue2Timer.Cancel();
       
   393 		iAsyncGetValue2Dfc.Cancel();
       
   394 		Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrCancel);
       
   395 		}
       
   396 	
       
   397 	if (iReadRequest->IsReady())
       
   398 		{
       
   399 		iReadTimer.Cancel();
       
   400 		iCompleteReadDfc.Cancel();
       
   401 		Kern::QueueBufferRequestComplete(iClient, iReadRequest, KErrCancel);
       
   402 		}
       
   403 	
       
   404 	if (iWriteRequest->IsReady())
       
   405 		{
       
   406 		iWriteTimer.Cancel();
       
   407 		iCompleteWriteDfc.Cancel();
       
   408 		Kern::QueueBufferRequestComplete(iClient, iWriteRequest, KErrCancel);
       
   409 		}
       
   410 	
       
   411 	return KErrNone;
       
   412 	}
       
   413 
       
   414 void DExampleChannel::Shutdown()
       
   415 	{
       
   416 	}
       
   417 
       
   418 void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
       
   419 	{
       
   420 	iConfig = aNewConfig;
       
   421 	}
       
   422 
       
   423 TInt DExampleChannel::PreNotify(TRequestStatus* aStatus)
       
   424 	{
       
   425 	return iNotifyRequest->SetStatus(aStatus);
       
   426 	}
       
   427 
       
   428 void DExampleChannel::StartNotify()
       
   429 	{
       
   430 	CompleteNotify(); // example implementation completes the request immediately
       
   431 	}
       
   432 
       
   433 void DExampleChannel::CompleteNotify()
       
   434 	{
       
   435 	Kern::QueueRequestComplete(iClient, iNotifyRequest, KErrNone);
       
   436 	}
       
   437 
       
   438 TInt DExampleChannel::PreAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
       
   439 	{
       
   440 	TInt r = iAsyncGetValueRequest->SetStatus(aStatus);
       
   441 	if (r != KErrNone)
       
   442 		return r;
       
   443 	iAsyncGetValueRequest->SetDestPtr(aValue);
       
   444 	return KErrNone;
       
   445 	}
       
   446 
       
   447 void DExampleChannel::StartAsyncGetValue()
       
   448 	{
       
   449 	// queue a timer to simulate an asynchronous operation
       
   450 	iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
       
   451 	}
       
   452 
       
   453 void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
       
   454 	{
       
   455 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   456 	self->CompleteAsyncGetValue();
       
   457 	}
       
   458 
       
   459 void DExampleChannel::CompleteAsyncGetValue()
       
   460 	{
       
   461 	iAsyncGetValueRequest->Data().iValue1 = 1;
       
   462 	iAsyncGetValueRequest->Data().iValue2 = _L8("shrt");
       
   463 	Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrNone);
       
   464 	}
       
   465 
       
   466 TInt DExampleChannel::PreAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
       
   467 	{
       
   468 	TInt r = iAsyncGetValue2Request->SetStatus(aStatus);
       
   469 	if (r != KErrNone)
       
   470 		return r;
       
   471 	iAsyncGetValue2Request->SetDestPtr1(aValue1);
       
   472 	iAsyncGetValue2Request->SetDestPtr2(aValue2);
       
   473 	return KErrNone;
       
   474 	}
       
   475 
       
   476 void DExampleChannel::StartAsyncGetValue2()
       
   477 	{
       
   478 	// queue a timer to simulate an asynchronous operation
       
   479 	iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
       
   480 	}
       
   481 
       
   482 void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
       
   483 	{
       
   484 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   485 	self->CompleteAsyncGetValue2();
       
   486 	}
       
   487 
       
   488 void DExampleChannel::CompleteAsyncGetValue2()
       
   489 	{
       
   490 	iAsyncGetValue2Request->Data1() = 1;
       
   491 	iAsyncGetValue2Request->Data2() = 2;
       
   492 	Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrNone);
       
   493 	}
       
   494 
       
   495 TInt DExampleChannel::PreRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
       
   496 	{
       
   497 	// check length argument first
       
   498 	if (aLength < 1 || aLength > KBufferSize)
       
   499 		return KErrArgument;
       
   500 
       
   501 	// start request setup
       
   502 	TInt r = iReadRequest->StartSetup(aStatus);
       
   503 	if (r != KErrNone)
       
   504 		return r;
       
   505 	
       
   506 	// add client buffer, this does pinning in context of client thread
       
   507 	r = iReadRequest->AddBuffer(iClientReadBuffer, (TLinAddr)aBuffer, aLength, ETrue);
       
   508 	if (r != KErrNone)
       
   509 		return KErrNoMemory;
       
   510 
       
   511 	iReadRequest->EndSetup();
       
   512 	return KErrNone;
       
   513 	}
       
   514 
       
   515 void DExampleChannel::StartRead()
       
   516 	{	
       
   517 	ReceiveToReadBuffer(); // called in DFC thread as may require serialised access to hardware
       
   518 	}
       
   519 
       
   520 TInt DExampleChannel::PreReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
       
   521 	{
       
   522 	// start request setup
       
   523 	TInt r = iReadRequest->StartSetup(aStatus);
       
   524 	if (r != KErrNone)
       
   525 		return r;
       
   526 
       
   527 	// add client descriptor, this does pinning in context of client thread
       
   528 	r = iReadRequest->AddBuffer(iClientReadBuffer, aDesOut);
       
   529 	if (r != KErrNone)
       
   530 		return r;
       
   531 
       
   532 	// can check length argument here
       
   533 	TInt length = iClientReadBuffer->MaxLength();
       
   534 	if (length < 1 || length > KBufferSize)
       
   535 		{
       
   536 		// need to reset object so it can be reused
       
   537 		iReadRequest->Reset();
       
   538 		return KErrArgument;
       
   539 		}
       
   540 
       
   541 	iReadRequest->EndSetup();	
       
   542 	return KErrNone;
       
   543 	}
       
   544 
       
   545 void DExampleChannel::StartReadDes()
       
   546 	{
       
   547 	ReceiveToReadBuffer(); // called in DFC thread as may require serialised access to hardware
       
   548 	}
       
   549 
       
   550 TInt DExampleChannel::PreWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
       
   551 	{
       
   552 	// check length argument first
       
   553 	if (aLength < 1 || aLength > KBufferSize)
       
   554 		return KErrArgument;
       
   555 
       
   556 	// demonstrate use the single-buffer version of Setup
       
   557 	return iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TLinAddr)aBuffer, aLength);
       
   558 	}
       
   559 
       
   560 void DExampleChannel::StartWrite()
       
   561 	{
       
   562 	SendFromWriteBuffer(); // called in DFC thread as may require serialised access to hardware
       
   563 	}
       
   564 
       
   565 TInt DExampleChannel::PreWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
       
   566 	{
       
   567 	// demonstrate use the single-buffer version of Setup
       
   568 	TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TAny*)aDesIn);
       
   569 	if (r != KErrNone)
       
   570 		return r;
       
   571 
       
   572 	// can check length argument here
       
   573 	TInt length = iClientWriteBuffer->Length();
       
   574 	if (length < 1 || length > KBufferSize)
       
   575 		{
       
   576 		// need to reset object so it can be reused
       
   577 		iWriteRequest->Reset();
       
   578 		return KErrArgument;
       
   579 		}
       
   580 	
       
   581 	return KErrNone;
       
   582 	}
       
   583 
       
   584 void DExampleChannel::StartWriteDes()
       
   585 	{
       
   586 	SendFromWriteBuffer(); // called in DFC thread as may require serialised access to hardware
       
   587 	}
       
   588 
       
   589 void DExampleChannel::ReceiveToReadBuffer()
       
   590 	{
       
   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);
       
   594 	}
       
   595 
       
   596 void DExampleChannel::SendFromWriteBuffer()
       
   597 	{
       
   598 	// just queue a timer to simulate an asynchronous send operation
       
   599 	iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
       
   600 	}
       
   601 
       
   602 void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
       
   603 	{
       
   604 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   605 	self->CompleteRead();
       
   606 	}
       
   607 
       
   608 void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
       
   609 	{
       
   610 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   611 	self->CompleteWrite();
       
   612 	}
       
   613 
       
   614 void DExampleChannel::CompleteRead()
       
   615 	{
       
   616 	TPtrC8 des(iBuffer, iClientReadBuffer->MaxLength());
       
   617 	TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, des, 0, KChunkShiftBy0, iClient);
       
   618 	Kern::QueueBufferRequestComplete(iClient, iReadRequest, r);
       
   619 	}
       
   620 
       
   621 void DExampleChannel::CompleteWrite()
       
   622 	{
       
   623 	TPtr8 des(iBuffer, iClientWriteBuffer->Length());
       
   624 	TInt r = Kern::ThreadBufRead(iClient, iClientWriteBuffer, des, 0, KChunkShiftBy0);
       
   625 	Kern::QueueBufferRequestComplete(iClient, iWriteRequest, r);
       
   626 	}
       
   627 
       
   628 //
       
   629 // Logical device
       
   630 //
       
   631 
       
   632 class DExampleFactory : public DLogicalDevice
       
   633 	{
       
   634 public:
       
   635 	DExampleFactory();
       
   636 	virtual TInt Install();
       
   637 	virtual void GetCaps(TDes8& aDes) const;
       
   638 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   639 	};
       
   640 
       
   641 DExampleFactory::DExampleFactory()
       
   642 	{
       
   643 	iParseMask = 0;
       
   644 	iVersion = TVersion(1, 0, 0);
       
   645 	}
       
   646 
       
   647 TInt DExampleFactory::Install()
       
   648 	{
       
   649 	return SetName(&KPagingExample1PostLdd);
       
   650 	}
       
   651 
       
   652 void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
       
   653 	{
       
   654 	// not used but required as DLogicalDevice::GetCaps is pure virtual
       
   655 	}
       
   656 
       
   657 TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
       
   658 	{
       
   659 	aChannel = new DExampleChannel;
       
   660 	return aChannel ? KErrNone : KErrNoMemory;
       
   661 	}
       
   662 
       
   663 DECLARE_STANDARD_LDD()
       
   664 	{
       
   665 	return new DExampleFactory;
       
   666 	}