1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/demandpaging/d_pagingexample_2_post.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,590 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\e32test\demandpaging\d_pagingexample_2_post.cpp
1.18 +// Demand paging migration example device driver d_pagingexample_2_post: a
1.19 +// DLogicalChannelBase-dervied driver, post-migration
1.20 +//
1.21 +//
1.22 +
1.23 +#include "d_pagingexample.h"
1.24 +#include <kernel/kernel.h>
1.25 +#include <kernel/kern_priv.h>
1.26 +
1.27 +const TInt KDfcQThreadPriority = 25;
1.28 +const TInt KBufferSize = KMaxTransferSize;
1.29 +
1.30 +//
1.31 +// Logical channel
1.32 +//
1.33 +
1.34 +class DExampleChannel : public DLogicalChannelBase
1.35 + {
1.36 +public:
1.37 + typedef RPagingExample::TConfigData TConfigData;
1.38 + typedef RPagingExample::TValueStruct TValueStruct;
1.39 +public:
1.40 + DExampleChannel();
1.41 + ~DExampleChannel();
1.42 + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
1.43 + virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2);
1.44 + TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
1.45 + TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
1.46 + TInt DoCancel(TUint aMask);
1.47 +private:
1.48 + TDfcQue* DfcQ();
1.49 + void Shutdown();
1.50 + void GetConfig(TConfigData&);
1.51 + void SetConfig(const TConfigData&);
1.52 + TInt StartNotify(TRequestStatus* aStatus);
1.53 + TInt StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus);
1.54 + TInt StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus);
1.55 + TInt StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
1.56 + TInt StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus);
1.57 + TInt StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
1.58 + TInt StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus);
1.59 + void ReceiveToReadBuffer();
1.60 + void SendFromWriteBuffer();
1.61 + static void CancelDfcFunc(TAny* aPtr);
1.62 + static void AsyncGetValueCompleteDfcFunc(TAny* aPtr);
1.63 + static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr);
1.64 + static void ReceiveCompleteDfcFunc(TAny* aPtr);
1.65 + static void SendCompleteDfcFunc(TAny* aPtr);
1.66 + void CompleteNotify();
1.67 + void CompleteAsyncGetValue();
1.68 + void CompleteAsyncGetValue2();
1.69 + void CompleteRead();
1.70 + void CompleteWrite();
1.71 + void Cancel();
1.72 +private:
1.73 + NFastMutex iLock;
1.74 + TDynamicDfcQue* iDynamicDfcQ;
1.75 + TConfigData iConfig;
1.76 + DThread* iClient;
1.77 + TDfc iCancelDfc;
1.78 +
1.79 + // Notify
1.80 + TClientRequest* iNotifyRequest;
1.81 +
1.82 + // Async get value
1.83 + TClientDataRequest<TValueStruct>* iAsyncGetValueRequest;
1.84 + NTimer iAsyncGetValueTimer;
1.85 + TDfc iAsyncGetValueDfc;
1.86 +
1.87 + // Async get value
1.88 + TClientDataRequest2<TInt,TInt>* iAsyncGetValue2Request;
1.89 + NTimer iAsyncGetValue2Timer;
1.90 + TDfc iAsyncGetValue2Dfc;
1.91 +
1.92 + // Read
1.93 + TClientBufferRequest* iReadRequest;
1.94 + NTimer iReadTimer;
1.95 + TClientBuffer* iClientReadBuffer;
1.96 + TDfc iCompleteReadDfc;
1.97 +
1.98 + // Write
1.99 + TClientBufferRequest* iWriteRequest;
1.100 + NTimer iWriteTimer;
1.101 + TClientBuffer* iClientWriteBuffer;
1.102 + TDfc iCompleteWriteDfc;
1.103 + TUint8 iBuffer[KBufferSize];
1.104 + };
1.105 +
1.106 +DExampleChannel::DExampleChannel() :
1.107 + iCancelDfc(CancelDfcFunc, this, 0),
1.108 + iAsyncGetValueTimer(NULL, this),
1.109 + iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, 0),
1.110 + iAsyncGetValue2Timer(NULL, this),
1.111 + iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, 0),
1.112 + iReadTimer(NULL, this),
1.113 + iCompleteReadDfc(ReceiveCompleteDfcFunc, this, 0),
1.114 + iWriteTimer(NULL, this),
1.115 + iCompleteWriteDfc(SendCompleteDfcFunc, this, 0)
1.116 + {
1.117 + iClient = &Kern::CurrentThread();
1.118 + iClient->Open();
1.119 + }
1.120 +
1.121 +DExampleChannel::~DExampleChannel()
1.122 + {
1.123 + Kern::SafeClose((DObject*&)iClient, NULL);
1.124 + if (iDynamicDfcQ)
1.125 + iDynamicDfcQ->Destroy();
1.126 + Kern::DestroyClientRequest(iNotifyRequest);
1.127 + Kern::DestroyClientRequest(iAsyncGetValueRequest);
1.128 + Kern::DestroyClientRequest(iAsyncGetValue2Request);
1.129 + Kern::DestroyClientBufferRequest(iReadRequest);
1.130 + Kern::DestroyClientBufferRequest(iWriteRequest);
1.131 + }
1.132 +
1.133 +TDfcQue* DExampleChannel::DfcQ()
1.134 + {
1.135 + return iDynamicDfcQ;
1.136 + }
1.137 +
1.138 +TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1.139 + {
1.140 + TInt r;
1.141 +
1.142 + r = Kern::CreateClientRequest(iNotifyRequest);
1.143 + if (r != KErrNone)
1.144 + return r;
1.145 + r = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
1.146 + if (r != KErrNone)
1.147 + return r;
1.148 + r = Kern::CreateClientDataRequest2(iAsyncGetValue2Request);
1.149 + if (r != KErrNone)
1.150 + return r;
1.151 + r = Kern::CreateClientBufferRequest(iWriteRequest, 1, TClientBufferRequest::EPinVirtual);
1.152 + if (r != KErrNone)
1.153 + return r;
1.154 +
1.155 + // create a dynamic DFC queue, which is used for handling client messages and for our own DFCs
1.156 + r = Kern::DynamicDfcQCreate(iDynamicDfcQ, KDfcQThreadPriority, KPagingExample1PostLdd);
1.157 + if (r != KErrNone)
1.158 + return r;
1.159 +
1.160 + // todo: this will be the default anyway
1.161 + iDynamicDfcQ->SetRealtimeState(ERealtimeStateOn);
1.162 +
1.163 + iCancelDfc.SetDfcQ(DfcQ());
1.164 + iAsyncGetValueDfc.SetDfcQ(DfcQ());
1.165 + iAsyncGetValue2Dfc.SetDfcQ(DfcQ());
1.166 + iCompleteReadDfc.SetDfcQ(DfcQ());
1.167 + iCompleteWriteDfc.SetDfcQ(DfcQ());
1.168 + return KErrNone;
1.169 + }
1.170 +
1.171 +TInt DExampleChannel::Request(TInt aReqNo, TAny* a1, TAny* a2)
1.172 + {
1.173 + TInt r = KErrNone;
1.174 + if (&Kern::CurrentThread() != iClient)
1.175 + r = KErrAccessDenied; // we only support one client
1.176 + else if (aReqNo==KMaxTInt)
1.177 + {
1.178 + // DoCancel
1.179 + r = DoCancel((TInt)a1);
1.180 + }
1.181 + else if (aReqNo<0)
1.182 + {
1.183 + // DoRequest
1.184 + TRequestStatus* pS=(TRequestStatus*)a1;
1.185 + TAny* array[2] = { NULL, NULL };
1.186 + kumemget32(array, a2, 2 * sizeof(TAny*));
1.187 + r = DoRequest(~aReqNo, pS, array[0], array[1]);
1.188 + if(r != KErrNone)
1.189 + Kern::RequestComplete(pS, r);
1.190 + r = KErrNone;
1.191 + }
1.192 + else
1.193 + {
1.194 + // DoControl
1.195 + r = DoControl(aReqNo, a1, a2);
1.196 + }
1.197 + return r;
1.198 + }
1.199 +
1.200 +TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
1.201 + {
1.202 + TInt r = KErrNone;
1.203 + TConfigData configBuffer;
1.204 + switch (aFunction)
1.205 + {
1.206 + case RPagingExample::EGetConfig:
1.207 + GetConfig(configBuffer);
1.208 + umemput32(a1, (TAny*)&configBuffer, sizeof(TConfigData));
1.209 + break;
1.210 +
1.211 + case RPagingExample::ESetConfig:
1.212 + umemget32(&configBuffer, a1, sizeof(TConfigData));
1.213 + SetConfig(configBuffer);
1.214 + break;
1.215 +
1.216 + default:
1.217 + r = KErrNotSupported;
1.218 + }
1.219 + return r;
1.220 + }
1.221 +
1.222 +TInt DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1.223 + {
1.224 + TInt r = KErrNotSupported;
1.225 + switch (aFunction)
1.226 + {
1.227 + case RPagingExample::ERequestNotify:
1.228 + r = StartNotify(aStatus);
1.229 + break;
1.230 +
1.231 + case RPagingExample::ERequestAsyncGetValue:
1.232 + r = StartAsyncGetValue((TInt*)a1, aStatus);
1.233 + break;
1.234 +
1.235 + case RPagingExample::ERequestAsyncGetValue2:
1.236 + r = StartAsyncGetValue2((TInt*)a1, (TInt*)a2, aStatus);
1.237 + break;
1.238 +
1.239 + case RPagingExample::ERequestRead:
1.240 + r = StartRead(a1, (TInt)a2, aStatus);
1.241 + break;
1.242 +
1.243 + case RPagingExample::ERequestReadDes:
1.244 + r = StartReadDes((TDes8*)a1, aStatus);
1.245 + break;
1.246 +
1.247 + case RPagingExample::ERequestWrite:
1.248 + r = StartWrite(a1, (TInt)a2, aStatus);
1.249 + break;
1.250 +
1.251 + case RPagingExample::ERequestWriteDes:
1.252 + r = StartWriteDes((TDes8*)a1, aStatus);
1.253 + break;
1.254 + }
1.255 + return r;
1.256 + }
1.257 +
1.258 +TInt DExampleChannel::DoCancel(TUint /*aMask*/)
1.259 + {
1.260 + iCancelDfc.Enque();
1.261 + return KErrNone;
1.262 + }
1.263 +
1.264 +void DExampleChannel::CancelDfcFunc(TAny* aPtr)
1.265 + {
1.266 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.267 + self->Cancel();
1.268 + }
1.269 +
1.270 +void DExampleChannel::Cancel()
1.271 + {
1.272 + if (iAsyncGetValueRequest->IsReady())
1.273 + {
1.274 + iAsyncGetValueTimer.Cancel();
1.275 + iAsyncGetValueDfc.Cancel();
1.276 + Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrCancel);
1.277 + }
1.278 +
1.279 + if (iAsyncGetValue2Request->IsReady())
1.280 + {
1.281 + iAsyncGetValue2Timer.Cancel();
1.282 + iAsyncGetValue2Dfc.Cancel();
1.283 + Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrCancel);
1.284 + }
1.285 +
1.286 + if (iReadRequest && iReadRequest->IsReady())
1.287 + {
1.288 + iReadTimer.Cancel();
1.289 + iCompleteReadDfc.Cancel();
1.290 + Kern::QueueBufferRequestComplete(iClient, iReadRequest, KErrCancel);
1.291 + Kern::DestroyClientBufferRequest(iReadRequest);
1.292 + }
1.293 +
1.294 + if (iWriteRequest->IsReady())
1.295 + {
1.296 + iWriteTimer.Cancel();
1.297 + iCompleteWriteDfc.Cancel();
1.298 + Kern::QueueBufferRequestComplete(iClient, iWriteRequest, KErrCancel);
1.299 + }
1.300 + }
1.301 +
1.302 +void DExampleChannel::Shutdown()
1.303 + {
1.304 + }
1.305 +
1.306 +void DExampleChannel::GetConfig(TConfigData& aConfigOut)
1.307 + {
1.308 + NKern::FMWait(&iLock);
1.309 + aConfigOut = iConfig;
1.310 + NKern::FMSignal(&iLock);
1.311 + }
1.312 +
1.313 +void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
1.314 + {
1.315 + NKern::FMWait(&iLock);
1.316 + iConfig = aNewConfig;
1.317 + NKern::FMSignal(&iLock);
1.318 + }
1.319 +
1.320 +TInt DExampleChannel::StartNotify(TRequestStatus* aStatus)
1.321 + {
1.322 + // example implementation completes the request immediately
1.323 + TInt r = iNotifyRequest->SetStatus(aStatus);
1.324 + if (r != KErrNone)
1.325 + return r;
1.326 + CompleteNotify(); // example implementation completes the request immediately
1.327 + return KErrNone;
1.328 + }
1.329 +
1.330 +void DExampleChannel::CompleteNotify()
1.331 + {
1.332 + Kern::QueueRequestComplete(iClient, iNotifyRequest, KErrNone);
1.333 + }
1.334 +
1.335 +TInt DExampleChannel::StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
1.336 + {
1.337 + // use of TClientDataRequest API protected by fast mutex
1.338 + NKern::FMWait(&iLock);
1.339 + TInt r = iAsyncGetValueRequest->SetStatus(aStatus);
1.340 + if (r == KErrNone)
1.341 + iAsyncGetValueRequest->SetDestPtr(aValue);
1.342 + NKern::FMSignal(&iLock);
1.343 + if (r != KErrNone)
1.344 + return r;
1.345 +
1.346 + // queue a timer to simulate an asynchronous operation
1.347 + iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
1.348 + return KErrNone;
1.349 + }
1.350 +
1.351 +void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
1.352 + {
1.353 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.354 + self->CompleteAsyncGetValue();
1.355 + }
1.356 +
1.357 +void DExampleChannel::CompleteAsyncGetValue()
1.358 + {
1.359 + // use of TClientDataRequest API protected by fast mutex
1.360 + NKern::FMWait(&iLock);
1.361 + if (iAsyncGetValueRequest->IsReady())
1.362 + {
1.363 + iAsyncGetValueRequest->Data().iValue1 = 1;
1.364 + iAsyncGetValueRequest->Data().iValue2 = _L8("shrt");
1.365 + Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrNone);
1.366 + }
1.367 + NKern::FMSignal(&iLock);
1.368 + }
1.369 +
1.370 +TInt DExampleChannel::StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
1.371 + {
1.372 + // use of TClientDataRequest API protected by fast mutex
1.373 + NKern::FMWait(&iLock);
1.374 + TInt r = iAsyncGetValue2Request->SetStatus(aStatus);
1.375 + if (r == KErrNone)
1.376 + iAsyncGetValue2Request->SetDestPtr1(aValue1);
1.377 + if (r == KErrNone)
1.378 + iAsyncGetValue2Request->SetDestPtr2(aValue2);
1.379 + NKern::FMSignal(&iLock);
1.380 + if (r != KErrNone)
1.381 + return r;
1.382 +
1.383 + // queue a timer to simulate an asynchronous operation
1.384 + iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
1.385 + return KErrNone;
1.386 + }
1.387 +
1.388 +void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
1.389 + {
1.390 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.391 + self->CompleteAsyncGetValue2();
1.392 + }
1.393 +
1.394 +void DExampleChannel::CompleteAsyncGetValue2()
1.395 + {
1.396 + // use of TClientDataRequest API protected by fast mutex
1.397 + NKern::FMWait(&iLock);
1.398 + if (iAsyncGetValue2Request->IsReady())
1.399 + {
1.400 + iAsyncGetValue2Request->Data1() = 1;
1.401 + iAsyncGetValue2Request->Data2() = 2;
1.402 + Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrNone);
1.403 + }
1.404 + NKern::FMSignal(&iLock);
1.405 + }
1.406 +
1.407 +TInt DExampleChannel::StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
1.408 + {
1.409 + // check length argument first
1.410 + if (aLength < 1 || aLength > KBufferSize)
1.411 + return KErrArgument;
1.412 +
1.413 + // normally drivers would pre-create a TClientBufferRequest where possible, but here we create
1.414 + // one on demand to test this possibilty
1.415 + NKern::ThreadEnterCS();
1.416 + TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
1.417 + NKern::ThreadLeaveCS(); // iReadRequest is deleted by the destructor
1.418 + if (r != KErrNone)
1.419 + return r;
1.420 +
1.421 + // start request setup
1.422 + r = iReadRequest->StartSetup(aStatus);
1.423 + if (r != KErrNone)
1.424 + return r;
1.425 +
1.426 + // add client buffer, this does pinning in context of client thread
1.427 + r = iReadRequest->AddBuffer(iClientReadBuffer, (TLinAddr)aBuffer, aLength, ETrue);
1.428 + if (r != KErrNone)
1.429 + return KErrNoMemory;
1.430 +
1.431 + iReadRequest->EndSetup();
1.432 +
1.433 + ReceiveToReadBuffer();
1.434 + return KErrNone;
1.435 + }
1.436 +
1.437 +TInt DExampleChannel::StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
1.438 + {
1.439 + // normally drivers would pre-create a TClientBufferRequest where possible, but here we create
1.440 + // one on demand to test this possibilty
1.441 + NKern::ThreadEnterCS();
1.442 + TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
1.443 + NKern::ThreadLeaveCS(); // iReadRequest is deleted by the destructor
1.444 + if (r != KErrNone)
1.445 + return r;
1.446 +
1.447 + // start request setup
1.448 + r = iReadRequest->StartSetup(aStatus);
1.449 + if (r != KErrNone)
1.450 + return r;
1.451 +
1.452 + // add client descriptor, this does pinning in context of client thread
1.453 + r = iReadRequest->AddBuffer(iClientReadBuffer, aDesOut);
1.454 + if (r != KErrNone)
1.455 + return r;
1.456 +
1.457 + // can check length argument here
1.458 + TInt length = iClientReadBuffer->MaxLength();
1.459 + if (length < 1 || length > KBufferSize)
1.460 + {
1.461 + // need to reset object so it can be reused
1.462 + iReadRequest->Reset();
1.463 + return KErrArgument;
1.464 + }
1.465 +
1.466 + iReadRequest->EndSetup();
1.467 +
1.468 + ReceiveToReadBuffer();
1.469 + return KErrNone;
1.470 + }
1.471 +
1.472 +TInt DExampleChannel::StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
1.473 + {
1.474 + // check length argument first
1.475 + if (aLength < 1 || aLength > KBufferSize)
1.476 + return KErrArgument;
1.477 +
1.478 + // demonstrate use the single-buffer version of Setup
1.479 + TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TLinAddr)aBuffer, aLength);
1.480 + if (r != KErrNone)
1.481 + return r;
1.482 +
1.483 + SendFromWriteBuffer();
1.484 + return KErrNone;
1.485 + }
1.486 +
1.487 +TInt DExampleChannel::StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
1.488 + {
1.489 + // demonstrate use the single-buffer version of Setup
1.490 + TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TAny*)aDesIn);
1.491 + if (r != KErrNone)
1.492 + return r;
1.493 +
1.494 + // can check length argument here
1.495 + TInt length = iClientWriteBuffer->Length();
1.496 + if (length < 1 || length > KBufferSize)
1.497 + {
1.498 + // need to reset object so it can be reused
1.499 + iWriteRequest->Reset();
1.500 + return KErrArgument;
1.501 + }
1.502 +
1.503 + SendFromWriteBuffer();
1.504 + return KErrNone;
1.505 + }
1.506 +
1.507 +void DExampleChannel::ReceiveToReadBuffer()
1.508 + {
1.509 + // just queue a timer to simulate an asynchronous receive operation
1.510 + // actually will return the previous contents of the buffer
1.511 + NKern::FMWait(&iLock);
1.512 + // The synchonisation is for illustrative purposes only - in a real driver we might make use of
1.513 + // the configution here, so this would need to be protected from concurrent modification.
1.514 + NKern::FMSignal(&iLock);
1.515 + iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc);
1.516 + }
1.517 +
1.518 +void DExampleChannel::SendFromWriteBuffer()
1.519 + {
1.520 + // just queue a timer to simulate an asynchronous send operation
1.521 + NKern::FMWait(&iLock);
1.522 + // The synchonisation is for illustrative purposes only - in a real driver we might make use of
1.523 + // the configution here, so this would need to be protected from concurrent modification.
1.524 + NKern::FMSignal(&iLock);
1.525 + iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
1.526 + }
1.527 +
1.528 +void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
1.529 + {
1.530 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.531 + self->CompleteRead();
1.532 + }
1.533 +
1.534 +void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
1.535 + {
1.536 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.537 + self->CompleteWrite();
1.538 + }
1.539 +
1.540 +void DExampleChannel::CompleteRead()
1.541 + {
1.542 + TPtrC8 des(iBuffer, iClientReadBuffer->MaxLength());
1.543 + TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, des, 0, KChunkShiftBy0, iClient);
1.544 + Kern::QueueBufferRequestComplete(iClient, iReadRequest, r);
1.545 + Kern::DestroyClientBufferRequest(iReadRequest);
1.546 + }
1.547 +
1.548 +void DExampleChannel::CompleteWrite()
1.549 + {
1.550 + TPtr8 des(iBuffer, iClientWriteBuffer->Length());
1.551 + TInt r = Kern::ThreadBufRead(iClient, iClientWriteBuffer, des, 0, KChunkShiftBy0);
1.552 + Kern::QueueBufferRequestComplete(iClient, iWriteRequest, r);
1.553 + }
1.554 +
1.555 +//
1.556 +// Logical device
1.557 +//
1.558 +
1.559 +class DExampleFactory : public DLogicalDevice
1.560 + {
1.561 +public:
1.562 + DExampleFactory();
1.563 + virtual TInt Install();
1.564 + virtual void GetCaps(TDes8& aDes) const;
1.565 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.566 + };
1.567 +
1.568 +DExampleFactory::DExampleFactory()
1.569 + {
1.570 + iParseMask = 0;
1.571 + iVersion = TVersion(1, 0, 0);
1.572 + }
1.573 +
1.574 +TInt DExampleFactory::Install()
1.575 + {
1.576 + return SetName(&KPagingExample2PostLdd);
1.577 + }
1.578 +
1.579 +void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
1.580 + {
1.581 + // not used but required as DLogicalDevice::GetCaps is pure virtual
1.582 + }
1.583 +
1.584 +TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
1.585 + {
1.586 + aChannel = new DExampleChannel;
1.587 + return aChannel ? KErrNone : KErrNoMemory;
1.588 + }
1.589 +
1.590 +DECLARE_STANDARD_LDD()
1.591 + {
1.592 + return new DExampleFactory;
1.593 + }