First public contribution.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\e32test\demandpaging\d_pagingexample_2_pre.cpp
15 // Demand paging migration example device driver d_pagingexample_2_pre: a
16 // DLogicalChannelBase-dervied driver, pre-migration
20 #include "d_pagingexample.h"
21 #include <kernel/kernel.h>
22 #include <kernel/kern_priv.h>
24 const TInt KBufferSize = KMaxTransferSize;
30 class DExampleChannel : public DLogicalChannelBase
33 typedef RPagingExample::TConfigData TConfigData;
34 typedef RPagingExample::TValueStruct TValueStruct;
38 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
39 virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2);
40 TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
41 TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
42 TInt DoCancel(TUint aMask);
46 void GetConfig(TConfigData&);
47 void SetConfig(const TConfigData&);
48 TInt StartNotify(TRequestStatus* aStatus);
49 TInt StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus);
50 TInt StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus);
51 TInt StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
52 TInt StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus);
53 TInt StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus);
54 TInt StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus);
55 void ReceiveToReadBuffer();
56 void SendFromWriteBuffer();
57 static void CancelDfcFunc(TAny* aPtr);
58 static void AsyncGetValueCompleteDfcFunc(TAny* aPtr);
59 static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr);
60 static void ReceiveCompleteDfcFunc(TAny* aPtr);
61 static void SendCompleteDfcFunc(TAny* aPtr);
62 void CompleteNotify();
63 void CompleteAsyncGetValue();
64 void CompleteAsyncGetValue2();
75 TRequestStatus* iNotifyStatus;
78 TRequestStatus* iAsyncGetValueStatus;
79 TInt* iAsyncGetValueDest;
80 NTimer iAsyncGetValueTimer;
81 TDfc iAsyncGetValueDfc;
84 TRequestStatus* iAsyncGetValue2Status;
85 TInt* iAsyncGetValue2Dest1;
86 TInt* iAsyncGetValue2Dest2;
87 NTimer iAsyncGetValue2Timer;
88 TDfc iAsyncGetValue2Dfc;
91 TRequestStatus* iReadStatus;
96 TDfc iCompleteReadDfc;
99 TRequestStatus* iWriteStatus;
103 const TDesC8* iWriteDes;
104 TDfc iCompleteWriteDfc;
105 TUint8 iBuffer[KBufferSize];
108 DExampleChannel::DExampleChannel() :
109 iCancelDfc(CancelDfcFunc, this, DfcQ(), 0),
110 iAsyncGetValueTimer(NULL, this),
111 iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, DfcQ(), 0),
112 iAsyncGetValue2Timer(NULL, this),
113 iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, DfcQ(), 0),
114 iReadTimer(NULL, this),
115 iCompleteReadDfc(ReceiveCompleteDfcFunc, this, DfcQ(), 0),
116 iWriteTimer(NULL, this),
117 iCompleteWriteDfc(SendCompleteDfcFunc, this, DfcQ(), 0)
119 iClient = &Kern::CurrentThread();
123 DExampleChannel::~DExampleChannel()
125 Kern::SafeClose((DObject*&)iClient, NULL);
128 TDfcQue* DExampleChannel::DfcQ()
130 return Kern::DfcQue0();
133 TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
138 TInt DExampleChannel::Request(TInt aReqNo, TAny* a1, TAny* a2)
141 if (&Kern::CurrentThread() != iClient)
142 r = KErrAccessDenied; // we only support one client
143 else if (aReqNo==KMaxTInt)
146 r = DoCancel((TInt)a1);
151 TRequestStatus* pS=(TRequestStatus*)a1;
152 TAny* array[2] = { NULL, NULL };
153 kumemget32(array, a2, 2 * sizeof(TAny*));
154 r = DoRequest(~aReqNo, pS, array[0], array[1]);
156 Kern::RequestComplete(pS, r);
162 r = DoControl(aReqNo, a1, a2);
167 TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
170 TConfigData configBuffer;
173 case RPagingExample::EGetConfig:
174 GetConfig(configBuffer);
175 umemput32(a1, (TAny*)&configBuffer, sizeof(TConfigData));
178 case RPagingExample::ESetConfig:
179 umemget32(&configBuffer, a1, sizeof(TConfigData));
180 SetConfig(configBuffer);
184 r = KErrNotSupported;
189 TInt DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
191 TInt r = KErrNotSupported;
194 case RPagingExample::ERequestNotify:
195 r = StartNotify(aStatus);
198 case RPagingExample::ERequestAsyncGetValue:
199 r = StartAsyncGetValue((TInt*)a1, aStatus);
202 case RPagingExample::ERequestAsyncGetValue2:
203 r = StartAsyncGetValue2((TInt*)a1, (TInt*)a2, aStatus);
206 case RPagingExample::ERequestRead:
207 r = StartRead(a1, (TInt)a2, aStatus);
210 case RPagingExample::ERequestReadDes:
211 r = StartReadDes((TDes8*)a1, aStatus);
214 case RPagingExample::ERequestWrite:
215 r = StartWrite(a1, (TInt)a2, aStatus);
218 case RPagingExample::ERequestWriteDes:
219 r = StartWriteDes((TDes8*)a1, aStatus);
225 TInt DExampleChannel::DoCancel(TUint /*aMask*/)
231 void DExampleChannel::CancelDfcFunc(TAny* aPtr)
233 DExampleChannel* self = (DExampleChannel*)aPtr;
237 void DExampleChannel::Cancel()
239 if (iAsyncGetValueStatus)
241 iAsyncGetValueTimer.Cancel();
242 iAsyncGetValueDfc.Cancel();
243 Kern::RequestComplete(iClient, iAsyncGetValueStatus, KErrCancel);
246 if (iAsyncGetValue2Status)
248 iAsyncGetValue2Timer.Cancel();
249 iAsyncGetValue2Dfc.Cancel();
250 Kern::RequestComplete(iClient, iAsyncGetValue2Status, KErrCancel);
256 iCompleteReadDfc.Cancel();
257 Kern::RequestComplete(iClient, iReadStatus, KErrCancel);
262 iWriteTimer.Cancel();
263 iCompleteWriteDfc.Cancel();
264 Kern::RequestComplete(iClient, iWriteStatus, KErrCancel);
268 void DExampleChannel::Shutdown()
272 void DExampleChannel::GetConfig(TConfigData& aConfigOut)
274 NKern::FMWait(&iLock);
275 aConfigOut = iConfig;
276 NKern::FMSignal(&iLock);
279 void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
281 NKern::FMWait(&iLock);
282 iConfig = aNewConfig;
283 NKern::FMSignal(&iLock);
286 TInt DExampleChannel::StartNotify(TRequestStatus* aStatus)
288 iNotifyStatus = aStatus;
289 CompleteNotify(); // example implementation completes the request immediately
293 void DExampleChannel::CompleteNotify()
295 Kern::RequestComplete(iClient, iNotifyStatus, KErrNone);
298 TInt DExampleChannel::StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
300 iAsyncGetValueDest = aValue;
301 iAsyncGetValueStatus = aStatus;
303 // queue a timer to simulate an asynchronous operation
304 iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
308 void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
310 DExampleChannel* self = (DExampleChannel*)aPtr;
311 self->CompleteAsyncGetValue();
314 void DExampleChannel::CompleteAsyncGetValue()
318 value.iValue2 = _L8("shrt");
319 TInt r = Kern::ThreadRawWrite(iClient, iAsyncGetValueDest, (TAny*)&value, sizeof(TValueStruct), iClient);
320 Kern::RequestComplete(iClient, iAsyncGetValueStatus, r);
323 TInt DExampleChannel::StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
325 iAsyncGetValue2Dest1 = aValue1;
326 iAsyncGetValue2Dest2 = aValue2;
327 iAsyncGetValue2Status = aStatus;
329 // queue a timer to simulate an asynchronous operation
330 iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
334 void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
336 DExampleChannel* self = (DExampleChannel*)aPtr;
337 self->CompleteAsyncGetValue2();
340 void DExampleChannel::CompleteAsyncGetValue2()
344 TInt r = Kern::ThreadRawWrite(iClient, iAsyncGetValue2Dest1, (TAny*)&value1, sizeof(TInt), iClient);
346 r = Kern::ThreadRawWrite(iClient, iAsyncGetValue2Dest2, (TAny*)&value2, sizeof(TInt), iClient);
347 Kern::RequestComplete(iClient, iAsyncGetValue2Status, r);
350 TInt DExampleChannel::StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
352 if (!NKern::CompareAndSwap(*(TAny**)&iReadStatus, NULL, aStatus))
354 if (aLength < 1 || aLength > KBufferSize)
360 iReadLength = aLength;
361 ReceiveToReadBuffer();
365 TInt DExampleChannel::StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
367 if (!NKern::CompareAndSwap(*(TAny**)&iReadStatus, NULL, aStatus))
369 TInt r = Kern::ThreadGetDesMaxLength(iClient, aDesOut);
376 if (length < 1 || length > KBufferSize)
382 iReadLength = length;
383 ReceiveToReadBuffer();
387 TInt DExampleChannel::StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
389 if (!NKern::CompareAndSwap(*(TAny**)&iWriteStatus, NULL, aStatus))
391 if (aLength < 1 || aLength > KBufferSize)
397 iWriteLength = aLength;
398 SendFromWriteBuffer();
402 TInt DExampleChannel::StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
404 if (!NKern::CompareAndSwap(*(TAny**)&iWriteStatus, NULL, aStatus))
406 TInt r = Kern::ThreadGetDesLength(iClient, aDesIn);
410 if (length < 1 || length > KBufferSize)
415 iWriteLength = length;
417 SendFromWriteBuffer();
421 void DExampleChannel::ReceiveToReadBuffer()
423 // just queue a timer to simulate an asynchronous receive operation
424 // actually will return the previous contents of the buffer
425 NKern::FMWait(&iLock);
426 // The synchonisation is for illustrative purposes only - in a real driver we might make use of
427 // the configution here, so this would need to be protected from concurrent modification.
428 NKern::FMSignal(&iLock);
429 iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc);
432 void DExampleChannel::SendFromWriteBuffer()
434 // just queue a timer to simulate an asynchronous send operation
435 NKern::FMWait(&iLock);
436 // The synchonisation is for illustrative purposes only - in a real driver we might make use of
437 // the configution here, so this would need to be protected from concurrent modification.
438 NKern::FMSignal(&iLock);
439 iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
442 void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
444 DExampleChannel* self = (DExampleChannel*)aPtr;
445 self->CompleteRead();
448 void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
450 DExampleChannel* self = (DExampleChannel*)aPtr;
451 self->CompleteWrite();
454 void DExampleChannel::CompleteRead()
459 r = Kern::ThreadRawWrite(iClient, iReadDest, iBuffer, iReadLength, iClient);
464 TPtrC8 des(iBuffer, iReadLength);
465 r = Kern::ThreadDesWrite(iClient, iReadDes, des, 0, KChunkShiftBy0, iClient);
470 Kern::RequestComplete(iClient, iReadStatus, r);
473 void DExampleChannel::CompleteWrite()
478 r = Kern::ThreadRawRead(iClient, iWriteSrc, iBuffer, iWriteLength);
483 TPtr8 des(iBuffer, iWriteLength);
484 r = Kern::ThreadDesRead(iClient, iWriteDes, des, 0);
489 Kern::RequestComplete(iClient, iWriteStatus, r);
496 class DExampleFactory : public DLogicalDevice
500 virtual TInt Install();
501 virtual void GetCaps(TDes8& aDes) const;
502 virtual TInt Create(DLogicalChannelBase*& aChannel);
505 DExampleFactory::DExampleFactory()
508 iVersion = TVersion(1, 0, 0);
511 TInt DExampleFactory::Install()
513 return SetName(&KPagingExample2PreLdd);
516 void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
518 // not used but required as DLogicalDevice::GetCaps is pure virtual
521 TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
523 aChannel = new DExampleChannel;
524 return aChannel ? KErrNone : KErrNoMemory;
527 DECLARE_STANDARD_LDD()
529 return new DExampleFactory;