1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/demandpaging/d_pagingexample_1_post.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,666 @@
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_1_post.cpp
1.18 +// Demand paging migration example device driver d_pagingexample_1_post: a DLogicalChannel-dervied
1.19 +// 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 DLogicalChannel
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 SendMsg(TMessageBase* aMsg);
1.44 + TInt SendControl(TMessageBase* aMsg);
1.45 + TInt SendRequest(TMessageBase* aMsg);
1.46 + virtual void HandleMsg(TMessageBase* aMsg);
1.47 + TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
1.48 + void DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
1.49 + TInt DoCancel(TUint aMask);
1.50 +private:
1.51 + TDfcQue* DfcQ();
1.52 + void Shutdown();
1.53 + void SetConfig(const TConfigData&);
1.54 + TInt PreNotify(TRequestStatus* aStatus);
1.55 + void StartNotify();
1.56 + TInt PreAsyncGetValue(TInt* aValue, TRequestStatus* aStatus);
1.57 + void StartAsyncGetValue();
1.58 + TInt PreAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus);
1.59 + void StartAsyncGetValue2();
1.60 + TInt PreRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
1.61 + void StartRead();
1.62 + TInt PreReadDes(TDes8* aDesOut, TRequestStatus* aStatus);
1.63 + void StartReadDes();
1.64 + TInt PreWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
1.65 + void StartWrite();
1.66 + TInt PreWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus);
1.67 + void StartWriteDes();
1.68 + void ReceiveToReadBuffer();
1.69 + void SendFromWriteBuffer();
1.70 + static void AsyncGetValueCompleteDfcFunc(TAny* aPtr);
1.71 + static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr);
1.72 + static void ReceiveCompleteDfcFunc(TAny* aPtr);
1.73 + static void SendCompleteDfcFunc(TAny* aPtr);
1.74 + void CompleteNotify();
1.75 + void CompleteAsyncGetValue();
1.76 + void CompleteAsyncGetValue2();
1.77 + void CompleteRead();
1.78 + void CompleteWrite();
1.79 +private:
1.80 + TDynamicDfcQue* iDynamicDfcQ;
1.81 + TConfigData iConfig;
1.82 + DThread* iClient;
1.83 +
1.84 + // Notify
1.85 + TClientRequest* iNotifyRequest;
1.86 +
1.87 + // Async get value
1.88 + TClientDataRequest<TValueStruct>* iAsyncGetValueRequest;
1.89 + NTimer iAsyncGetValueTimer;
1.90 + TDfc iAsyncGetValueDfc;
1.91 +
1.92 + // Async get value 2
1.93 + TClientDataRequest2<TInt,TInt>* iAsyncGetValue2Request;
1.94 + NTimer iAsyncGetValue2Timer;
1.95 + TDfc iAsyncGetValue2Dfc;
1.96 +
1.97 + // Read
1.98 + TClientBufferRequest* iReadRequest;
1.99 + NTimer iReadTimer;
1.100 + TClientBuffer* iClientReadBuffer;
1.101 + TDfc iCompleteReadDfc;
1.102 +
1.103 + // Write
1.104 + TClientBufferRequest* iWriteRequest;
1.105 + NTimer iWriteTimer;
1.106 + TClientBuffer* iClientWriteBuffer;
1.107 + TDfc iCompleteWriteDfc;
1.108 + TUint8 iBuffer[KBufferSize];
1.109 + };
1.110 +
1.111 +DExampleChannel::DExampleChannel() :
1.112 + iAsyncGetValueTimer(NULL, this),
1.113 + iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, 0),
1.114 + iAsyncGetValue2Timer(NULL, this),
1.115 + iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, 0),
1.116 + iReadTimer(NULL, this),
1.117 + iCompleteReadDfc(ReceiveCompleteDfcFunc, this, 0),
1.118 + iWriteTimer(NULL, this),
1.119 + iCompleteWriteDfc(SendCompleteDfcFunc, this, 0)
1.120 + {
1.121 + iClient = &Kern::CurrentThread();
1.122 + iClient->Open();
1.123 + }
1.124 +
1.125 +DExampleChannel::~DExampleChannel()
1.126 + {
1.127 + Kern::SafeClose((DObject*&)iClient, NULL);
1.128 + if (iDynamicDfcQ)
1.129 + iDynamicDfcQ->Destroy();
1.130 + Kern::DestroyClientRequest(iNotifyRequest);
1.131 + Kern::DestroyClientRequest(iAsyncGetValueRequest);
1.132 + Kern::DestroyClientRequest(iAsyncGetValue2Request);
1.133 + Kern::DestroyClientBufferRequest(iReadRequest);
1.134 + Kern::DestroyClientBufferRequest(iWriteRequest);
1.135 + }
1.136 +
1.137 +TDfcQue* DExampleChannel::DfcQ()
1.138 + {
1.139 + return iDynamicDfcQ;
1.140 + }
1.141 +
1.142 +TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1.143 + {
1.144 + TInt r;
1.145 +
1.146 + r = Kern::CreateClientRequest(iNotifyRequest);
1.147 + if (r != KErrNone)
1.148 + return r;
1.149 + r = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
1.150 + if (r != KErrNone)
1.151 + return r;
1.152 + r = Kern::CreateClientDataRequest2(iAsyncGetValue2Request);
1.153 + if (r != KErrNone)
1.154 + return r;
1.155 + r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
1.156 + if (r != KErrNone)
1.157 + return r;
1.158 + r = Kern::CreateClientBufferRequest(iWriteRequest, 1, TClientBufferRequest::EPinVirtual);
1.159 + if (r != KErrNone)
1.160 + return r;
1.161 +
1.162 + // create a dynamic DFC queue, which is used for handling client messages and for our own DFCs
1.163 + r = Kern::DynamicDfcQCreate(iDynamicDfcQ, KDfcQThreadPriority, KPagingExample1PostLdd);
1.164 + if (r != KErrNone)
1.165 + return r;
1.166 +
1.167 + // todo: this will be the default anyway
1.168 + iDynamicDfcQ->SetRealtimeState(ERealtimeStateOn);
1.169 +
1.170 + SetDfcQ(DfcQ());
1.171 + iAsyncGetValueDfc.SetDfcQ(DfcQ());
1.172 + iAsyncGetValue2Dfc.SetDfcQ(DfcQ());
1.173 + iCompleteReadDfc.SetDfcQ(DfcQ());
1.174 + iCompleteWriteDfc.SetDfcQ(DfcQ());
1.175 + iMsgQ.Receive();
1.176 + return KErrNone;
1.177 + }
1.178 +
1.179 +// override SendMsg method to allow pinning data in the context of the client thread
1.180 +TInt DExampleChannel::SendMsg(TMessageBase* aMsg)
1.181 + {
1.182 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.183 + TInt id = m.iValue;
1.184 +
1.185 + // we only support one client
1.186 + if (id != (TInt)ECloseMsg && m.Client() != iClient)
1.187 + return KErrAccessDenied;
1.188 +
1.189 + TInt r = KErrNone;
1.190 + if (id != (TInt)ECloseMsg && id != KMaxTInt)
1.191 + {
1.192 + if (id<0)
1.193 + {
1.194 + TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1.195 + r = SendRequest(aMsg);
1.196 + if (r != KErrNone)
1.197 + Kern::RequestComplete(pS,r);
1.198 + }
1.199 + else
1.200 + r = SendControl(aMsg);
1.201 + }
1.202 + else
1.203 + r = DLogicalChannel::SendMsg(aMsg);
1.204 +
1.205 + return r;
1.206 + }
1.207 +
1.208 +void DExampleChannel::HandleMsg(TMessageBase* aMsg)
1.209 + {
1.210 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.211 + TInt id=m.iValue;
1.212 +
1.213 + if (id==(TInt)ECloseMsg)
1.214 + {
1.215 + Shutdown();
1.216 + m.Complete(KErrNone,EFalse);
1.217 + return;
1.218 + }
1.219 + else if (id==KMaxTInt)
1.220 + {
1.221 + // DoCancel
1.222 + DoCancel(m.Int0());
1.223 + m.Complete(KErrNone,ETrue);
1.224 + return;
1.225 + }
1.226 + else if (id<0)
1.227 + {
1.228 + // DoRequest
1.229 + TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1.230 + DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
1.231 + m.Complete(KErrNone,ETrue);
1.232 + }
1.233 + else
1.234 + {
1.235 + // DoControl
1.236 + TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
1.237 + m.Complete(r,ETrue);
1.238 + }
1.239 + }
1.240 +
1.241 +TInt DExampleChannel::SendControl(TMessageBase* aMsg)
1.242 + {
1.243 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.244 + TInt id=m.iValue;
1.245 +
1.246 + // thread-local copy of configuration data
1.247 + TConfigData kernelConfigBuffer;
1.248 + TAny* userConfigPtr = m.Ptr0();
1.249 +
1.250 + switch (id)
1.251 + {
1.252 + case RPagingExample::ESetConfig:
1.253 + // copy config from client to local buffer in context of client thread
1.254 + umemget32(&kernelConfigBuffer, userConfigPtr, sizeof(TConfigData));
1.255 + // update message to point to kernel-side buffer
1.256 + m.iArg[0] = &kernelConfigBuffer;
1.257 + break;
1.258 +
1.259 + case RPagingExample::EGetConfig:
1.260 + // update message to point to kernel-side buffer
1.261 + m.iArg[0] = &kernelConfigBuffer;
1.262 + break;
1.263 + }
1.264 +
1.265 + TInt r = DLogicalChannel::SendMsg(aMsg);
1.266 + if (r != KErrNone)
1.267 + return r;
1.268 +
1.269 + switch (id)
1.270 + {
1.271 + case RPagingExample::EGetConfig:
1.272 + // copy config from local bufferto client in context of client thread
1.273 + umemput32(userConfigPtr, &kernelConfigBuffer, sizeof(TConfigData));
1.274 + break;
1.275 + }
1.276 +
1.277 + return r;
1.278 + }
1.279 +
1.280 +TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
1.281 + {
1.282 + TInt r = KErrNone;
1.283 + TConfigData* configBuffer = (TConfigData*)a1;
1.284 + switch (aFunction)
1.285 + {
1.286 + case RPagingExample::EGetConfig:
1.287 + // copy current config into local buffer in context of DFC thread to avoid potential race conditions
1.288 + *configBuffer = iConfig;
1.289 + break;
1.290 +
1.291 + case RPagingExample::ESetConfig:
1.292 + // set config from copy in local buffer in context of DFC thread to avoid potential race conditions
1.293 + SetConfig(*configBuffer);
1.294 + break;
1.295 +
1.296 + default:
1.297 + r = KErrNotSupported;
1.298 + }
1.299 + return r;
1.300 + }
1.301 +
1.302 +TInt DExampleChannel::SendRequest(TMessageBase* aMsg)
1.303 + {
1.304 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.305 + TInt function = ~m.iValue;
1.306 + TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1.307 + TAny* a1 = m.Ptr1();
1.308 + TAny* a2 = m.Ptr2();
1.309 +
1.310 + TInt r = KErrNotSupported;
1.311 + switch (function)
1.312 + {
1.313 + case RPagingExample::ERequestNotify:
1.314 + r = PreNotify(pS);
1.315 + break;
1.316 +
1.317 + case RPagingExample::ERequestAsyncGetValue:
1.318 + r = PreAsyncGetValue((TInt*)a1, pS);
1.319 + break;
1.320 +
1.321 + case RPagingExample::ERequestAsyncGetValue2:
1.322 + r = PreAsyncGetValue2((TInt*)a1, (TInt*)a2, pS);
1.323 + break;
1.324 +
1.325 + case RPagingExample::ERequestRead:
1.326 + r = PreRead(a1, (TInt)a2, pS);
1.327 + break;
1.328 +
1.329 + case RPagingExample::ERequestReadDes:
1.330 + r = PreReadDes((TDes8*)a1, pS);
1.331 + break;
1.332 +
1.333 + case RPagingExample::ERequestWrite:
1.334 + r = PreWrite(a1, (TInt)a2, pS);
1.335 + break;
1.336 +
1.337 + case RPagingExample::ERequestWriteDes:
1.338 + r = PreWriteDes((TDes8*)a1, pS);
1.339 + break;
1.340 + }
1.341 +
1.342 + if (r == KErrNone)
1.343 + r = DLogicalChannel::SendMsg(aMsg);
1.344 + return r;
1.345 + }
1.346 +
1.347 +void DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* /*aStatus*/, TAny* /*a1*/, TAny* /*a2*/)
1.348 + {
1.349 + switch (aFunction)
1.350 + {
1.351 + case RPagingExample::ERequestNotify:
1.352 + StartNotify();
1.353 + break;
1.354 +
1.355 + case RPagingExample::ERequestAsyncGetValue:
1.356 + StartAsyncGetValue();
1.357 + break;
1.358 +
1.359 + case RPagingExample::ERequestAsyncGetValue2:
1.360 + StartAsyncGetValue2();
1.361 + break;
1.362 +
1.363 + case RPagingExample::ERequestRead:
1.364 + StartRead();
1.365 + break;
1.366 +
1.367 + case RPagingExample::ERequestReadDes:
1.368 + StartReadDes();
1.369 + break;
1.370 +
1.371 + case RPagingExample::ERequestWrite:
1.372 + StartWrite();
1.373 + break;
1.374 +
1.375 + case RPagingExample::ERequestWriteDes:
1.376 + StartWriteDes();
1.377 + break;
1.378 +
1.379 + default:
1.380 + __NK_ASSERT_ALWAYS(EFalse); // we already validated the request number
1.381 + }
1.382 + }
1.383 +
1.384 +TInt DExampleChannel::DoCancel(TUint /*aMask*/)
1.385 + {
1.386 + if (iAsyncGetValueRequest->IsReady())
1.387 + {
1.388 + iAsyncGetValueTimer.Cancel();
1.389 + iAsyncGetValueDfc.Cancel();
1.390 + Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrCancel);
1.391 + }
1.392 +
1.393 + if (iAsyncGetValue2Request->IsReady())
1.394 + {
1.395 + iAsyncGetValue2Timer.Cancel();
1.396 + iAsyncGetValue2Dfc.Cancel();
1.397 + Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrCancel);
1.398 + }
1.399 +
1.400 + if (iReadRequest->IsReady())
1.401 + {
1.402 + iReadTimer.Cancel();
1.403 + iCompleteReadDfc.Cancel();
1.404 + Kern::QueueBufferRequestComplete(iClient, iReadRequest, KErrCancel);
1.405 + }
1.406 +
1.407 + if (iWriteRequest->IsReady())
1.408 + {
1.409 + iWriteTimer.Cancel();
1.410 + iCompleteWriteDfc.Cancel();
1.411 + Kern::QueueBufferRequestComplete(iClient, iWriteRequest, KErrCancel);
1.412 + }
1.413 +
1.414 + return KErrNone;
1.415 + }
1.416 +
1.417 +void DExampleChannel::Shutdown()
1.418 + {
1.419 + }
1.420 +
1.421 +void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
1.422 + {
1.423 + iConfig = aNewConfig;
1.424 + }
1.425 +
1.426 +TInt DExampleChannel::PreNotify(TRequestStatus* aStatus)
1.427 + {
1.428 + return iNotifyRequest->SetStatus(aStatus);
1.429 + }
1.430 +
1.431 +void DExampleChannel::StartNotify()
1.432 + {
1.433 + CompleteNotify(); // example implementation completes the request immediately
1.434 + }
1.435 +
1.436 +void DExampleChannel::CompleteNotify()
1.437 + {
1.438 + Kern::QueueRequestComplete(iClient, iNotifyRequest, KErrNone);
1.439 + }
1.440 +
1.441 +TInt DExampleChannel::PreAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
1.442 + {
1.443 + TInt r = iAsyncGetValueRequest->SetStatus(aStatus);
1.444 + if (r != KErrNone)
1.445 + return r;
1.446 + iAsyncGetValueRequest->SetDestPtr(aValue);
1.447 + return KErrNone;
1.448 + }
1.449 +
1.450 +void DExampleChannel::StartAsyncGetValue()
1.451 + {
1.452 + // queue a timer to simulate an asynchronous operation
1.453 + iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
1.454 + }
1.455 +
1.456 +void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
1.457 + {
1.458 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.459 + self->CompleteAsyncGetValue();
1.460 + }
1.461 +
1.462 +void DExampleChannel::CompleteAsyncGetValue()
1.463 + {
1.464 + iAsyncGetValueRequest->Data().iValue1 = 1;
1.465 + iAsyncGetValueRequest->Data().iValue2 = _L8("shrt");
1.466 + Kern::QueueRequestComplete(iClient, iAsyncGetValueRequest, KErrNone);
1.467 + }
1.468 +
1.469 +TInt DExampleChannel::PreAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
1.470 + {
1.471 + TInt r = iAsyncGetValue2Request->SetStatus(aStatus);
1.472 + if (r != KErrNone)
1.473 + return r;
1.474 + iAsyncGetValue2Request->SetDestPtr1(aValue1);
1.475 + iAsyncGetValue2Request->SetDestPtr2(aValue2);
1.476 + return KErrNone;
1.477 + }
1.478 +
1.479 +void DExampleChannel::StartAsyncGetValue2()
1.480 + {
1.481 + // queue a timer to simulate an asynchronous operation
1.482 + iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
1.483 + }
1.484 +
1.485 +void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
1.486 + {
1.487 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.488 + self->CompleteAsyncGetValue2();
1.489 + }
1.490 +
1.491 +void DExampleChannel::CompleteAsyncGetValue2()
1.492 + {
1.493 + iAsyncGetValue2Request->Data1() = 1;
1.494 + iAsyncGetValue2Request->Data2() = 2;
1.495 + Kern::QueueRequestComplete(iClient, iAsyncGetValue2Request, KErrNone);
1.496 + }
1.497 +
1.498 +TInt DExampleChannel::PreRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
1.499 + {
1.500 + // check length argument first
1.501 + if (aLength < 1 || aLength > KBufferSize)
1.502 + return KErrArgument;
1.503 +
1.504 + // start request setup
1.505 + TInt r = iReadRequest->StartSetup(aStatus);
1.506 + if (r != KErrNone)
1.507 + return r;
1.508 +
1.509 + // add client buffer, this does pinning in context of client thread
1.510 + r = iReadRequest->AddBuffer(iClientReadBuffer, (TLinAddr)aBuffer, aLength, ETrue);
1.511 + if (r != KErrNone)
1.512 + return KErrNoMemory;
1.513 +
1.514 + iReadRequest->EndSetup();
1.515 + return KErrNone;
1.516 + }
1.517 +
1.518 +void DExampleChannel::StartRead()
1.519 + {
1.520 + ReceiveToReadBuffer(); // called in DFC thread as may require serialised access to hardware
1.521 + }
1.522 +
1.523 +TInt DExampleChannel::PreReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
1.524 + {
1.525 + // start request setup
1.526 + TInt r = iReadRequest->StartSetup(aStatus);
1.527 + if (r != KErrNone)
1.528 + return r;
1.529 +
1.530 + // add client descriptor, this does pinning in context of client thread
1.531 + r = iReadRequest->AddBuffer(iClientReadBuffer, aDesOut);
1.532 + if (r != KErrNone)
1.533 + return r;
1.534 +
1.535 + // can check length argument here
1.536 + TInt length = iClientReadBuffer->MaxLength();
1.537 + if (length < 1 || length > KBufferSize)
1.538 + {
1.539 + // need to reset object so it can be reused
1.540 + iReadRequest->Reset();
1.541 + return KErrArgument;
1.542 + }
1.543 +
1.544 + iReadRequest->EndSetup();
1.545 + return KErrNone;
1.546 + }
1.547 +
1.548 +void DExampleChannel::StartReadDes()
1.549 + {
1.550 + ReceiveToReadBuffer(); // called in DFC thread as may require serialised access to hardware
1.551 + }
1.552 +
1.553 +TInt DExampleChannel::PreWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
1.554 + {
1.555 + // check length argument first
1.556 + if (aLength < 1 || aLength > KBufferSize)
1.557 + return KErrArgument;
1.558 +
1.559 + // demonstrate use the single-buffer version of Setup
1.560 + return iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TLinAddr)aBuffer, aLength);
1.561 + }
1.562 +
1.563 +void DExampleChannel::StartWrite()
1.564 + {
1.565 + SendFromWriteBuffer(); // called in DFC thread as may require serialised access to hardware
1.566 + }
1.567 +
1.568 +TInt DExampleChannel::PreWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
1.569 + {
1.570 + // demonstrate use the single-buffer version of Setup
1.571 + TInt r = iWriteRequest->Setup(iClientWriteBuffer, aStatus, (TAny*)aDesIn);
1.572 + if (r != KErrNone)
1.573 + return r;
1.574 +
1.575 + // can check length argument here
1.576 + TInt length = iClientWriteBuffer->Length();
1.577 + if (length < 1 || length > KBufferSize)
1.578 + {
1.579 + // need to reset object so it can be reused
1.580 + iWriteRequest->Reset();
1.581 + return KErrArgument;
1.582 + }
1.583 +
1.584 + return KErrNone;
1.585 + }
1.586 +
1.587 +void DExampleChannel::StartWriteDes()
1.588 + {
1.589 + SendFromWriteBuffer(); // called in DFC thread as may require serialised access to hardware
1.590 + }
1.591 +
1.592 +void DExampleChannel::ReceiveToReadBuffer()
1.593 + {
1.594 + // just queue a timer to simulate an asynchronous receive operation
1.595 + // actually will return the previous contents of the buffer
1.596 + iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc);
1.597 + }
1.598 +
1.599 +void DExampleChannel::SendFromWriteBuffer()
1.600 + {
1.601 + // just queue a timer to simulate an asynchronous send operation
1.602 + iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
1.603 + }
1.604 +
1.605 +void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
1.606 + {
1.607 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.608 + self->CompleteRead();
1.609 + }
1.610 +
1.611 +void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
1.612 + {
1.613 + DExampleChannel* self = (DExampleChannel*)aPtr;
1.614 + self->CompleteWrite();
1.615 + }
1.616 +
1.617 +void DExampleChannel::CompleteRead()
1.618 + {
1.619 + TPtrC8 des(iBuffer, iClientReadBuffer->MaxLength());
1.620 + TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, des, 0, KChunkShiftBy0, iClient);
1.621 + Kern::QueueBufferRequestComplete(iClient, iReadRequest, r);
1.622 + }
1.623 +
1.624 +void DExampleChannel::CompleteWrite()
1.625 + {
1.626 + TPtr8 des(iBuffer, iClientWriteBuffer->Length());
1.627 + TInt r = Kern::ThreadBufRead(iClient, iClientWriteBuffer, des, 0, KChunkShiftBy0);
1.628 + Kern::QueueBufferRequestComplete(iClient, iWriteRequest, r);
1.629 + }
1.630 +
1.631 +//
1.632 +// Logical device
1.633 +//
1.634 +
1.635 +class DExampleFactory : public DLogicalDevice
1.636 + {
1.637 +public:
1.638 + DExampleFactory();
1.639 + virtual TInt Install();
1.640 + virtual void GetCaps(TDes8& aDes) const;
1.641 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.642 + };
1.643 +
1.644 +DExampleFactory::DExampleFactory()
1.645 + {
1.646 + iParseMask = 0;
1.647 + iVersion = TVersion(1, 0, 0);
1.648 + }
1.649 +
1.650 +TInt DExampleFactory::Install()
1.651 + {
1.652 + return SetName(&KPagingExample1PostLdd);
1.653 + }
1.654 +
1.655 +void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
1.656 + {
1.657 + // not used but required as DLogicalDevice::GetCaps is pure virtual
1.658 + }
1.659 +
1.660 +TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
1.661 + {
1.662 + aChannel = new DExampleChannel;
1.663 + return aChannel ? KErrNone : KErrNoMemory;
1.664 + }
1.665 +
1.666 +DECLARE_STANDARD_LDD()
1.667 + {
1.668 + return new DExampleFactory;
1.669 + }