os/kernelhwsrv/kerneltest/e32test/demandpaging/d_pagingexample_1_pre.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}