kerneltest/e32test/demandpaging/d_pagingexample_1_pre.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_1_pre.cpp
       
    15 // Demand paging migration example device driver d_pagingexample_1_pre: a DLogicalChannel-dervied
       
    16 // driver, pre-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 void HandleMsg(TMessageBase* aMsg);
       
    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 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 AsyncGetValueCompleteDfcFunc(TAny* aPtr);
       
    58 	static void AsyncGetValue2CompleteDfcFunc(TAny* aPtr);
       
    59 	static void ReceiveCompleteDfcFunc(TAny* aPtr);
       
    60 	static void SendCompleteDfcFunc(TAny* aPtr);
       
    61 	void CompleteNotify();
       
    62 	void CompleteAsyncGetValue();
       
    63 	void CompleteAsyncGetValue2();
       
    64 	void CompleteRead();
       
    65 	void CompleteWrite();
       
    66 private:
       
    67 	TDynamicDfcQue* iDynamicDfcQ;
       
    68 	TConfigData iConfig;
       
    69 	DThread* iClient;
       
    70 	
       
    71 	// Notify
       
    72 	TRequestStatus* iNotifyStatus;
       
    73 	
       
    74 	// Async get value
       
    75 	TRequestStatus* iAsyncGetValueStatus;
       
    76 	TInt* iAsyncGetValueDest;
       
    77 	NTimer iAsyncGetValueTimer;
       
    78 	TDfc iAsyncGetValueDfc;
       
    79 	
       
    80 	// Async get value 2
       
    81 	TRequestStatus* iAsyncGetValue2Status;
       
    82 	TInt* iAsyncGetValue2Dest1;
       
    83 	TInt* iAsyncGetValue2Dest2;
       
    84 	NTimer iAsyncGetValue2Timer;
       
    85 	TDfc iAsyncGetValue2Dfc;
       
    86 	
       
    87 	// Read
       
    88 	TRequestStatus* iReadStatus;
       
    89 	NTimer iReadTimer;
       
    90 	TAny* iReadDest;
       
    91 	TInt iReadLength;
       
    92 	TDes8* iReadDes;
       
    93 	TDfc iCompleteReadDfc;
       
    94 	
       
    95 	// Write
       
    96 	TRequestStatus* iWriteStatus;
       
    97 	NTimer iWriteTimer;
       
    98 	TAny* iWriteSrc;
       
    99 	TInt iWriteLength;
       
   100 	const TDesC8* iWriteDes;
       
   101 	TDfc iCompleteWriteDfc;
       
   102 	TUint8 iBuffer[KBufferSize];
       
   103 	};
       
   104 
       
   105 DExampleChannel::DExampleChannel() :
       
   106 	iAsyncGetValueTimer(NULL, this),
       
   107 	iAsyncGetValueDfc(AsyncGetValueCompleteDfcFunc, this, 0),
       
   108 	iAsyncGetValue2Timer(NULL, this),
       
   109 	iAsyncGetValue2Dfc(AsyncGetValue2CompleteDfcFunc, this, 0),
       
   110 	iReadTimer(NULL, this),
       
   111 	iCompleteReadDfc(ReceiveCompleteDfcFunc, this, 0),
       
   112 	iWriteTimer(NULL, this),
       
   113 	iCompleteWriteDfc(SendCompleteDfcFunc, this, 0)
       
   114 	{
       
   115 	iClient = &Kern::CurrentThread();
       
   116 	iClient->Open();
       
   117 	}
       
   118 
       
   119 DExampleChannel::~DExampleChannel()
       
   120 	{
       
   121 	Kern::SafeClose((DObject*&)iClient, NULL);
       
   122 	if (iDynamicDfcQ)
       
   123 		iDynamicDfcQ->Destroy();
       
   124 	}
       
   125 
       
   126 TDfcQue* DExampleChannel::DfcQ()
       
   127 	{
       
   128 	return iDynamicDfcQ;
       
   129 	}
       
   130 
       
   131 TInt DExampleChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
       
   132 	{
       
   133 	// Existing drivers may use the kernel global DFC queue, but for testing purposes we actually
       
   134 	// allocate our own so we can control its realtime state.
       
   135 	TInt r = Kern::DynamicDfcQCreate(iDynamicDfcQ, KDfcQThreadPriority, KPagingExample1PreLdd);
       
   136 	if (r != KErrNone)
       
   137 		return r;
       
   138 	iDynamicDfcQ->SetRealtimeState(ERealtimeStateWarn);
       
   139 	
       
   140 	SetDfcQ(DfcQ());
       
   141 	iAsyncGetValueDfc.SetDfcQ(DfcQ());
       
   142 	iAsyncGetValue2Dfc.SetDfcQ(DfcQ());
       
   143 	iCompleteReadDfc.SetDfcQ(DfcQ());
       
   144 	iCompleteWriteDfc.SetDfcQ(DfcQ());
       
   145 	iMsgQ.Receive();
       
   146 	return KErrNone;
       
   147 	}
       
   148 
       
   149 void DExampleChannel::HandleMsg(TMessageBase* aMsg)
       
   150 	{
       
   151 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   152     TInt id=m.iValue;
       
   153 	
       
   154 	if (id==(TInt)ECloseMsg)
       
   155 		{
       
   156 		Shutdown();
       
   157 		m.Complete(KErrNone,EFalse);
       
   158 		return;
       
   159 		}
       
   160 
       
   161 	// we only support one client
       
   162 	if (m.Client() != iClient)
       
   163 		{
       
   164 		m.Complete(KErrAccessDenied,ETrue);
       
   165 		return;
       
   166 		}
       
   167 	
       
   168     if (id==KMaxTInt)
       
   169 		{
       
   170 		// DoCancel
       
   171 		DoCancel(m.Int0());
       
   172 		m.Complete(KErrNone,ETrue);
       
   173 		return;
       
   174 		}
       
   175     else if (id<0)
       
   176 		{
       
   177 		// DoRequest
       
   178 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   179 		TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
       
   180 		if (r!=KErrNone)
       
   181 			Kern::RequestComplete(m.Client(),pS,r);
       
   182 		m.Complete(KErrNone,ETrue);
       
   183 		}
       
   184     else
       
   185 		{
       
   186 		// DoControl
       
   187 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   188 		m.Complete(r,ETrue);
       
   189 		}
       
   190 	}
       
   191 
       
   192 TInt DExampleChannel::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
       
   193 	{
       
   194 	TInt r = KErrNone;
       
   195 	switch (aFunction)
       
   196 		{
       
   197 		case RPagingExample::ESetRealtimeState:
       
   198 			iDynamicDfcQ->SetRealtimeState(a1 ? ERealtimeStateOn : ERealtimeStateWarn);
       
   199 			break;
       
   200 			
       
   201 		case RPagingExample::EGetConfig:
       
   202 			r = Kern::ThreadRawWrite(iClient, a1, (TAny*)&iConfig, sizeof(TConfigData), iClient);
       
   203 			break;
       
   204 
       
   205 		case RPagingExample::ESetConfig:
       
   206 			{
       
   207 			TConfigData newConfig;
       
   208 			r = Kern::ThreadRawRead(iClient, a1, &newConfig, sizeof(TConfigData));
       
   209 			if (r == KErrNone)
       
   210 				SetConfig(newConfig);
       
   211 			}
       
   212 			break;
       
   213 
       
   214 		default:
       
   215 			r = KErrNotSupported;
       
   216 		}
       
   217 	return r;
       
   218 	}
       
   219 
       
   220 TInt DExampleChannel::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
   221 	{
       
   222 	TInt r = KErrNotSupported;
       
   223 	switch (aFunction)
       
   224 		{
       
   225 		case RPagingExample::ERequestNotify:
       
   226 			r = StartNotify(aStatus);
       
   227 			break;
       
   228 			
       
   229 		case RPagingExample::ERequestAsyncGetValue:
       
   230 			r = StartAsyncGetValue((TInt*)a1, aStatus);
       
   231 			break;
       
   232 			
       
   233 		case RPagingExample::ERequestAsyncGetValue2:
       
   234 			r = StartAsyncGetValue2((TInt*)a1, (TInt*)a2, aStatus);
       
   235 			break;
       
   236 			
       
   237 		case RPagingExample::ERequestRead:
       
   238 			r = StartRead(a1, (TInt)a2, aStatus);
       
   239 			break;
       
   240 			
       
   241 		case RPagingExample::ERequestReadDes:
       
   242 			r = StartReadDes((TDes8*)a1, aStatus);
       
   243 			break;
       
   244 
       
   245 		case RPagingExample::ERequestWrite:
       
   246 			r = StartWrite(a1, (TInt)a2, aStatus);
       
   247 			break;
       
   248 			
       
   249 		case RPagingExample::ERequestWriteDes:
       
   250 			r = StartWriteDes((TDes8*)a1, aStatus);
       
   251 			break;
       
   252 		}
       
   253 	return r;
       
   254 	}
       
   255 
       
   256 TInt DExampleChannel::DoCancel(TUint /*aMask*/)
       
   257 	{
       
   258 	if (iAsyncGetValueStatus)
       
   259 		{
       
   260 		iAsyncGetValueTimer.Cancel();
       
   261 		iAsyncGetValueDfc.Cancel();
       
   262 		Kern::RequestComplete(iClient, iAsyncGetValueStatus, KErrCancel);
       
   263 		}
       
   264 
       
   265 	if (iAsyncGetValue2Status)
       
   266 		{
       
   267 		iAsyncGetValue2Timer.Cancel();
       
   268 		iAsyncGetValue2Dfc.Cancel();
       
   269 		Kern::RequestComplete(iClient, iAsyncGetValue2Status, KErrCancel);
       
   270 		}
       
   271 
       
   272 	if (iReadStatus)
       
   273 		{
       
   274 		iReadTimer.Cancel();
       
   275 		iCompleteReadDfc.Cancel();
       
   276 		Kern::RequestComplete(iClient, iReadStatus, KErrCancel);
       
   277 		}
       
   278 
       
   279 	if (iWriteStatus)
       
   280 		{
       
   281 		iWriteTimer.Cancel();
       
   282 		iCompleteWriteDfc.Cancel();
       
   283 		Kern::RequestComplete(iClient, iWriteStatus, KErrCancel);
       
   284 		}
       
   285 	
       
   286 	return KErrNone;
       
   287 	}
       
   288 
       
   289 void DExampleChannel::Shutdown()
       
   290 	{
       
   291 	}
       
   292 
       
   293 void DExampleChannel::SetConfig(const TConfigData& aNewConfig)
       
   294 	{
       
   295 	iConfig = aNewConfig;
       
   296 	}
       
   297 
       
   298 TInt DExampleChannel::StartNotify(TRequestStatus* aStatus)
       
   299 	{
       
   300 	iNotifyStatus = aStatus;	
       
   301 	CompleteNotify(); // example implementation completes the request immediately
       
   302 	return KErrNone;
       
   303 	}
       
   304 
       
   305 void DExampleChannel::CompleteNotify()
       
   306 	{
       
   307 	Kern::RequestComplete(iClient, iNotifyStatus, KErrNone);
       
   308 	}
       
   309 
       
   310 TInt DExampleChannel::StartAsyncGetValue(TInt* aValue, TRequestStatus* aStatus)
       
   311 	{
       
   312 	iAsyncGetValueDest = aValue;
       
   313 	iAsyncGetValueStatus = aStatus;
       
   314 
       
   315 	// queue a timer to simulate an asynchronous operation
       
   316 	iAsyncGetValueTimer.OneShot(KAsyncDelay, iAsyncGetValueDfc);
       
   317 	return KErrNone;
       
   318 	}
       
   319 
       
   320 void DExampleChannel::AsyncGetValueCompleteDfcFunc(TAny* aPtr)
       
   321 	{
       
   322 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   323 	self->CompleteAsyncGetValue();
       
   324 	}
       
   325 
       
   326 void DExampleChannel::CompleteAsyncGetValue()
       
   327 	{
       
   328 	TValueStruct value;
       
   329 	value.iValue1 = 1;
       
   330 	value.iValue2 = _L8("shrt");
       
   331 	TInt r = Kern::ThreadRawWrite(iClient, iAsyncGetValueDest, (TAny*)&value, sizeof(TValueStruct), iClient);
       
   332 	Kern::RequestComplete(iClient, iAsyncGetValueStatus, r);
       
   333 	}
       
   334 
       
   335 TInt DExampleChannel::StartAsyncGetValue2(TInt* aValue1, TInt* aValue2, TRequestStatus* aStatus)
       
   336 	{
       
   337 	iAsyncGetValue2Dest1 = aValue1;
       
   338 	iAsyncGetValue2Dest2 = aValue2;
       
   339 	iAsyncGetValue2Status = aStatus;
       
   340 
       
   341 	// queue a timer to simulate an asynchronous operation
       
   342 	iAsyncGetValue2Timer.OneShot(KAsyncDelay, iAsyncGetValue2Dfc);
       
   343 	return KErrNone;
       
   344 	}
       
   345 
       
   346 void DExampleChannel::AsyncGetValue2CompleteDfcFunc(TAny* aPtr)
       
   347 	{
       
   348 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   349 	self->CompleteAsyncGetValue2();
       
   350 	}
       
   351 
       
   352 void DExampleChannel::CompleteAsyncGetValue2()
       
   353 	{
       
   354 	TInt value1 = 1;
       
   355 	TInt value2 = 2;
       
   356 	TInt r = Kern::ThreadRawWrite(iClient, iAsyncGetValue2Dest1, (TAny*)&value1, sizeof(TInt), iClient);
       
   357 	if (r == KErrNone)
       
   358 		r = Kern::ThreadRawWrite(iClient, iAsyncGetValue2Dest2, (TAny*)&value2, sizeof(TInt), iClient);
       
   359 	Kern::RequestComplete(iClient, iAsyncGetValue2Status, r);
       
   360 	}
       
   361 
       
   362 TInt DExampleChannel::StartRead(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
       
   363 	{
       
   364 	if (iReadStatus)
       
   365 		return KErrInUse;
       
   366 	if (aLength < 1 || aLength > KBufferSize)
       
   367 		return KErrArgument;
       
   368 	iReadStatus = aStatus;
       
   369 	iReadDest = aBuffer;
       
   370 	iReadLength = aLength;
       
   371 	ReceiveToReadBuffer();
       
   372 	return KErrNone;
       
   373 	}
       
   374 
       
   375 TInt DExampleChannel::StartReadDes(TDes8* aDesOut, TRequestStatus* aStatus)
       
   376 	{
       
   377 	if (iReadStatus)
       
   378 		return KErrInUse;
       
   379 	TInt r = Kern::ThreadGetDesMaxLength(iClient, aDesOut);
       
   380 	if (r < 0)
       
   381 		return r;
       
   382 	TInt length = r;
       
   383 	if (length < 1 || length > KBufferSize)
       
   384 		return KErrArgument;
       
   385 	iReadStatus = aStatus;
       
   386 	iReadDes = aDesOut;
       
   387 	iReadLength = length;
       
   388 	ReceiveToReadBuffer();
       
   389 	return KErrNone;
       
   390 	}
       
   391 
       
   392 TInt DExampleChannel::StartWrite(TAny* aBuffer, TInt aLength, TRequestStatus* aStatus)
       
   393 	{
       
   394 	if (iWriteStatus)
       
   395 		return KErrInUse;
       
   396 	if (aLength < 1 || aLength > KBufferSize)
       
   397 		return KErrArgument;
       
   398 	iWriteStatus = aStatus;
       
   399 	iWriteSrc = aBuffer;
       
   400 	iWriteLength = aLength;
       
   401 	SendFromWriteBuffer();
       
   402 	return KErrNone;
       
   403 	}
       
   404 
       
   405 TInt DExampleChannel::StartWriteDes(const TDesC8* aDesIn, TRequestStatus* aStatus)
       
   406 	{
       
   407 	if (iWriteStatus)
       
   408 		return KErrInUse;
       
   409 	TInt r = Kern::ThreadGetDesLength(iClient, aDesIn);
       
   410 	if (r < 0)
       
   411 		return r;
       
   412 	TInt length = r;
       
   413 	if (length < 1 || length > KBufferSize)
       
   414 		return KErrArgument;
       
   415 	iWriteStatus = aStatus;
       
   416 	iWriteLength = length;
       
   417 	iWriteDes = aDesIn;
       
   418 	SendFromWriteBuffer();
       
   419 	return KErrNone;
       
   420 	}
       
   421 
       
   422 void DExampleChannel::ReceiveToReadBuffer()
       
   423 	{
       
   424 	// just queue a timer to simulate an asynchronous receive operation
       
   425 	// actually will return the previous contents of the buffer
       
   426 	iReadTimer.OneShot(KAsyncDelay, iCompleteReadDfc);
       
   427 	}
       
   428 
       
   429 void DExampleChannel::SendFromWriteBuffer()
       
   430 	{
       
   431 	// just queue a timer to simulate an asynchronous send operation
       
   432 	iWriteTimer.OneShot(KAsyncDelay, iCompleteWriteDfc);
       
   433 	}
       
   434 
       
   435 void DExampleChannel::ReceiveCompleteDfcFunc(TAny* aPtr)
       
   436 	{
       
   437 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   438 	self->CompleteRead();
       
   439 	}
       
   440 
       
   441 void DExampleChannel::SendCompleteDfcFunc(TAny* aPtr)
       
   442 	{
       
   443 	DExampleChannel* self = (DExampleChannel*)aPtr;
       
   444 	self->CompleteWrite();
       
   445 	}
       
   446 
       
   447 void DExampleChannel::CompleteRead()
       
   448 	{
       
   449 	TInt r;
       
   450 	if (iReadDest)
       
   451 		{
       
   452 		r = Kern::ThreadRawWrite(iClient, iReadDest, iBuffer, iReadLength, iClient);
       
   453 		iReadDest = NULL;
       
   454 		}
       
   455 	else
       
   456 		{
       
   457 		TPtrC8 des(iBuffer, iReadLength);
       
   458 		r = Kern::ThreadDesWrite(iClient, iReadDes, des, 0, KChunkShiftBy0, iClient);
       
   459 		iReadDes = NULL;
       
   460 		}
       
   461 	
       
   462 	iReadLength = 0;
       
   463 	Kern::RequestComplete(iClient, iReadStatus, r);
       
   464 	}
       
   465 
       
   466 void DExampleChannel::CompleteWrite()
       
   467 	{
       
   468 	TInt r;
       
   469 	if (iWriteSrc)
       
   470 		{
       
   471 		r = Kern::ThreadRawRead(iClient, iWriteSrc, iBuffer, iWriteLength);
       
   472 		iWriteSrc = NULL;
       
   473 		}
       
   474 	else
       
   475 		{
       
   476 		TPtr8 des(iBuffer, iWriteLength);
       
   477 		r = Kern::ThreadDesRead(iClient, iWriteDes, des, 0);
       
   478 		iWriteDes = NULL;
       
   479 		}
       
   480 	
       
   481 	iWriteLength = 0;
       
   482 	Kern::RequestComplete(iClient, iWriteStatus, r);
       
   483 	}
       
   484 
       
   485 //
       
   486 // Logical device
       
   487 //
       
   488 
       
   489 class DExampleFactory : public DLogicalDevice
       
   490 	{
       
   491 public:
       
   492 	DExampleFactory();
       
   493 	virtual TInt Install();
       
   494 	virtual void GetCaps(TDes8& aDes) const;
       
   495 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   496 	};
       
   497 
       
   498 DExampleFactory::DExampleFactory()
       
   499 	{
       
   500 	iParseMask = 0;
       
   501 	iVersion = TVersion(1, 0, 0);
       
   502 	}
       
   503 
       
   504 TInt DExampleFactory::Install()
       
   505 	{
       
   506 	return SetName(&KPagingExample1PreLdd);
       
   507 	}
       
   508 
       
   509 void DExampleFactory::GetCaps(TDes8& /*aDes*/) const
       
   510 	{
       
   511 	// not used but required as DLogicalDevice::GetCaps is pure virtual
       
   512 	}
       
   513 
       
   514 TInt DExampleFactory::Create(DLogicalChannelBase*& aChannel)
       
   515 	{
       
   516 	aChannel = new DExampleChannel;
       
   517 	return aChannel ? KErrNone : KErrNoMemory;
       
   518 	}
       
   519 
       
   520 DECLARE_STANDARD_LDD()
       
   521 	{
       
   522 	return new DExampleFactory;
       
   523 	}