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