kerneltest/e32test/demandpaging/d_pagingexample_2_post.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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_2_post.cpp
       
    15 // Demand paging migration example device driver d_pagingexample_2_post: a
       
    16 // DLogicalChannelBase-dervied 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 DLogicalChannelBase
       
    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 Request(TInt aReqNo, TAny* a1, TAny* a2);
       
    41 	TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
       
    42 	TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
       
    43 	TInt DoCancel(TUint aMask);
       
    44 private:
       
    45  	TDfcQue* DfcQ();
       
    46 	void Shutdown();
       
    47 	void GetConfig(TConfigData&);
       
    48 	void SetConfig(const TConfigData&);
       
    49 	TInt StartNotify(TRequestStatus* aStatus);
       
    50 	TInt StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus);
       
    51 	TInt StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus);
       
    52 	TInt StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
       
    53 	TInt StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus);
       
    54 	TInt StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
       
    55 	TInt StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus);
       
    56 	void ReceiveToReadBuffer();
       
    57 	void SendFromWriteBuffer();
       
    58 	static void CancelDfcFunc(TAny* aPtr);
       
    59 	static void AsyncGetValueCompleteDfcFunc(TAny* aPtr);
       
    60 	static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr);
       
    61 	static void ReceiveCompleteDfcFunc(TAny* aPtr);
       
    62 	static void SendCompleteDfcFunc(TAny* aPtr);
       
    63 	void CompleteNotify();
       
    64 	void CompleteAsyncGetValue();
       
    65 	void CompleteAsyncGetValue2();
       
    66 	void CompleteRead();
       
    67 	void CompleteWrite();
       
    68 	void Cancel();
       
    69 private:
       
    70 	NFastMutex iLock;
       
    71 	TDynamicDfcQue* iDynamicDfcQ;
       
    72 	TConfigData iConfig;
       
    73 	DThread* iClient;
       
    74 	TDfc iCancelDfc;
       
    75 	
       
    76 	// Notify
       
    77 	TClientRequest* iNotifyRequest;
       
    78 	
       
    79 	// Async get value
       
    80 	TClientDataRequest<TValueStruct>* iAsyncGetValueRequest;
       
    81 	NTimer iAsyncGetValueTimer;
       
    82 	TDfc iAsyncGetValueDfc;
       
    83 
       
    84 	// Async get value
       
    85 	TClientDataRequest2<TInt,TInt>* iAsyncGetValue2Request;
       
    86 	NTimer iAsyncGetValue2Timer;
       
    87 	TDfc iAsyncGetValue2Dfc;
       
    88 
       
    89 	// Read
       
    90 	TClientBufferRequest* iReadRequest;
       
    91 	NTimer iReadTimer;
       
    92 	TClientBuffer* iClientReadBuffer;
       
    93 	TDfc iCompleteReadDfc;
       
    94 	
       
    95 	// Write
       
    96 	TClientBufferRequest* iWriteRequest;
       
    97 	NTimer iWriteTimer;
       
    98 	TClientBuffer* iClientWriteBuffer;
       
    99 	TDfc iCompleteWriteDfc;
       
   100 	TUint8 iBuffer[KBufferSize];
       
   101 	};
       
   102 
       
   103 DExampleChannel::DExampleChannel() :
       
   104 	iCancelDfc(CancelDfcFunc, this, 0),
       
   105 	iAsyncGetValueTimer(NULL, this),
       
   106 	iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, 0),
       
   107 	iAsyncGetValue2Timer(NULL, this),
       
   108 	iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, 0),
       
   109 	iReadTimer(NULL, this),
       
   110 	iCompleteReadDfc(ReceiveCompleteDfcFunc, this, 0),
       
   111 	iWriteTimer(NULL, this),
       
   112 	iCompleteWriteDfc(SendCompleteDfcFunc, this, 0)
       
   113 	{
       
   114 	iClient = &Kern::CurrentThread();
       
   115 	iClient->Open();
       
   116 	}
       
   117 
       
   118 DExampleChannel::~DExampleChannel()
       
   119 	{
       
   120 	Kern::SafeClose((DObject*&)iClient, NULL);
       
   121 	if (iDynamicDfcQ)
       
   122 		iDynamicDfcQ->Destroy();
       
   123 	Kern::DestroyClientRequest(iNotifyRequest);
       
   124 	Kern::DestroyClientRequest(iAsyncGetValueRequest);
       
   125 	Kern::DestroyClientRequest(iAsyncGetValue2Request);
       
   126 	Kern::DestroyClientBufferRequest(iReadRequest);
       
   127 	Kern::DestroyClientBufferRequest(iWriteRequest);
       
   128 	}
       
   129 
       
   130 TDfcQue* DExampleChannel::DfcQ()
       
   131 	{
       
   132 	return iDynamicDfcQ;
       
   133 	}
       
   134 
       
   135 TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
       
   136 	{
       
   137 	TInt r;
       
   138 	
       
   139 	r = Kern::CreateClientRequest(iNotifyRequest);
       
   140 	if (r != KErrNone)
       
   141 		return r;
       
   142 	r = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
       
   143 	if (r != KErrNone)
       
   144 		return r;
       
   145 	r = Kern::CreateClientDataRequest2(iAsyncGetValue2Request);
       
   146 	if (r != KErrNone)
       
   147 		return r;
       
   148 	r = Kern::CreateClientBufferRequest(iWriteRequest, 1, TClientBufferRequest::EPinVirtual);
       
   149 	if (r != KErrNone)
       
   150 		return r;
       
   151 	
       
   152 	// create a dynamic DFC queue, which is used for handling client messages and for our own DFCs
       
   153 	r = Kern::DynamicDfcQCreate(iDynamicDfcQ, KDfcQThreadPriority, KPagingExample1PostLdd);
       
   154 	if (r != KErrNone)
       
   155 		return r;
       
   156 
       
   157 	// todo: this will be the default anyway
       
   158 	iDynamicDfcQ->SetRealtimeState(ERealtimeStateOn);
       
   159 	
       
   160 	iCancelDfc.SetDfcQ(DfcQ());
       
   161 	iAsyncGetValueDfc.SetDfcQ(DfcQ());
       
   162 	iAsyncGetValue2Dfc.SetDfcQ(DfcQ());
       
   163 	iCompleteReadDfc.SetDfcQ(DfcQ());
       
   164 	iCompleteWriteDfc.SetDfcQ(DfcQ());
       
   165 	return KErrNone;
       
   166 	}
       
   167 
       
   168 TInt DExampleChannel::Request(TInt aReqNo, TAny* a1, TAny* a2)
       
   169 	{
       
   170 	TInt r = KErrNone;
       
   171 	if (&Kern::CurrentThread() != iClient)
       
   172 		r = KErrAccessDenied;  // we only support one client
       
   173 	else if (aReqNo==KMaxTInt)
       
   174 		{
       
   175 		// DoCancel
       
   176 		r = DoCancel((TInt)a1);
       
   177 		}
       
   178     else if (aReqNo<0)
       
   179 		{
       
   180 		// DoRequest
       
   181 		TRequestStatus* pS=(TRequestStatus*)a1;
       
   182 		TAny* array[2] = { NULL, NULL };
       
   183 		kumemget32(array, a2, 2 * sizeof(TAny*));
       
   184 		r = DoRequest(~aReqNo, pS, array[0], array[1]);
       
   185 		if(r != KErrNone)
       
   186 			Kern::RequestComplete(pS, r);
       
   187 		r = KErrNone;
       
   188 		}
       
   189     else
       
   190 		{
       
   191 		// DoControl
       
   192 		r = DoControl(aReqNo, a1, a2);
       
   193 		}
       
   194 	return r;
       
   195 	}
       
   196 
       
   197 TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
       
   198 	{
       
   199 	TInt r = KErrNone;
       
   200 	TConfigData configBuffer;
       
   201 	switch (aFunction)
       
   202 		{
       
   203 		case RPagingExample::EGetConfig:
       
   204 			GetConfig(configBuffer);
       
   205 			umemput32(a1, (TAny*)&configBuffer, sizeof(TConfigData));
       
   206 			break;
       
   207 
       
   208 		case RPagingExample::ESetConfig:
       
   209 			umemget32(&configBuffer, a1, sizeof(TConfigData));
       
   210 			SetConfig(configBuffer);
       
   211 			break;
       
   212 
       
   213 		default:
       
   214 			r = KErrNotSupported;
       
   215 		}
       
   216 	return r;
       
   217 	}
       
   218 
       
   219 TInt DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
   220 	{
       
   221 	TInt r = KErrNotSupported;
       
   222 	switch (aFunction)
       
   223 		{
       
   224 		case RPagingExample::ERequestNotify:
       
   225 			r = StartNotify(aStatus);
       
   226 			break;
       
   227 			
       
   228 		case RPagingExample::ERequestAsyncGetValue:
       
   229 			r = StartAsyncGetValue((TInt*)a1, aStatus);
       
   230 			break;
       
   231 			
       
   232 		case RPagingExample::ERequestAsyncGetValue2:
       
   233 			r = StartAsyncGetValue2((TInt*)a1, (TInt*)a2, aStatus);
       
   234 			break;
       
   235 			
       
   236 		case RPagingExample::ERequestRead:
       
   237 			r = StartRead(a1, (TInt)a2, aStatus);
       
   238 			break;
       
   239 			
       
   240 		case RPagingExample::ERequestReadDes:
       
   241 			r = StartReadDes((TDes8*)a1, aStatus);
       
   242 			break;
       
   243 
       
   244 		case RPagingExample::ERequestWrite:
       
   245 			r = StartWrite(a1, (TInt)a2, aStatus);
       
   246 			break;
       
   247 			
       
   248 		case RPagingExample::ERequestWriteDes:
       
   249 			r = StartWriteDes((TDes8*)a1, aStatus);
       
   250 			break;
       
   251 		}
       
   252 	return r;
       
   253 	}
       
   254 
       
   255 TInt DExampleChannel::DoCancel(TUint /*aMask*/)
       
   256 	{
       
   257 	iCancelDfc.Enque();
       
   258 	return KErrNone;
       
   259 	}
       
   260 
       
   261 void DExampleChannel::CancelDfcFunc(TAny* aPtr)
       
   262 	{
       
   263 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   264 	self->Cancel();
       
   265 	}
       
   266 
       
   267 void DExampleChannel::Cancel()
       
   268 	{
       
   269 	if (iAsyncGetValueRequest->IsReady())
       
   270 		{
       
   271 		iAsyncGetValueTimer.Cancel();
       
   272 		iAsyncGetValueDfc.Cancel();
       
   273 		Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrCancel);
       
   274 		}
       
   275 	
       
   276 	if (iAsyncGetValue2Request->IsReady())
       
   277 		{
       
   278 		iAsyncGetValue2Timer.Cancel();
       
   279 		iAsyncGetValue2Dfc.Cancel();
       
   280 		Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrCancel);
       
   281 		}
       
   282 
       
   283 	if (iReadRequest && iReadRequest->IsReady())
       
   284 		{
       
   285 		iReadTimer.Cancel();
       
   286 		iCompleteReadDfc.Cancel();
       
   287 		Kern::QueueBufferRequestComplete(iClient, iReadRequest, KErrCancel);
       
   288 		Kern::DestroyClientBufferRequest(iReadRequest);
       
   289 		}
       
   290 
       
   291 	if (iWriteRequest->IsReady())
       
   292 		{
       
   293 		iWriteTimer.Cancel();
       
   294 		iCompleteWriteDfc.Cancel();
       
   295 		Kern::QueueBufferRequestComplete(iClient, iWriteRequest, KErrCancel);
       
   296 		}
       
   297 	}
       
   298 
       
   299 void DExampleChannel::Shutdown()
       
   300 	{
       
   301 	}
       
   302 
       
   303 void DExampleChannel::GetConfig(TConfigData& aConfigOut)
       
   304 	{
       
   305 	NKern::FMWait(&iLock);
       
   306 	aConfigOut = iConfig;
       
   307 	NKern::FMSignal(&iLock);
       
   308 	}
       
   309 
       
   310 void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
       
   311 	{
       
   312 	NKern::FMWait(&iLock);
       
   313 	iConfig = aNewConfig;
       
   314 	NKern::FMSignal(&iLock);
       
   315 	}
       
   316 
       
   317 TInt DExampleChannel::StartNotify(TRequestStatus* aStatus)
       
   318 	{
       
   319 	// example implementation completes the request immediately
       
   320 	TInt r = iNotifyRequest->SetStatus(aStatus);
       
   321 	if (r != KErrNone)
       
   322 		return r;
       
   323 	CompleteNotify(); // example implementation completes the request immediately
       
   324 	return KErrNone;
       
   325 	}
       
   326 
       
   327 void DExampleChannel::CompleteNotify()
       
   328 	{
       
   329 	Kern::QueueRequestComplete(iClient, iNotifyRequest, KErrNone);
       
   330 	}
       
   331 
       
   332 TInt DExampleChannel::StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
       
   333 	{
       
   334 	// use of TClientDataRequest API protected by fast mutex
       
   335 	NKern::FMWait(&iLock);
       
   336 	TInt r = iAsyncGetValueRequest->SetStatus(aStatus);
       
   337 	if (r == KErrNone)
       
   338 		iAsyncGetValueRequest->SetDestPtr(aValue);
       
   339 	NKern::FMSignal(&iLock);
       
   340 	if (r != KErrNone)
       
   341 		return r;
       
   342 
       
   343 	// queue a timer to simulate an asynchronous operation
       
   344 	iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
       
   345 	return KErrNone;
       
   346 	}
       
   347 
       
   348 void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
       
   349 	{
       
   350 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   351 	self->CompleteAsyncGetValue();
       
   352 	}
       
   353 
       
   354 void DExampleChannel::CompleteAsyncGetValue()
       
   355 	{
       
   356 	// use of TClientDataRequest API protected by fast mutex
       
   357 	NKern::FMWait(&iLock);
       
   358 	if (iAsyncGetValueRequest->IsReady())
       
   359 		{
       
   360 		iAsyncGetValueRequest->Data().iValue1 = 1;
       
   361 		iAsyncGetValueRequest->Data().iValue2 = _L8("shrt");
       
   362 		Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrNone);
       
   363 		}
       
   364 	NKern::FMSignal(&iLock);
       
   365 	}
       
   366 
       
   367 TInt DExampleChannel::StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
       
   368 	{
       
   369 	// use of TClientDataRequest API protected by fast mutex
       
   370 	NKern::FMWait(&iLock);
       
   371 	TInt r = iAsyncGetValue2Request->SetStatus(aStatus);
       
   372 	if (r == KErrNone)
       
   373 		iAsyncGetValue2Request->SetDestPtr1(aValue1);
       
   374 	if (r == KErrNone)
       
   375 		iAsyncGetValue2Request->SetDestPtr2(aValue2);
       
   376 	NKern::FMSignal(&iLock);
       
   377 	if (r != KErrNone)
       
   378 		return r;
       
   379 
       
   380 	// queue a timer to simulate an asynchronous operation
       
   381 	iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
       
   382 	return KErrNone;
       
   383 	}
       
   384 
       
   385 void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
       
   386 	{
       
   387 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   388 	self->CompleteAsyncGetValue2();
       
   389 	}
       
   390 
       
   391 void DExampleChannel::CompleteAsyncGetValue2()
       
   392 	{
       
   393 	// use of TClientDataRequest API protected by fast mutex
       
   394 	NKern::FMWait(&iLock);
       
   395 	if (iAsyncGetValue2Request->IsReady())
       
   396 		{
       
   397 		iAsyncGetValue2Request->Data1() = 1;
       
   398 		iAsyncGetValue2Request->Data2() = 2;
       
   399 		Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrNone);
       
   400 		}
       
   401 	NKern::FMSignal(&iLock);
       
   402 	}
       
   403 
       
   404 TInt DExampleChannel::StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
       
   405 	{
       
   406 	// check length argument first
       
   407 	if (aLength < 1 || aLength > KBufferSize)
       
   408 		return KErrArgument;
       
   409 
       
   410 	// normally drivers would pre-create a TClientBufferRequest where possible, but here we create
       
   411 	// one on demand to test this possibilty
       
   412 	NKern::ThreadEnterCS();
       
   413 	TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
       
   414 	NKern::ThreadLeaveCS();  // iReadRequest is deleted by the destructor
       
   415 	if (r != KErrNone)
       
   416 		return r;
       
   417 
       
   418 	// start request setup
       
   419 	r = iReadRequest->StartSetup(aStatus);
       
   420 	if (r != KErrNone)
       
   421 		return r;
       
   422 	
       
   423 	// add client buffer, this does pinning in context of client thread
       
   424 	r = iReadRequest->AddBuffer(iClientReadBuffer, (TLinAddr)aBuffer, aLength, ETrue);
       
   425 	if (r != KErrNone)
       
   426 		return KErrNoMemory;
       
   427 
       
   428 	iReadRequest->EndSetup();
       
   429 	
       
   430 	ReceiveToReadBuffer();
       
   431 	return KErrNone;
       
   432 	}
       
   433 
       
   434 TInt DExampleChannel::StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
       
   435 	{
       
   436 	// normally drivers would pre-create a TClientBufferRequest where possible, but here we create
       
   437 	// one on demand to test this possibilty
       
   438 	NKern::ThreadEnterCS();
       
   439 	TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
       
   440 	NKern::ThreadLeaveCS();  // iReadRequest is deleted by the destructor
       
   441 	if (r != KErrNone)
       
   442 		return r;
       
   443 	
       
   444 	// start request setup
       
   445 	r = iReadRequest->StartSetup(aStatus);
       
   446 	if (r != KErrNone)
       
   447 		return r;
       
   448 
       
   449 	// add client descriptor, this does pinning in context of client thread
       
   450 	r = iReadRequest->AddBuffer(iClientReadBuffer, aDesOut);
       
   451 	if (r != KErrNone)
       
   452 		return r;
       
   453 
       
   454 	// can check length argument here
       
   455 	TInt length = iClientReadBuffer->MaxLength();
       
   456 	if (length < 1 || length > KBufferSize)
       
   457 		{
       
   458 		// need to reset object so it can be reused
       
   459 		iReadRequest->Reset();
       
   460 		return KErrArgument;
       
   461 		}
       
   462 
       
   463 	iReadRequest->EndSetup();	
       
   464 
       
   465 	ReceiveToReadBuffer();
       
   466 	return KErrNone;
       
   467 	}
       
   468 
       
   469 TInt DExampleChannel::StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
       
   470 	{
       
   471 	// check length argument first
       
   472 	if (aLength < 1 || aLength > KBufferSize)
       
   473 		return KErrArgument;
       
   474 
       
   475 	// demonstrate use the single-buffer version of Setup
       
   476 	TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TLinAddr)aBuffer, aLength);
       
   477 	if (r != KErrNone)
       
   478 		return r;
       
   479 
       
   480 	SendFromWriteBuffer();
       
   481 	return KErrNone;
       
   482 	}
       
   483 
       
   484 TInt DExampleChannel::StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
       
   485 	{
       
   486 	// demonstrate use the single-buffer version of Setup
       
   487 	TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TAny*)aDesIn);
       
   488 	if (r != KErrNone)
       
   489 		return r;
       
   490 
       
   491 	// can check length argument here
       
   492 	TInt length = iClientWriteBuffer->Length();
       
   493 	if (length < 1 || length > KBufferSize)
       
   494 		{
       
   495 		// need to reset object so it can be reused
       
   496 		iWriteRequest->Reset();
       
   497 		return KErrArgument;
       
   498 		}
       
   499 	
       
   500 	SendFromWriteBuffer();
       
   501 	return KErrNone;
       
   502 	}
       
   503 
       
   504 void DExampleChannel::ReceiveToReadBuffer()
       
   505 	{
       
   506 	// just queue a timer to simulate an asynchronous receive operation
       
   507 	// actually will return the previous contents of the buffer
       
   508 	NKern::FMWait(&iLock);
       
   509 	// The synchonisation is for illustrative purposes only - in a real driver we might make use of
       
   510 	// the configution here, so this would need to be protected from concurrent modification.
       
   511 	NKern::FMSignal(&iLock);
       
   512 	iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc);
       
   513 	}
       
   514 
       
   515 void DExampleChannel::SendFromWriteBuffer()
       
   516 	{
       
   517 	// just queue a timer to simulate an asynchronous send operation
       
   518 	NKern::FMWait(&iLock);
       
   519 	// The synchonisation is for illustrative purposes only - in a real driver we might make use of
       
   520 	// the configution here, so this would need to be protected from concurrent modification.
       
   521 	NKern::FMSignal(&iLock);
       
   522 	iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
       
   523 	}
       
   524 
       
   525 void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
       
   526 	{
       
   527 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   528 	self->CompleteRead();
       
   529 	}
       
   530 
       
   531 void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
       
   532 	{
       
   533 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   534 	self->CompleteWrite();
       
   535 	}
       
   536 
       
   537 void DExampleChannel::CompleteRead()
       
   538 	{
       
   539 	TPtrC8 des(iBuffer, iClientReadBuffer->MaxLength());
       
   540 	TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, des, 0, KChunkShiftBy0, iClient);
       
   541 	Kern::QueueBufferRequestComplete(iClient, iReadRequest, r);
       
   542 	Kern::DestroyClientBufferRequest(iReadRequest);
       
   543 	}
       
   544 
       
   545 void DExampleChannel::CompleteWrite()
       
   546 	{
       
   547 	TPtr8 des(iBuffer, iClientWriteBuffer->Length());
       
   548 	TInt r = Kern::ThreadBufRead(iClient, iClientWriteBuffer, des, 0, KChunkShiftBy0);
       
   549 	Kern::QueueBufferRequestComplete(iClient, iWriteRequest, r);
       
   550 	}
       
   551 
       
   552 //
       
   553 // Logical device
       
   554 //
       
   555 
       
   556 class DExampleFactory : public DLogicalDevice
       
   557 	{
       
   558 public:
       
   559 	DExampleFactory();
       
   560 	virtual TInt Install();
       
   561 	virtual void GetCaps(TDes8& aDes) const;
       
   562 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   563 	};
       
   564 
       
   565 DExampleFactory::DExampleFactory()
       
   566 	{
       
   567 	iParseMask = 0;
       
   568 	iVersion = TVersion(1, 0, 0);
       
   569 	}
       
   570 
       
   571 TInt DExampleFactory::Install()
       
   572 	{
       
   573 	return SetName(&KPagingExample2PostLdd);
       
   574 	}
       
   575 
       
   576 void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
       
   577 	{
       
   578 	// not used but required as DLogicalDevice::GetCaps is pure virtual
       
   579 	}
       
   580 
       
   581 TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
       
   582 	{
       
   583 	aChannel = new DExampleChannel;
       
   584 	return aChannel ? KErrNone : KErrNoMemory;
       
   585 	}
       
   586 
       
   587 DECLARE_STANDARD_LDD()
       
   588 	{
       
   589 	return new DExampleFactory;
       
   590 	}