os/kernelhwsrv/kernel/eka/drivers/pipe/dpipe.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-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 //
    15 
    16 
    17 #include <kernel/kern_priv.h>
    18 #include "dpipe.h"
    19 
    20 //_LIT(KPipePanicCategory,"PipePanic");
    21 const TInt KPipeGranularity   = 8;
    22 
    23 DECLARE_STANDARD_LDD()
    24 /** 
    25 Standard export function for LDDs. This creates a DLogicalDevice derived
    26 object, in this case our DPipeDevice
    27 */
    28 	{
    29 	return new DPipeDevice;
    30 	}
    31 
    32 DPipeDevice::DPipeDevice()
    33 /**
    34 DPipeDevice Constructor has minimal implementation such setting the version number
    35 Indicate the use of unit number
    36 
    37 @param		None
    38 
    39 @return 	None
    40 */ 
    41 	{
    42 	iCount = 0;
    43     iIdindex = 0;
    44     iAllocated = 0;
    45 	iVersion = RPipe::VersionRequired();
    46 	}
    47 
    48 
    49 DPipeDevice::~DPipeDevice()
    50 	{
    51 	// Delete the existing pipes
    52 	for(TInt count = 0; count<iCount; count++)
    53 		{
    54 		DPipe* pipe=iDpipes[count];
    55 		pipe->Wait();
    56 		pipe->CloseAll();
    57 		delete pipe;
    58 		}
    59 	Kern::Free(iDpipes);
    60 	iMutex->Close(NULL);
    61 	}
    62 
    63 
    64 TInt DPipeDevice::Install()
    65 /**
    66 Second stage constructor and at least set a name for the 
    67 driver object. Inherited from DLogicalDevice. This must at least set a name
    68 for the driver object.
    69 
    70 @param		None
    71 
    72 @return 	KErrNone 	If successful, otherwise one of the system wide error codes.
    73 */
    74 	{
    75 	_LIT(KMutexName,"PipeDeviceMutex");
    76 	TInt err = Kern::MutexCreate(iMutex, KMutexName, KMutexOrdGeneral1);
    77 	if (err)
    78 		{
    79 		return err;
    80 		}
    81 	
    82 	return SetName(&RPipe::Name());
    83 	}
    84 
    85 
    86 void DPipeDevice::GetCaps(TDes8& aDes) const
    87 /**
    88 Returns the driver capabilities. Called in the response to
    89 an RPipe::GetCaps() request
    90 
    91 @param  	aDes 		Descriptor into which capabilities information 
    92 					    is to be written
    93 @return 	None
    94 */
    95 	{
    96 	// Write it back to user memory
    97 	TVersion version;
    98 	version = iVersion;
    99 	Kern::InfoCopy(aDes,(TUint8*)&version, sizeof(version));
   100 	}
   101 
   102 
   103 TInt DPipeDevice::Create(DLogicalChannelBase*& aChannel)
   104 /**
   105 Called by the kernel's device driver framework to create a Logical Channel. 
   106 This is called in the context of the user thread (client) which requested the
   107 creation of the Logical Channel. 
   108 
   109  @param 	aChannel 	Set to point to the created logical channel
   110 
   111  @return 	KErrNone 	If successful, otherwise system one of the other
   112  						wide error codes.
   113  */
   114 	{
   115 	aChannel = new DPipeChannel;
   116 	if (!aChannel)
   117 		return KErrNoMemory;
   118 	return KErrNone;
   119 	}
   120 
   121 
   122 TInt  DPipeDevice::CreatePipe(const TDesC& aName, TInt aSize, DPipe*& aPipe, TAny* aCap)
   123 /**
   124 Called by DPipeChannel instance to create named DPipe object and 
   125 associate itself with the newly created named DPipe instance.
   126 
   127 @param aName			name need to be attached to the newly created DPipe object.
   128 @param aSize			size of the DPipe object.
   129 @param aPipe	 		Pointer to DPipe, If successful set the pointer to newly created DPipe					instance else NULL						
   130 @param aCap				Pointer to TSecuritypolicy passed as void pointer
   131 
   132 @return  KErrNone 		If successful, otherwise one of the other system wide error code	
   133 @pre    Calling thread must be in a critical section.
   134 @pre    Mutex must be held
   135 */	
   136 	{	
   137 	__ASSERT_MUTEX(iMutex);
   138 	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipeDevice::CreatePipe")); 
   139 	TInt err = KErrNone;
   140 	DPipe** pS = iDpipes;
   141 	DPipe** pE = pS + iCount;
   142 	while(pS < pE)
   143 		{
   144 		DPipe* pO = *pS++;
   145 		if((pO->MatchName(&aName)))
   146 			{ 
   147 			err = KErrAlreadyExists;
   148 			break;
   149 			}
   150 		}
   151 	if(err == KErrNone)
   152 		{
   153 		DPipe* pipe = DPipe::CreatePipe(aName, aSize, aCap);	
   154 		if(pipe)
   155 			{
   156 		 	err = AddPipe(pipe);
   157 			if(err!= KErrNone)
   158 				{
   159 				delete pipe;
   160 				}
   161 			else
   162 				{
   163 				aPipe = pipe;		
   164 				}
   165 			}
   166 		else
   167 			{
   168 			err = KErrNoMemory;
   169 			}
   170 		}
   171 	__KTRACE_OPT(KPIPE, Kern::Printf("<DPipeDevice::CreatePipe ret=%d", err)); 
   172 	return err;
   173 	}
   174 
   175 
   176 DPipe*  DPipeDevice::CreatePipe(TInt aSize)
   177 /**
   178 Called by DPipeChannel instance to create un-named DPipe instance and 
   179 associate itself with the newly created un-named DPipe instance.
   180 
   181 @param aSize		size of the DPipe object.
   182 				
   183 @return  DPipe*	    If successful, otherwise NULL
   184 @pre    Mutex must be held
   185 @pre	In critical section
   186 */
   187 	{
   188 	__ASSERT_CRITICAL;
   189 	__ASSERT_MUTEX(iMutex);
   190 	TKName aName;
   191 	DPipe* pipe =  DPipe::CreatePipe(aName, aSize);
   192 	if(!pipe)
   193 		{
   194 		return NULL;
   195 		}
   196 		
   197 	TInt r = AddPipe(pipe);
   198 	if (r != KErrNone)
   199 		{
   200 		delete pipe;
   201 		return NULL;
   202 		}		
   203 	return pipe;	
   204 	}
   205 
   206 
   207 	
   208 TInt DPipeDevice::AddPipe(DPipe* aObj)
   209 /**
   210 Add an instance of Dpipe to the array. 
   211 @param aObj			Pointer to  DPipe object
   212 @return KErrNone 	If the call is successful otherwise  one of the other
   213 					system wide error code.
   214 					
   215 @pre    Calling thread must be in a critical section.
   216 @pre    Mutex to be held
   217 */
   218 	{
   219 	__ASSERT_CRITICAL; //otherwise iDPipes and iCount could go out of sync
   220 	__ASSERT_MUTEX(iMutex);
   221 	// store the current instance to the array
   222 	if(iCount == iAllocated)
   223 		{
   224 		TInt newAlloc = iAllocated + KPipeGranularity;
   225 		TInt r = Kern::SafeReAlloc((TAny*&)iDpipes, iCount * sizeof(DPipe*), newAlloc * sizeof(DPipe*));
   226 		if (r!= KErrNone)
   227 			{
   228 			return r;
   229 			}
   230 		iAllocated = newAlloc;
   231 		}
   232 	TInt id = GenerateId();	
   233 	aObj->SetId(id);
   234 	iDpipes[iCount++]= aObj;
   235 
   236 	__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::AddPipe Pipe added ID=%d", id)); 
   237 	return KErrNone;
   238 	}
   239 	
   240 
   241 	
   242 void DPipeDevice::RemovePipe(DPipe** aObj)
   243 /**
   244 Remove an instance of DPipe from the array
   245 
   246 @param	Pointer to Dpipe Array
   247 
   248 @return None
   249 
   250 @pre    Calling thread must not be in a critical section.
   251 @pre    Mutex to be held
   252 */
   253 	{
   254 	__ASSERT_MUTEX(iMutex);
   255 	__ASSERT_CRITICAL; //we don't want to leave the array inconsistant
   256 
   257  	DPipe**	pE = (iDpipes + iCount) - 1;
   258  	if(aObj<pE)
   259 		{
   260 		//bump along array elements to close the gap
   261 		wordmove((TAny*)aObj, (TAny*)(aObj+1), TInt(pE)- TInt(aObj));
   262 		}
   263 	--iCount;
   264 	if(iCount % KPipeGranularity == 0)
   265 		{
   266 			Kern::SafeReAlloc((TAny*&)iDpipes, iAllocated*sizeof(DPipe*), iCount* sizeof(DPipe*));
   267 			iAllocated = iCount;
   268 		}
   269 	}
   270 	
   271 
   272 DPipe* DPipeDevice::FindNamedPipe(const TDesC* aName)
   273 /**
   274 Called by the DPipeChannel to check if a named DPipe instance exist with a name
   275 as specified by aName parameter.
   276 
   277 @param aName		The name of the DPipe instance to search for. 
   278 
   279 @return  DPipe*	    If successful, otherwise NULL
   280 
   281 @pre Device mutex to be held
   282 */
   283 	{
   284 	__ASSERT_MUTEX(iMutex);
   285 	DPipe** pS = iDpipes;
   286 	DPipe** pE = pS + iCount;
   287 	
   288 	while(pS < pE)
   289 		{
   290 		DPipe* pO = *pS++;
   291 		if(pO->MatchName(aName))
   292 			{ 
   293 			return pO;
   294 			}
   295 		}
   296 	return NULL;
   297 	}
   298 		
   299 DPipe* DPipeDevice::FindUnnamedPipe(const TInt aId)
   300 /**
   301 Called by the DPipeChannel to check if an un-named DPipe instance exist with an ID
   302 as specified by aId parameter.
   303 
   304 @param aId			The ID of the DPipe instance to search for. 
   305 	
   306 @return  DPipe*	   If successful, otherwise NULL
   307 @pre Device mutex to be held
   308 */
   309 	{
   310 	__ASSERT_MUTEX(iMutex);
   311 	DPipe** pS = iDpipes;
   312 	DPipe** pE = pS + iCount;	
   313 	while(pS < pE)
   314 		{
   315 		DPipe* pO = *pS++;
   316 		if(pO->MatchId(aId))
   317 			{
   318 			return pO;
   319 			}
   320 		}
   321 	return NULL;
   322 	}
   323 
   324 TInt DPipeDevice::Destroy(const TDesC* aName)
   325 /**
   326 This method is called to destroy a named DPipe instance. The caller needs to have 
   327 sufficient capabilities to delete a named pipe. This method will fail if there are
   328 any handles still open on the pipe. 
   329 
   330 @param	aName		Name of the DPipe instance to be deleted.
   331 
   332 @return	KErrNone 	If successful, otherwise one of the other system wide error.
   333 
   334 */
   335 	{
   336 	TAutoWait<DMutex> autoMutex(*iMutex);
   337 	DPipe** pS = iDpipes;
   338 	DPipe**	pE = pS + iCount;
   339 	TInt err = KErrNotFound;
   340 	TInt count = 0;
   341 	while(pS < pE)
   342 		{
   343 		DPipe** pO = pS++;
   344 		DPipe* pipe = *pO;
   345 		if(((*pO)->MatchName(aName)))
   346 			{
   347 			//! Check capability 
   348 			if(pipe->GetCap())
   349 				{
   350 				if(!(pipe->GetCap()->CheckPolicy(&Kern::CurrentThread())))
   351 					{
   352 					err = KErrPermissionDenied;
   353 					break;
   354 					}
   355 				}
   356 			// Check if any handles still opened on the pipe.
   357 			pipe->Wait();
   358 			if (!pipe->IsPipeClosed())
   359 				{
   360 				err = KErrInUse;
   361 				pipe->Signal(); //need to signal if we won't be destroying pipe
   362 				break;
   363 				}
   364 			__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Destroy remove ID=%d", pipe->OpenId())); 
   365 			delete iDpipes[count];
   366 			RemovePipe(pO);
   367 			err = KErrNone;
   368 			break;
   369 			}
   370 		count ++;
   371 		}
   372 	return err;
   373 	}
   374 
   375 
   376 TInt DPipeDevice::Close(TInt aId)
   377 /**
   378 This method is called to close both named and un-named DPipe. In case of un-named DPipe
   379 if there is no further reference of a DPipeChannel exist, the corresponding un-named DPipe
   380 will be deleted. 
   381 
   382 @param aId		 	ID of the pipe that need to be closed.
   383 
   384 @return KErrNone 	If successful otherwise one of the other system wide error.
   385 
   386 */
   387 	{
   388 	TAutoWait<DMutex> autoMutex(*iMutex);
   389 	DPipe** pS = iDpipes;
   390 	DPipe**	pE = pS + iCount;
   391 	TInt err = KErrNotFound;
   392 	while(pS < pE)
   393 		{
   394 		DPipe** pO = pS++;
   395 		DPipe* pipe = *pO;
   396 		if(pipe->MatchId(aId))
   397 			{
   398 			__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Close found ID=%d", pipe->OpenId())); 
   399 			//even if we can't delete the pipe, we have
   400 			//found it so don't return KErrNotFound
   401 			err = KErrNone;
   402 
   403 			pipe->Wait();
   404 			
   405 			// we can only delete an unamed pipe with both ends closed
   406 		 	if(!pipe->IsNamedPipe() && pipe->IsPipeClosed())
   407 		 		{
   408 				__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Close remove ID=%d", pipe->OpenId())); 
   409 				delete pipe;
   410 				RemovePipe(pO); 
   411 				break;
   412 		 		}
   413 			pipe->Signal(); 
   414 
   415 			}
   416 		}
   417 	return err;
   418 	}
   419 
   420 
   421 
   422 TInt DPipeDevice::GenerateId()
   423 /**
   424 Generate a ID  and store for a Named pipe while creating.
   425 
   426 @param 	 None
   427 @return  TInt	ID for the name pipe
   428 
   429 @pre    Mutex to be held
   430 
   431 */
   432 	{
   433 	__ASSERT_MUTEX(iMutex);
   434 	iIdindex++;
   435 	return (KIdBase + iIdindex);		
   436 	}
   437 
   438 
   439 DPipeChannel::DPipeChannel()
   440 	:iClientRequest(NULL), iData(NULL), iChannelType(RPipe::EChannelUnset)
   441 /**
   442 Constructor
   443 */
   444 	{
   445 	}
   446 
   447 
   448 DPipeChannel::~DPipeChannel()
   449 /**
   450 Destructor
   451 */
   452 	{
   453 	CloseHandle();
   454 	
   455 	Kern::DestroyClientRequest(iClientRequest); //null ptr is safe
   456 	}
   457 
   458 
   459 
   460 TInt DPipeChannel::RequestUserHandle (DThread* aThread, TOwnerType aType)
   461 /**
   462 Inherited from DObject. This method is called when a user thread requests
   463 a handle to this channel. Minimal implantation here is capability check
   464 
   465 @param aThread		DThread instance reference that requests a handle to this channel.
   466 @param aType		Ownership type for the handle.
   467 
   468 @return  KErrNone  If successful otherwise one the system wide error.
   469 */
   470 	{
   471 	(void)aThread;
   472 	(void)aType;
   473  	return KErrNone;
   474 	}
   475 
   476 
   477     
   478 TInt DPipeChannel::DoCreate (TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
   479 /**
   480 Inherited from DLogicalChannelBase class.  This method represents the second stage
   481 constructor called by the kernel's device driver framework. This is called in the
   482 context of the user thread (client) which requested the creation of the Logical
   483 Channel. The thread is in critical section.
   484 
   485 @param aUnit		The unit argument supplied by the client
   486 @param aInfo		The info argument supplied by the client 
   487 @param aVer			The version argument supplied by the client 
   488 
   489 @return KErrNone 	If successful, otherwise one of the other system wide error codes.
   490 */
   491 	{
   492 	(void)aInfo;
   493 	(void)aUnit;
   494 	
   495   	// Check version
   496     if (!Kern::QueryVersionSupported(RPipe::VersionRequired(),aVer))
   497         return KErrNotSupported;
   498 
   499 	TInt r = Kern::CreateClientRequest(iClientRequest);
   500 	if(r != KErrNone)
   501 		{
   502 		return r;
   503 		}
   504 
   505 	// Done 
   506 	return KErrNone;
   507 	}
   508 
   509 
   510 TInt DPipeChannel::Request(TInt aReqNo, TAny* a1, TAny* a2)
   511 /**
   512 Called by the Device driver framework upon user request. Stores the 
   513 Thread pointer under whose context this function is called. 
   514 
   515 @param aFunction	A number identifying the  message type
   516 @param a1			A 32-bit Value passed by the user
   517 @param a2			A 32-bit Value passed by the user
   518 
   519 @return	KErrNone	If successful, otherwise one of the system wide error code
   520 	
   521 */	
   522 	{
   523 	TInt err = KErrNone;
   524 	
   525 	DATAPAGING_TEST
   526 		(
   527 		err = Kern::HalFunction(EHalGroupVM, EVMHalFlushCache, 0, 0);
   528 		if(err != KErrNone)
   529 			{
   530 			return err;
   531 			}
   532 		)
   533 
   534 	if(aReqNo == KMaxTInt)
   535 		{
   536 			CancelRequest((TInt)a1);
   537 			return err;
   538 		}
   539 	if(aReqNo < 0)
   540 		{
   541 		// DoRequest
   542 		TAny *array[2] = {0,0};
   543 		TRequestStatus * pStat = (TRequestStatus*)a1;
   544 		kumemget32(&array[0], a2, 2*sizeof(TAny*));
   545 		err = DoRequest(~aReqNo, pStat, array[0], array[1]);
   546 		if(err!= KErrNone)
   547 			Kern::RequestComplete(pStat, err);
   548 		
   549 		}
   550 	else
   551 		{
   552 		// DoControl
   553 		err = DoControl(aReqNo, a1, a2);
   554 		}
   555 		return err;
   556 	}
   557 
   558 
   559 TInt DPipeChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   560 /**
   561 Processes Synchronous 'control' requests. This function is called to service
   562 any synchronous calls through the  user side RPipe handle. 
   563 
   564 @param aFunction		A number identifying the  message type
   565 @param a1				A 32-bit Value passed by the user
   566 @param a2				A 32-bit Value passed by the user
   567 
   568 @return KErrNone 		If the call is successful, otherwise one of the other
   569 						system wide error
   570 */
   571 	{
   572 	TInt aSize = 0;
   573 	TInt aId = 0;
   574 	
   575     switch(aFunction)
   576 		{
   577 		case RPipe::EDefineNamedPipe:
   578 			return PipeCreate(a1, a2);
   579 			
   580 		case RPipe::EOpenToReadNamedPipe:
   581 			return PipeOpen((const TDesC*)a1, RPipe::EReadChannel);
   582 		
   583 		case RPipe::EOpenToWriteNamedPipe:
   584 			return PipeOpen((const TDesC*)a1, RPipe::EWriteChannel);
   585 		
   586 		case RPipe::EOpenToWriteButFailOnNoReaderNamedPipe:
   587 			return OpenOnReader((const TDesC*)a1);
   588 		
   589 		case RPipe::EDestroyNamedPipe:
   590 			return PipeDestroy((const TDesC*)a1);	
   591 		
   592 		case RPipe::ECreateUnNamedPipe:
   593 			kumemget((TAny*)&aSize, a1, sizeof(TInt));
   594 			return PipeCreate( aSize);
   595 		
   596 		case RPipe::EOpenUnNamedPipe:
   597 			kumemget((TAny*)&aId, a1, sizeof(TInt));
   598 			return PipeOpen(aId);
   599 		
   600 		case RPipe::ERead:
   601 			kumemget((TAny*)&aSize, a2, sizeof(TInt));
   602 			return Read (a1, aSize);
   603 		
   604 		case RPipe::EWrite:
   605 			kumemget((TAny*)&aSize, a2, sizeof(TInt));
   606 			return Write (a1, aSize);
   607 				
   608 		case RPipe::ESize:
   609 			 return Size();
   610 		
   611 		case RPipe::EDataAvailableCount:
   612 			 {		
   613 			 TAutoWait<DMutex> autoMutex(iData->Mutex());
   614 			 return iData->AvailableDataCount();
   615 			 }
   616 			 
   617 		case RPipe::EFlushPipe:
   618 			 Flush();
   619 			 return KErrNone;
   620 			 
   621 		case RPipe::EGetPipeInfo:
   622 			 umemput(a1,(TAny*)&iChannelType, sizeof(TInt));
   623 			 aSize = Size();
   624 			 umemput(a2,(TAny*)&aSize, sizeof(TInt));
   625 			 return KErrNone;
   626 			
   627 	
   628 		default:
   629 			 return KErrNotSupported;
   630 			 
   631 		}
   632 
   633 	}
   634 
   635 
   636 TInt DPipeChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   637 /**
   638 Processes Asynchronous requests This function is called to service
   639 any asynchronous calls through the  user side RPipe handle. 
   640 
   641 @param aFunction		A number identifying the  message type
   642 @param aStatus 			Status request to be completed. 
   643 @param a1				A 32-bit Value passed by the user
   644 @param a2				A 32-bit Value passed by the user
   645 
   646 @return  KErrNone 		If the call is successful, else one of the system wide error
   647 */
   648 	{
   649 	(void)a2;
   650 	TInt aSize = 0;
   651 	TInt aChoice = 0;
   652 
   653     switch(aReqNo)
   654 		{
   655 		case RPipe::EDataAvailable:
   656 				return NotifyDataAvailable(aStatus, ETrue);	
   657 			
   658 		case RPipe::ESpaceAvailable:
   659 				umemget(&aSize, a1, sizeof(aSize));
   660 				return NotifySpaceAvailable(aSize, aStatus, ETrue);
   661 		
   662 		case RPipe::EWaitNotification:
   663 				// a2 == RPipe::EWaitForReader is for WaitForReader.
   664 				// a2 == RPipe::EWaitForWriter is for WaitForWriter.
   665 				umemget(&aChoice, a2, sizeof(aChoice));
   666 				return WaitNotification(aStatus, a1, aChoice);
   667 				
   668 		case RPipe::EReadBlocking:
   669 			{
   670 				return NotifyDataAvailable(aStatus, EFalse);
   671 			}
   672 				
   673 		case RPipe::EWriteBlocking:
   674 			{
   675 				umemget(&aSize, a1, sizeof(aSize));
   676 				return NotifySpaceAvailable(aSize, aStatus, EFalse);
   677 			}
   678 		default:
   679 				return KErrNotSupported;
   680 		}
   681 	}
   682 
   683 
   684 		
   685 TInt DPipeChannel::PipeCreate(TAny* a1,  TAny* a2)
   686 /**
   687 Creates named pipes with the specified name  and size. It calls Pipe Device 
   688 object to create the pipe and obtained the pointer to it. The pointer is then
   689 stored in its iData member data.
   690 @param a1		Pointer to TPipeInfo class
   691 
   692 @param a2		Pointer to TSecurityPolicy class
   693 
   694 @return KErrNone	If successful, otherwise one of the other system wide error code.
   695 */
   696 	{
   697 	if(iData)
   698 		{
   699 		//this channel already has a pipe
   700 		return KErrInUse;
   701 		}
   702 
   703 	// The following code safely gets the 3 arguments into kernel memory.
   704 	// (The user side API is badly designed,)
   705 	RPipe::TPipeInfo& info = (*(RPipe::TPipeInfoBuf*)a1)(); // reference to user side 'TPipeInfo'
   706 	TInt size;
   707 	kumemget(&size,&info.isize,sizeof(size));
   708 	TKName name;
   709 	Kern::KUDesGet(name,info.iName);
   710 	TSecurityPolicy* securityPolicy = 0;
   711 	TSecurityPolicy securityPolicyBuffer;
   712 	if(a2)
   713 		{
   714 		kumemget(&securityPolicyBuffer,a2,sizeof(securityPolicyBuffer));
   715 		securityPolicy = &securityPolicyBuffer;
   716 		}
   717 
   718 	DPipe * pipe = NULL;
   719 	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   720 
   721 	//must wait on device since after creation
   722 	//the pipe becomes globably findable 
   723 	//and destroyable
   724 	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   725 
   726 	TInt err = ((DPipeDevice*)iDevice)->CreatePipe(name, size, pipe, securityPolicy);
   727 	if(err!= KErrNone)
   728 		{
   729 		return err;
   730 		}
   731 
   732 	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   733 	pipe->SetReadEnd(this);
   734 	iData = pipe;
   735 	iChannelType = RPipe::EReadChannel;
   736 	return err;
   737 	}
   738 
   739 
   740 TInt DPipeChannel::PipeCreate(const TInt aSize)
   741 /**
   742 Creates unnamed pipes with the specified Id and size. It calls Pipe Device 
   743 object to create the pipe and obtained the pointer to it. The pointer is then
   744 stored in its iData member data. Marked the current channel as read end.  
   745 
   746 @param aSize		Size of the unnamed pipe to be created.
   747 
   748 @return	Handle ID if successful, otherwise one of the other system wide error code.
   749 */
   750 	{
   751 	if(iData)
   752 		{
   753 		//this channel already has a pipe
   754 		return KErrInUse;
   755 		}
   756 
   757 	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   758 
   759 	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   760 
   761 	DPipe* pipe = device.CreatePipe(aSize);
   762 	if(pipe == NULL)
   763 		{
   764 		return KErrNoMemory;
   765 		}
   766 
   767 	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   768 
   769 	pipe->SetReadEnd(this);
   770 	iData = pipe;
   771 	iChannelType = RPipe::EReadChannel;
   772 
   773 	return iData->OpenId();
   774 	}
   775 
   776 
   777 TInt DPipeChannel::OpenOnReader(const TDesC* aName)
   778 /**
   779 Opens a named pipe identified by the name parameter. It calls Pipe Device object
   780 to open the Pipe identified by the name and obtained the pointer to the pipe. The
   781 pointer is them stored in its iData member data. Marked the current channel as write
   782 end. 
   783 @param 	aName		The name of the pipe to be opened.
   784 
   785 @return KErrNone	If successful, otherwise one of the other system wide error code. 
   786 */
   787 	{
   788 	if(iData)
   789 		{
   790 		//this channel already has a pipe
   791 		return KErrInUse;
   792 		}
   793 
   794 	TKName PName;
   795 	Kern::KUDesGet(PName, *aName);
   796 
   797 	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   798 
   799 	//need to hold the device mutex to
   800 	//prevent the pipe getting deleted before we can call
   801 	//SetWriteEnd
   802 	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   803 	DPipe* pipe = device.FindNamedPipe(&PName);
   804 
   805 	if(pipe == NULL)
   806 		{
   807 		return KErrNotFound;
   808 		}
   809 
   810 	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   811 	if (!pipe->IsReadEndOpened())
   812 		{
   813 		return KErrNotReady;
   814 		}
   815 	
   816 	iData = pipe;
   817 
   818 	if(!CheckCap())
   819 		{
   820 		iData = NULL;
   821 		return KErrPermissionDenied;
   822 		}
   823 	
   824 	if(pipe->IsWriteEndOpened())
   825 		{
   826 		iData = NULL;
   827 		return KErrInUse;
   828 		}	
   829 
   830 	iData->SetWriteEnd(this);
   831 	iChannelType = RPipe::EWriteChannel;
   832 	return KErrNone;
   833 	}
   834 
   835 
   836 TInt DPipeChannel::PipeDestroy(const TDesC* aName)
   837 /**
   838 Destroys the named pipe.
   839 @param	aName 			Name of the Kernel pipe to be destroyed.
   840 
   841 @return KErrNone		If the pipe is successfully destroyed, otherwise one of the
   842 						other system wide error codes
   843 */
   844 	{	
   845 	TKName PName;
   846 	Kern::KUDesGet(PName, *aName);
   847 	return ((DPipeDevice*)iDevice)->Destroy(&PName);
   848 	}
   849 
   850 TInt DPipeChannel::PipeOpen(const TInt aId)
   851 /**
   852 Opens a unnamed pipe identified by the specified id. It calls Pipe Device object
   853 to open a unnamed pipe identified by the specified id and obtain the pointer to the
   854 pipe. The pipe reference is then stored in its iData member data and marked the 
   855 current channel as write end. 
   856 
   857 @param 	aId 		Id of the unnamed pipe to be opened.
   858 
   859 @return KErrNone	If successful, otherwise one of the system wide error code. 
   860 */
   861 	{
   862 	if(iData)
   863 		{
   864 		//this channel already has a pipe
   865 		return KErrInUse;
   866 		}
   867 
   868 	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   869 	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   870 
   871 	DPipe* pipe = device.FindUnnamedPipe(aId);
   872 	if(pipe == NULL)
   873 		{
   874 		return KErrNotFound;
   875 		}
   876 
   877 	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   878 	if (pipe->IsWriteEndOpened() )
   879 		{
   880 		return KErrInUse;
   881 		}
   882 
   883 	pipe->SetWriteEnd(this);
   884 
   885 	iChannelType = RPipe::EWriteChannel;
   886 	iData = pipe;
   887 	
   888 	return KErrNone;
   889 	}
   890 
   891 
   892 TInt DPipeChannel::PipeOpen(const TDesC* aName, RPipe::TChannelType aType)
   893 /**
   894 This function will be called under DoControl();
   895 Attempts to open the pipe for reading (iReadEnd) or writing (iWriteEnd)
   896 @param  aName 		Name of the pipe to be opened
   897 
   898 @param  aType	 	Type of operation to be performed.
   899 
   900 @return KErrNone	Pipe successfully created, otherwise one of the other system wide
   901 					error code
   902 */ 
   903 	{
   904 	if(iData)
   905 		{
   906 		//this channel already has a pipe
   907 		return KErrInUse;
   908 		}
   909 
   910 	TKName PName;
   911 	Kern::KUDesGet(PName, *aName);
   912 	
   913 	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   914 
   915 	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   916 
   917 	DPipe* pipe = device.FindNamedPipe(&PName);
   918 	if(pipe == NULL)
   919 		{
   920 		return KErrNotFound;
   921 		}
   922 
   923 
   924 	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   925 	iData = pipe;
   926 	//! Check capabilitity if applicalble
   927 	if(!CheckCap())
   928 		{
   929 		iData = NULL;
   930 		return KErrPermissionDenied;
   931 		}
   932 
   933 	// Check if the pipe is already opened.
   934 	if(aType == RPipe::EReadChannel)
   935 		{
   936 		if(iData->IsReadEndOpened())
   937 			{
   938 			iData = NULL;
   939 			return KErrInUse;
   940 			}
   941 		iData->SetReadEnd(this);
   942 		}
   943 	else
   944 		{
   945 		if(iData->IsWriteEndOpened())
   946 			{
   947 			iData = NULL;
   948 			return KErrInUse;
   949 			}
   950 		iData->SetWriteEnd(this);	
   951 		}
   952 
   953 	iChannelType = aType;
   954 
   955 	return KErrNone;	
   956 	}
   957 
   958 
   959 
   960 TBool DPipeChannel::CheckCap()
   961 /**
   962 Check if Security policy is installed, if so, checks if the current thread
   963 has required capabilities
   964 
   965 @param 	None
   966 
   967 @return TBool  ETrue if The current thread has required capabilities and also if
   968 			  no capabilities is installed, otherwise EFlase.
   969 			  
   970 */
   971 	{
   972 	//iData->GetCap is always true
   973 	if(iData->GetCap())
   974 		return iData->GetCap()->CheckPolicy(&Kern::CurrentThread());
   975 	else 
   976 		return ETrue;
   977 	}
   978 
   979 
   980 
   981 TInt DPipeChannel::Read (TAny* aBuff, TInt aSize)
   982 /**
   983 Synchronous, non-blocking read operation. If the pipe is empty it will 
   984 return immediately with KErrUnderflow. A successful DPipe::Read() operation 
   985 will free up more space in the pipe. If a request status object has been registered
   986 for Space Available notification, it will complete. Note that there is no 
   987 guarantee that the amount of space freed up in the pipe will be sufficient 
   988 for the next DPipe::Write() operation.
   989 
   990 @param	aBuff			Buffer from which data need to be read
   991 
   992 @param	aSize			Size of the data to be read
   993 
   994 @return:>0				Amount of data read  in octets.
   995 		 KErrArgument   Invalid Length	Amount of data to be read is invalid (e.g. negative) 
   996 		 KErrNotReady	If the write end is closed,
   997 		  				otherwise one of the other system wide error code  		
   998 */
   999 	{
  1000 	
  1001 	if( iChannelType != RPipe::EReadChannel)
  1002 		return KErrAccessDenied;
  1003 	
  1004 
  1005 	TAutoWait<DMutex> outerAutoMutex(*iData->iReadMutex);
  1006 	TAutoWait<DMutex> innerAutoMutex(iData->Mutex());
  1007 	//iData->Wait();
  1008 	if(!iData->IsWriteEndOpened() && iData->IsBufferEmpty())
  1009 		{
  1010 		//it is ok to read from a broken pipe provided there is data in it
  1011 		return KErrNotReady;	
  1012 		}
  1013 
  1014 	return iData->Read(aBuff, aSize);
  1015 	}
  1016 
  1017 
  1018 TInt DPipeChannel::Write (TAny* aBuff, TInt aSize)
  1019 /**
  1020 Synchronous, non-blocking write operation. If the pipe is full it will 
  1021 return immediately with KErrOverflow. A successful DPipe::Write() operation will
  1022 return amount of data written to the pipe.If a request status object has been registered
  1023 for Data Available notification, it will complete.
  1024 
  1025 
  1026 @param aBuf				Buffer from which data need to be written to the pipe.
  1027 				
  1028 @param aSize			Amount of data to be written to the pipe.
  1029 	 
  1030 @return >0				Amount of data written to the pipe, in octets.
  1031 		KErrOverflow	The pipe is full no data is written.
  1032 		KErrArgument	if the amount of data to be written in invalid
  1033 		KErrNotReady	if the read end is not opened.
  1034 						otherwise one of the other system wide error code
  1035 */
  1036 	{
  1037 	
  1038 	if(iChannelType!= RPipe::EWriteChannel)
  1039 		return KErrAccessDenied;
  1040 		
  1041 	TAutoWait<DMutex> outerAutoMutex(*iData->iWriteMutex);
  1042 	TAutoWait<DMutex> innerAutoMutex(iData->Mutex());
  1043 	
  1044 	if(!(iData->IsReadEndOpened()))
  1045 		{
  1046 		return KErrNotReady;
  1047 		}
  1048 
  1049 	return iData->Write(aBuff, aSize);	
  1050 	}
  1051 
  1052 
  1053 
  1054 TInt DPipeChannel::CloseHandle()
  1055 /**
  1056 Attempts to close the pipe for reading  or writing .
  1057 
  1058 @param	None
  1059 
  1060 @return KErrNone				Success.
  1061 		KErrCouldNotDisconnect	The pipe is already closed for that operation.
  1062 
  1063 */
  1064 	{
  1065 	if(iData==NULL)
  1066 		{
  1067 		return KErrNone;
  1068 		}
  1069 
  1070 	__KTRACE_OPT(KPIPE, Kern::Printf("DPipeChannel::CloseHandle ID=%d, ChannelType=%d", iData->OpenId(), iChannelType)); 
  1071 	
  1072 	NKern::ThreadEnterCS();
  1073 	iData->Wait();
  1074 	TInt err = KErrNone;
  1075 	if(iChannelType == RPipe::EReadChannel)
  1076 	 	{
  1077 	 	CancelRequest(RPipe::EDataAvailable);
  1078 	 	err = iData->CloseReadEnd();
  1079 	 	}
  1080 	else if(iChannelType == RPipe::EWriteChannel)
  1081 	 	{
  1082 	 	CancelRequest(RPipe::ESpaceAvailable);
  1083 	 	err = iData->CloseWriteEnd();
  1084 	 	}
  1085 	else
  1086 	 	{
  1087 		FAULT(); //iChannelType should be set correctly if iData was non-null
  1088 	 	}
  1089 	// If we had a pointer to the pipe but it had no back pointer
  1090 	// to us something has gone wrong.
  1091 	__NK_ASSERT_DEBUG(err == KErrNone); 
  1092 
  1093 	const TInt pipeId=iData->OpenId();
  1094 	iData->Signal();
  1095 	iData = NULL;
  1096 
  1097 	// The return code from close would inform us if
  1098 	// the device had no record of the pipe.
  1099 	// However, for a named pipe there is no gurrantee that the pipe
  1100 	// hasn't been deleted once we close our end of the pipe and
  1101 	// Signal.
  1102 	static_cast<DPipeDevice*>(iDevice)->Close(pipeId);
  1103 
  1104 	NKern::ThreadLeaveCS();
  1105 	 
  1106 	return err;
  1107 	}
  1108 
  1109 
  1110 
  1111 TInt DPipeChannel::NotifySpaceAvailable ( TInt aSize,TRequestStatus* aStat, TBool aAllowDisconnected)
  1112 /**
  1113 Registers the request status object to be completed when space becomes 
  1114 available in the pipe. 
  1115 
  1116 @param 	aSize			The size for which the user has requested for notification
  1117 
  1118 @param	aStat			Status request to be registered
  1119 @param	aAllowDisconnected If false then confirm that the pipe has a reader
  1120 
  1121 @return KErrNone		 Success in registering the request
  1122 		KErrAccessDenied If the correct end is not used to register the request
  1123 		KErrInUse		 A notifier of this type has already been registered.
  1124 						 otherwise one of the other system wide error code.
  1125 		KErrNotReady	The pipe has no reader
  1126 */
  1127 	{
  1128 	
  1129 	//! Check if correct end is used
  1130 	if(iChannelType!= RPipe::EWriteChannel)
  1131 		{
  1132 		return KErrAccessDenied;
  1133 		}
  1134 	
  1135 	TAutoWait<DMutex> autoMutex(iData->Mutex());
  1136 	//Check if there is already a pending Space Available request.
  1137 	if(iClientRequest->StatusPtr())
  1138 		{
  1139 		return KErrInUse;
  1140 		}
  1141 	else
  1142 		{
  1143 		if(!aAllowDisconnected && !(iData->IsReadEndOpened()) )
  1144 			return KErrNotReady;
  1145 
  1146 		TInt r = iClientRequest->SetStatus(aStat);
  1147 		__NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
  1148 		DThread* const currThread = &Kern::CurrentThread();
  1149 
  1150 		if((iData->RegisterSpaceAvailableNotification(aSize))==KErrCompletion)
  1151 			{
  1152 			Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
  1153 			}
  1154 		else
  1155 			{
  1156 			iRequestThread = currThread;
  1157 			// Open a reference on client thread so its control block can't disappear until
  1158 			// this channel has finished with it.
  1159 			iRequestThread->Open();   
  1160 			iRequestType = RPipe::ESpaceAvailable;
  1161 			}
  1162 		}
  1163 	return KErrNone;
  1164 	}
  1165 
  1166 
  1167 TInt DPipeChannel::NotifyDataAvailable (TRequestStatus* aStat, TBool aAllowDisconnected)
  1168 /**
  1169 Registers the request status object to be completed when data becomes 
  1170 available in the pipe. 
  1171 
  1172 @param	aStat			Status request to be registered
  1173 @param	aAllowDisconnected  If false then fail if the pipe is empty with no writer.
  1174 
  1175 @return KErrNone		 Success in registering the request
  1176 		KErrAccessDenied If the correct end is not used to register the request 
  1177 		KErrInUse		 A notifier of this type has already been registered.
  1178 						 otherwise one of the other system wide error code.
  1179 		KErrNotReady	 The pipe was empty and had no writer
  1180 */
  1181 	{	
  1182 
  1183 	//! Check if correct end is used
  1184 	if(iChannelType!= RPipe::EReadChannel)
  1185 		{
  1186 		return KErrAccessDenied;
  1187 		}
  1188 
  1189 	// Check if there is already a pending Data Available request.	
  1190 	TAutoWait<DMutex> autoMutex(iData->Mutex() );
  1191 	if(iClientRequest->StatusPtr())
  1192 		{
  1193 		return KErrInUse;
  1194 		}
  1195 	else
  1196 		{
  1197 		if(!aAllowDisconnected)
  1198 			{
  1199 			if(iData->IsBufferEmpty() && (!iData->IsWriteEndOpened()))
  1200 				return KErrNotReady;
  1201 			}
  1202 		
  1203 		TInt r = iClientRequest->SetStatus(aStat);
  1204 		__NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
  1205 		DThread* const currThread = &Kern::CurrentThread();
  1206 
  1207 		if((iData->RegisterDataAvailableNotification()) == KErrCompletion)
  1208 			{
  1209 			Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
  1210 			}
  1211 		else
  1212 			{
  1213 			iRequestThread = currThread;
  1214 			// Open a reference on client thread so its control block can't disappear until
  1215 			// this channel has finished with it.
  1216 			iRequestThread->Open();   
  1217 			iRequestType = RPipe::EDataAvailable;
  1218 			}
  1219 		}
  1220 	return  KErrNone;;
  1221 	}
  1222 
  1223 
  1224 TInt DPipeChannel::WaitNotification(TRequestStatus* aStat, TAny* aName, TInt aChoice)
  1225 /**
  1226 Registers the request status object to be completed when other end of the pipe
  1227 is opened for reading (or writing).This method completes immediately if the other end of the
  1228 pipe is already opened.
  1229 
  1230 
  1231 @param	aName		Pointer to the a name passed as void pointer
  1232 
  1233 @param	aStat		Status request to be registered
  1234 
  1235 @param	aChoice		EWaitForReader,wait notification for Read end Opened.
  1236 					EWaitForWriter,wait notification for Write end Opened.
  1237 
  1238 @return KErrNone		 Success in registering the request
  1239 		KErrInUse		 A notifier of this type has already been registered.
  1240 		KErrAccessDenied If the correct end is not used to register the request 
  1241 						 otherwise one of the other system wide error code
  1242 
  1243 */
  1244 	{
  1245 	//! Check if correct end is used
  1246 	if(((aChoice == RPipe::EWaitForReader) && (iChannelType!= RPipe::EWriteChannel))
  1247 		|| ((aChoice == RPipe::EWaitForWriter) && (iChannelType!= RPipe::EReadChannel)))
  1248 		{
  1249 		return KErrAccessDenied;
  1250 		}
  1251 
  1252 	TKName PName;
  1253 	Kern::KUDesGet(PName, *(TDesC*)aName);
  1254 
  1255 	TAutoWait<DMutex> autoMutex(iData->Mutex());
  1256 	if(iData->MatchName(&PName)== EFalse)
  1257 		{
  1258 		return KErrNotFound;
  1259 		}
  1260 	// Check if there is already a pending request.
  1261 	else if(iClientRequest->StatusPtr())
  1262 		{
  1263 		return KErrInUse;
  1264 		}
  1265 	else
  1266 		{
  1267 		TInt r = iClientRequest->SetStatus(aStat);
  1268 		__NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
  1269 		DThread* const currThread = &Kern::CurrentThread();
  1270 
  1271 		//register the request.
  1272 		if((iData->RegisterWaitNotification((TInt )aChoice))== KErrCompletion)
  1273 			{
  1274 			Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
  1275 			}
  1276 		else
  1277 			{
  1278 			iRequestThread = currThread;
  1279 			// Open a reference on client thread so its control block can't disappear until
  1280 			// this channel has finished with it.
  1281 			iRequestThread->Open();   
  1282 			iRequestType = RPipe::EWaitNotification;
  1283 			}
  1284 		}
  1285 	return KErrNone;
  1286 	}
  1287 
  1288 
  1289 /**
  1290 For a given request return true if the notification
  1291 we are cancelling is outstanding. If not, or
  1292 if the supplied request is not a valid cancllation
  1293 return false
  1294 */
  1295 TBool DPipeChannel::ValidCancellation(TInt aReqType)
  1296 {
  1297 	switch(aReqType)
  1298 	{
  1299 	case RPipe::ECancelDataAvailable:
  1300 		return (iRequestType==RPipe::EDataAvailable);
  1301 	case RPipe::ECancelSpaceAvailable:
  1302 		return (iRequestType==RPipe::ESpaceAvailable);
  1303 	case RPipe::ECancelWaitNotification:
  1304 		return (iRequestType==RPipe::EWaitNotification);
  1305 	default:
  1306 		return EFalse;
  1307 	}
  1308 }
  1309 
  1310 void DPipeChannel::CancelRequest ( TInt aReqType)
  1311 /**
  1312 Cancels an outstanding space available notifier request.
  1313 
  1314 @param 	aReqType A number identifying the  message type
  1315 
  1316 @return  None
  1317 */
  1318 {
  1319 	TAutoWait<DMutex> autoMutex(iData->Mutex() );
  1320 	if(iClientRequest->StatusPtr() && ValidCancellation(aReqType))
  1321 		{
  1322 		switch(aReqType)
  1323 			{
  1324 			case RPipe::ECancelDataAvailable:
  1325 				iData->CancelDataAvailable();			
  1326 				break;
  1327 			
  1328 			case RPipe::ECancelSpaceAvailable:
  1329 				iData->CancelSpaceAvailable();
  1330 				break;
  1331 		
  1332 			case RPipe::ECancelWaitNotification:
  1333 				iData->CancelWaitNotifier();
  1334 				break;
  1335 	
  1336 			default:
  1337 				FAULT();
  1338 			}
  1339 		Kern::QueueRequestComplete(iRequestThread, iClientRequest, KErrCancel);
  1340 		// Close our reference on the client thread
  1341 		Kern::SafeClose((DObject*&)iRequestThread,NULL);
  1342 		iRequestThread = NULL;
  1343 		}
  1344 	return;	
  1345 	}
  1346 
  1347 
  1348 TInt DPipeChannel::Size()
  1349 /**
  1350 Returns the size of the Pipe's buffer
  1351 
  1352 @param None
  1353 
  1354 @return TInt	Return the size of the pipe, otherwise one of the other system wide 
  1355 				error code.
  1356 */	{
  1357 	if(!iData)
  1358 		return KErrNotReady;
  1359 	else
  1360 		return iData->Size();
  1361 	}
  1362 
  1363     
  1364 void DPipeChannel::Flush()
  1365 /*
  1366 Flush the content of the pipe
  1367 
  1368 @param	None
  1369 @pre   Must be in a critical section.
  1370 @return	None
  1371 
  1372 */	{
  1373 	//The flush is, in effect, a read where the data is ignored
  1374 	TAutoWait<DMutex> autoMutex(*iData->iReadMutex);
  1375 
  1376 	iData->Wait();
  1377 	iData->FlushPipe();
  1378 	iData->Signal();
  1379 	}
  1380 	
  1381 
  1382 // Called from the DPipe  
  1383 	
  1384 void DPipeChannel::DoRequestCallback()
  1385 /**
  1386 It is called from the DPipe to complete the Outstanding request
  1387 
  1388 @param None
  1389 
  1390 @return None
  1391 */
  1392 	{
  1393 	__ASSERT_MUTEX(&iData->Mutex());
  1394 	__NK_ASSERT_DEBUG(iRequestThread);
  1395 	Kern::QueueRequestComplete(iRequestThread, iClientRequest, KErrNone);
  1396 	Kern::SafeClose((DObject*&)iRequestThread,NULL);
  1397 	iRequestThread=NULL;
  1398 	}
  1399 
  1400 
  1401 
  1402 // DPipe the Kernel side pipe representing class
  1403 
  1404 DPipe::~DPipe()
  1405 /**
  1406 Destructor
  1407 */
  1408 	{
  1409 	delete iBuffer;
  1410 	if (iPipeMutex)
  1411 		iPipeMutex->Close(NULL);
  1412 	if (iReadMutex)
  1413 		iReadMutex->Close(NULL);
  1414 	if(iWriteMutex)
  1415 		iWriteMutex->Close(NULL);
  1416 	}
  1417 	
  1418 
  1419 // Creates a Named pipe
  1420 DPipe* DPipe::CreatePipe(const TDesC& aName, TInt aSize, TAny *aPolicy)
  1421 /**
  1422 Static method to Create a Named pipe. 
  1423 @param	aName		Reference to the Name to be set to the current named pipe.
  1424 @param	aSize		Size of the Pipe.
  1425 @param TAny			Pointer to TSecurityPolicy passed as void pointer
  1426 
  1427 @return DPipe*  	Reference to DPipe* instance if successful, otherwise NULL
  1428 */
  1429 	{
  1430 
  1431 	DPipe* tmp = new DPipe;
  1432 	if (!tmp)
  1433 		{
  1434 		return NULL;
  1435 		}
  1436 	if(tmp->ConstructPipe(aName, aSize, aPolicy)!= KErrNone)
  1437 		{
  1438 		delete tmp;
  1439 		return NULL;
  1440 		}
  1441 	return tmp;
  1442 	}
  1443 	
  1444 	
  1445 TInt DPipe::ConstructPipe(const TDesC& aName, TInt aSize,TAny* aPolicy)
  1446 /**
  1447 Second phase constructor
  1448 
  1449 @param	aName		The name of the pipe to be created
  1450 @param	aSize		The size of the pipe to be created
  1451 @param TAny			Pointer to TSecurityPolicy passed as void pointer
  1452 
  1453 @return KErrNone	If successful, otherwise one of the other system wide error code
  1454 */
  1455 	{
  1456 	// check the size parameter.
  1457 	if(aPolicy)
  1458 		{
  1459 		
  1460 		memcpy(&iPolicy,aPolicy,sizeof(TSecurityPolicy));
  1461 		
  1462 		}
  1463 	else
  1464 		{
  1465 		TSecurityPolicy apolicy(ECapability_None);
  1466 		memcpy(&iPolicy,&apolicy,sizeof(TSecurityPolicy));
  1467 		}
  1468 
  1469 	if(aName.Length() != 0)
  1470 		{
  1471 		iName.Copy(aName);	
  1472 		}
  1473 		
  1474 	iBuffer = static_cast<TUint8*>(Kern::AllocZ(aSize));
  1475 	if(!iBuffer)
  1476 		return KErrNoMemory;
  1477 		
  1478 	// Initialisation
  1479 	_LIT(KMutexName,"PipeMutex");
  1480 	TInt err = Kern::MutexCreate(iPipeMutex, KMutexName, KMutexOrdGeneral0);
  1481 	if (err)
  1482 		{
  1483 		return err;
  1484 		}
  1485 	_LIT(KReadMutex,"ReadMutex");
  1486 	err = Kern::MutexCreate(iReadMutex, KReadMutex, KMutexOrdGeneral1);
  1487 	if (err)
  1488 		{
  1489 		return err;
  1490 		}
  1491 
  1492 	_LIT(KWriteMutex,"WriteMutex");
  1493 	err = Kern::MutexCreate(iWriteMutex, KWriteMutex, KMutexOrdGeneral1);
  1494 	if (err)
  1495 		{
  1496 		return err;
  1497 		}
  1498 
  1499 	iSize = aSize;
  1500 	iWritePointer = iReadPointer = 0;
  1501 	iFull = EFalse;	
  1502 	return KErrNone;		
  1503 	}	
  1504 
  1505 
  1506 TInt DPipe::OpenId()
  1507 /**
  1508 Returns the id of the Pipe
  1509 
  1510 @param	None
  1511 
  1512 @return iID			 ID of the pipe
  1513 */
  1514 	{
  1515 	//could be const
  1516 	return iID;
  1517 	}
  1518 
  1519 
  1520 void DPipe::SetId(TInt aId)
  1521 /**
  1522 Set the id of the Pipe
  1523 
  1524 @param 	aId		 	The id to be set 
  1525 
  1526 @return None
  1527 */
  1528 	{
  1529 	//this is only called by the pipe device
  1530 	//it could also be set at construction time
  1531 	iID = aId;	
  1532 	}
  1533 
  1534 
  1535 TBool DPipe::IsPipeClosed()
  1536 /**
  1537 Check if the Pipe is Closed.
  1538 @param	None
  1539 @return TBool		ETure if Successful, otherwise EFalse;
  1540 */
  1541 	{
  1542 	__ASSERT_MUTEX(iPipeMutex);
  1543 
  1544 	return !(iReadChannel || iWriteChannel);
  1545 	}
  1546 
  1547 
  1548 TBool DPipe::MatchName(const TDesC8* aName)
  1549 /**
  1550 Check if the current instance of DPipe Name is matching with aName parameter
  1551 
  1552 @param	aName		Name to be checked with the current DPipe's name.
  1553 
  1554 @return TBool	  	ETrue if match found, otherwise EFalse
  1555 */
  1556 	{
  1557 	//name could be const
  1558  	return (iName.Compare(*aName) == 0);
  1559 	}
  1560 	
  1561 
  1562 TBool DPipe::MatchId(const TInt aId)
  1563 /**
  1564 Checks if the current instance of DPipe is matching with the aId parameter
  1565 
  1566 @param	aId	 		ID to be checked with the current DPipe's id
  1567 
  1568 @return TBool		ETure if match found , otherwise EFalse;
  1569 */
  1570 	{
  1571 	return (iID == aId);
  1572 	}
  1573 
  1574 
  1575 TBool DPipe::IsBufferEmpty()
  1576 /**
  1577 Checks if the Buffer is Empty
  1578 
  1579 @param   None
  1580 @return ETrue if buffer is empty
  1581 */
  1582 	{
  1583 	return (AvailableDataCount()==0);
  1584 	}
  1585 
  1586 
  1587 TInt DPipe::Write(TAny* aBuf, TInt aSize)
  1588 /**
  1589 Synchronous, non-blocking write operation. If the pipe is full it will 
  1590 return immediately with KErrOverflow. A successful DPipe::Write() operation will
  1591 return amount of data written to the pipe.If a request status object has been registered
  1592 for Data Available notification, it will complete.
  1593 
  1594 @param	aBuf		Buffer from which data need to be written to the pipe.
  1595 @param	aSize		Amount of data to be written to the pipe.
  1596 	 
  1597 @return >0			 Amount of data written to the pipe, in octets.
  1598 		KErrNone	 No data written to the pipe.
  1599 		KErrOverflow Pipe is full, cannot write any more data. 
  1600 		KErrArgument If the amount of data to be written is invalid.
  1601 					 Otherwise one of the other system wide error code
  1602 
  1603 @pre iPipeMutex held
  1604 @pre iWriteMutex held
  1605 
  1606 @note Write enters and exists with the pipe mutex held - but releases and reaquires internally
  1607 */
  1608 	{
  1609 	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::Write(aBuf=0x%08x, aSize=%d)", aBuf, aSize));
  1610 	
  1611 	__ASSERT_MUTEX(iPipeMutex);
  1612 	__ASSERT_MUTEX(iWriteMutex);
  1613 	// Check for the Invalid  Length
  1614 	if(aSize < 0)
  1615 		{
  1616 		return KErrArgument;
  1617 		}
  1618 
  1619 	if(aSize == 0)
  1620 		{
  1621 		return KErrNone;
  1622 		}
  1623 	
  1624 	//Since only one thread can be writing to the write end
  1625 	//of a pipe it is sufficient that AvailableDataCount
  1626 	//holds the pipe mutex. After it returns the 
  1627 	//available space may increase
  1628 	//but can not decrease
  1629 	const TInt spaceavailable = (iSize - AvailableDataCount());
  1630 	if (spaceavailable < aSize)
  1631 		{
  1632 		//Though the API may suggest otherwise - partial writes are not supported.
  1633 		return KErrOverflow;
  1634 		}
  1635 		
  1636 	//release mutex before IPC read
  1637 	Signal();
  1638 
  1639 	//First half
  1640 	const TDesC8*  pBuf = (const TDesC8*)aBuf;
  1641 
  1642 	const TInt distanceToEnd =  iSize - iWritePointer;
  1643 	const TInt firstHalf = Min(distanceToEnd, aSize);
  1644 	TPtr ptr(&iBuffer[iWritePointer], firstHalf);
  1645 
  1646 	DThread* const currThread = &Kern::CurrentThread();
  1647 	TInt r=Kern::ThreadDesRead(currThread, pBuf, ptr, 0, KChunkShiftBy0);
  1648 	if(r!=KErrNone)
  1649 		{
  1650 		Wait(); //we must exit with mutex held
  1651 		return r;
  1652 		}
  1653 
  1654 	//Second half
  1655 	const TInt secondHalf = aSize - firstHalf;
  1656 	__NK_ASSERT_DEBUG( secondHalf >= 0);
  1657 	if(secondHalf != 0)	
  1658 		{
  1659 		ptr.Set(&iBuffer[0], secondHalf, secondHalf);
  1660 
  1661 		r = Kern::ThreadDesRead(currThread, pBuf, ptr, firstHalf, KChunkShiftBy0);
  1662 		if(r!=KErrNone)
  1663 			{
  1664 			Wait(); //we must exit with mutex held
  1665 			return r;
  1666 			}
  1667 		}
  1668 	
  1669 	Wait(); //reaquire mutex for state update
  1670 	iWritePointer = (iWritePointer + aSize)% iSize;	
  1671 		
  1672 	if(iWritePointer == iReadPointer)
  1673 		{
  1674 		iFull = ETrue;
  1675 		}
  1676 		
  1677 	if(iDataAvailableRequest)
  1678 		{
  1679 		iReadChannel->DoRequestCallback();
  1680 		iDataAvailableRequest = EFalse;		
  1681 		}
  1682 
  1683 	return aSize;
  1684 	}
  1685 
  1686 
  1687 TInt DPipe::Read(TAny* aBuf, TInt aSize)
  1688 /**
  1689 Synchronous, non-blocking read operation. If the pipe is empty it will 
  1690 return immediately with KErrUnderflow. A successful DPipe::Read() operation 
  1691 will free up more space in the pipe. If a request status object has been registered
  1692 for Space Available notification, it will complete. Note that there is no 
  1693 guarantee that the amount of space freed up in the pipe will be sufficient 
  1694 for the next DPipe::Write() operation.
  1695 
  1696 @param	aBuff		Buffer to which data need to be written.
  1697 @param	aSize		Size of the data to be read from the pipe.
  1698 
  1699 @return	>0			 Amount of data read from the pipe, in octets.
  1700 		KErrNone	 The pipe is empty , no data was read from the pipe.
  1701 		KErrArgument If the amount of data to be read is invalid.
  1702 					 Otherwise one of the system wide error code
  1703 @pre iPipeMutex held
  1704 @pre iReadMutex held
  1705 
  1706 @note Read enters and exists with the pipe mutex held - but releases and reaquires internally
  1707 */
  1708 	{	
  1709 	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::Read(aBuf=0x%08x, aSize=%d)", aBuf, aSize));
  1710 	__ASSERT_MUTEX(iPipeMutex);
  1711 	__ASSERT_MUTEX(iReadMutex);
  1712 		
  1713 	if(aSize < 0)
  1714 		{
  1715 		return KErrArgument;
  1716 		}
  1717 	
  1718 	const TInt totalToRead = Min(AvailableDataCount(), aSize);
  1719 	
  1720 
  1721 	if(totalToRead == 0)
  1722 		return 0;
  1723 
  1724 	Signal();
  1725 
  1726 
  1727 	//! First half	
  1728 	const TInt distanceToEnd = iSize - iReadPointer;
  1729 	__NK_ASSERT_DEBUG(distanceToEnd>=0);
  1730 	const TInt firstHalf = Min(totalToRead, distanceToEnd);
  1731 
  1732 	TPtrC8 pipeBuffer(&iBuffer[iReadPointer], firstHalf);
  1733 	TDes8* userBuffer = (TDes8*)aBuf;
  1734 
  1735 	DThread* const currThread = &Kern::CurrentThread();
  1736 	TInt r = Kern::ThreadDesWrite(currThread, userBuffer, pipeBuffer, 0, KChunkShiftBy0, NULL); 
  1737 	if(r!=KErrNone)
  1738 		{
  1739 		Wait(); //we must exit with mutex held
  1740 		return r;
  1741 		}
  1742 	
  1743 	const TInt secondHalf=totalToRead-firstHalf;
  1744 	__NK_ASSERT_DEBUG(secondHalf>=0);
  1745 	if(secondHalf!=0)
  1746 		{
  1747 	    //! Second half
  1748 		pipeBuffer.Set(&iBuffer[0], secondHalf);
  1749 		r = Kern::ThreadDesWrite(currThread, userBuffer, pipeBuffer, firstHalf, KChunkShiftBy0, NULL);
  1750 		if(r!=KErrNone)
  1751 			{
  1752 			Wait(); //we must exit with mutex held
  1753 			return r;
  1754 			}
  1755 		}
  1756 	__NK_ASSERT_DEBUG(firstHalf+secondHalf==totalToRead);
  1757 
  1758 	Wait(); //Reaquire mutex for state update
  1759 
  1760 	iReadPointer = (iReadPointer + totalToRead)% iSize;
  1761 	iFull = EFalse;
  1762 	MaybeCompleteSpaceNotification();
  1763 		
  1764 	__ASSERT_MUTEX(iReadMutex);
  1765 	return totalToRead;			
  1766 	}
  1767 
  1768 TInt DPipe::AvailableDataCount()
  1769 /**
  1770 Returns the Data available in the pipe. 
  1771 
  1772 @param	None
  1773 
  1774 @return TInt  Amount of data available in the pipe
  1775 
  1776 */
  1777 	{
  1778 	__ASSERT_MUTEX(iPipeMutex);
  1779 	TInt size=-1;
  1780 	if ( iWritePointer > iReadPointer )
  1781 		{
  1782 		size = iWritePointer - iReadPointer;
  1783 		}
  1784 	else if ( iReadPointer > iWritePointer )
  1785 		{
  1786 		size = iSize - iReadPointer + iWritePointer;
  1787 		}
  1788 	else 
  1789 		{
  1790 		//iReadPointer == iWritePointer
  1791 		size = iFull ? iSize : 0;
  1792 		}
  1793 	return size;
  1794 	}
  1795 
  1796 TInt DPipe::RegisterSpaceAvailableNotification(TInt aSize)
  1797 /**
  1798 Registers the request status object to be completed when space becomes 
  1799 available in the pipe. 
  1800 
  1801 @param	aSize			The size for which the space availability be notified.
  1802 
  1803 @return KErrNone		Success.
  1804 	    KErrCompletion	The request is not registered as it completes immediately
  1805 	    				otherwise one of the system wide error code.
  1806 @pre   Mutex must be held.
  1807 @pre   Must be in a critical section.
  1808 */
  1809 	{
  1810 	__ASSERT_MUTEX(iPipeMutex);
  1811 	__NK_ASSERT_DEBUG(Rng(1, aSize, iSize));
  1812 
  1813 	// Check if Specified size is available.
  1814 	TInt err = KErrNone;
  1815 	if ((aSize <= (iSize - AvailableDataCount())))
  1816 		{
  1817 		iSpaceAvailableRequest = EFalse;
  1818 		err = KErrCompletion;
  1819 		}
  1820 	else
  1821 		{
  1822 		iSpaceAvailableSize  = aSize;
  1823 		iSpaceAvailableRequest = ETrue;	
  1824 		}
  1825     return err;
  1826 	}
  1827 
  1828 
  1829 TInt DPipe::RegisterDataAvailableNotification()
  1830 /**
  1831 Registers the request status object to be completed when data becomes 
  1832 available in the pipe. 
  1833 
  1834 @param	None
  1835 
  1836 @return KErrNone	If successful, otherwise one of the other system wide
  1837 					error code.
  1838 @pre   Mutex must be held.
  1839 @pre   Must be in a critical section.
  1840 */
  1841 	{
  1842 	__ASSERT_MUTEX(iPipeMutex);
  1843 
  1844 	TInt err = KErrNone;
  1845 	// Check if Data is available.
  1846 	if(AvailableDataCount())
  1847 		{
  1848 		iDataAvailableRequest = EFalse;
  1849 		err = KErrCompletion;
  1850 		}
  1851 	else
  1852 		{
  1853 		iDataAvailableRequest = ETrue;
  1854 		}	
  1855  	return err;
  1856 	}
  1857 
  1858 
  1859 TInt DPipe::RegisterWaitNotification(TInt aChoice)	
  1860 /**
  1861 Registers the request status object to be completed when other end of the pipe
  1862 is opened for reading. This method completes immediately if the other end of the
  1863 pipe is already opened.
  1864 
  1865 @param 	None
  1866 
  1867 @return KErrNone	Successfully registered, otherwise one of the other system wide
  1868 					error code.
  1869 @pre Mutex must be held.
  1870 @pre Must be in a critical section.
  1871 */
  1872 	{
  1873 	__ASSERT_MUTEX(iPipeMutex);
  1874 
  1875 	TInt err = KErrNone;
  1876 	// Check if Read end is opened
  1877 	if (aChoice == RPipe::EWaitForReader) 
  1878 		{
  1879 		if(IsReadEndOpened())
  1880 			{	
  1881 			iWaitRequest = EFalse;
  1882 			err = KErrCompletion;
  1883 			}
  1884 		else
  1885 			{
  1886 			iWaitRequest = ETrue;
  1887 			}	
  1888 			
  1889 		}
  1890 	else 
  1891 		{
  1892 		if(IsWriteEndOpened())
  1893 			{	
  1894 			iWaitRequest = EFalse;
  1895 			err = KErrCompletion;
  1896 			}
  1897 		else
  1898 			{
  1899 			iWaitRequest = ETrue;
  1900 			}	
  1901 		}
  1902 	
  1903 	return err;
  1904 	}
  1905 
  1906 
  1907 //! Cancellation methods
  1908 void DPipe::CancelSpaceAvailable()
  1909 /**
  1910 Cancels an outstanding space available notifier request.
  1911 
  1912 @param  None
  1913 
  1914 @return None
  1915 */
  1916 	{	
  1917 	__ASSERT_MUTEX(iPipeMutex);
  1918 	if(iSpaceAvailableRequest)	
  1919 		iSpaceAvailableRequest = EFalse;
  1920 	}
  1921 
  1922 
  1923 void DPipe::CancelDataAvailable()
  1924 /**
  1925 Cancels an outstanding data available notifier request.
  1926 
  1927 @param None
  1928 
  1929 @return None
  1930 */
  1931 	{
  1932 	__ASSERT_MUTEX(iPipeMutex);
  1933 	if(iDataAvailableRequest)
  1934 		iDataAvailableRequest = EFalse;
  1935 	}
  1936 
  1937 
  1938 void DPipe::CancelWaitNotifier()
  1939 /**
  1940 Cancel an outstanding wait notifier request
  1941 
  1942 @param	None
  1943 
  1944 @return	KErrNone		If Successful, otherwise one of the other system wide error code.
  1945 	
  1946 */
  1947 	{
  1948 	__ASSERT_MUTEX(iPipeMutex);
  1949 	// Cancel Wait Notifier request
  1950 	if(iWaitRequest)
  1951 		iWaitRequest = EFalse;
  1952 	}
  1953 
  1954 
  1955 void DPipe::CloseAll()
  1956 /**
  1957 Cancel any outstanding request. 
  1958 
  1959 @param	 None
  1960 
  1961 @return  None
  1962 */
  1963 	{
  1964 	CancelSpaceAvailable();
  1965 	CancelDataAvailable();
  1966 	CancelWaitNotifier();
  1967 	
  1968 	CloseWriteEnd();
  1969   	CloseReadEnd(); 
  1970 	}
  1971 
  1972 
  1973 TInt DPipe::CloseReadEnd()
  1974 /**
  1975 Close the read end of the pipe.
  1976 
  1977 Cancels outstanding requests placed by the *write*
  1978 channel and clears pipe's pointer to the read channel.
  1979 If this function is called then the read channel's back
  1980 pointer to the pipe must also be cleared.
  1981 
  1982 @param	None
  1983 
  1984 @return KErrNone 	If the end is closed, else  one  of the other system 
  1985 					wide error code
  1986 */
  1987 	{
  1988 	__ASSERT_MUTEX(iPipeMutex);
  1989 	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::CloseReadEnd ID=%d, iReadChannel=0x%08x", OpenId(), iReadChannel)); 
  1990 
  1991 	if (!iReadChannel)
  1992 		return KErrCouldNotDisconnect;
  1993 	else
  1994 		{
  1995 		if(iWriteChannel)
  1996 			{
  1997 			iWriteChannel->CancelRequest(RPipe::ECancelSpaceAvailable);	
  1998 			}
  1999 		iReadChannel = NULL;
  2000 		}		
  2001 	return KErrNone;
  2002 	}
  2003 
  2004 
  2005 TInt  DPipe::CloseWriteEnd()
  2006 /**
  2007 Close the write end of the pipe
  2008 
  2009 Cancels outstanding requests placed by the *read*
  2010 channel and clears pipe's pointer to the write channel.
  2011 If this function is called then the write channel's back
  2012 pointer to the pipe must also be cleared.
  2013 
  2014 @param	None
  2015 
  2016 @return KErrNone 	If the write end is successfully closed, else
  2017 	                one of the other system wide error code.
  2018 */
  2019 	{
  2020 	__ASSERT_MUTEX(iPipeMutex);
  2021 	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::CloseWriteEnd ID=%d, iWriteChannel=0x%08x", OpenId(), iWriteChannel)); 
  2022 
  2023 	if (!iWriteChannel)
  2024 		return KErrCouldNotDisconnect;
  2025 	else
  2026 		{
  2027 		// Cancel RBlocking call if it is there
  2028 		if(iReadChannel)
  2029 			{
  2030 			iReadChannel->CancelRequest(RPipe::ECancelDataAvailable);	
  2031 			}
  2032 		iWriteChannel = NULL;	
  2033 		}
  2034 	return KErrNone;				
  2035 	}
  2036 	
  2037 	
  2038 
  2039 void DPipe::FlushPipe()
  2040 /**
  2041 Flush all the date from the pipe and reinitialise the buffer pointer.
  2042 
  2043 @param 	None
  2044 
  2045 @return None
  2046 
  2047 @pre 	Pipe Mutex to be held
  2048 @pre 	Read Mutex to be held
  2049 
  2050 */
  2051 	{
  2052 	__ASSERT_MUTEX(iPipeMutex);
  2053 	__ASSERT_MUTEX(iReadMutex);
  2054 
  2055 	iReadPointer = iWritePointer;
  2056 	iFull	= EFalse;
  2057 	
  2058 	MaybeCompleteSpaceNotification();	
  2059 	}
  2060 
  2061 /**
  2062 If there is an outstanding space request, and
  2063 there is enough space to satisfy it then complete
  2064 and clear request.
  2065 
  2066 @pre the pipe mutex must be held
  2067 */
  2068 void DPipe::MaybeCompleteSpaceNotification()
  2069 	{
  2070 	__ASSERT_MUTEX(iPipeMutex);
  2071 
  2072 	// Check if there is writeblocking request
  2073 	if(iSpaceAvailableRequest) 
  2074 		{
  2075 		const TInt spacecount = (iSize - AvailableDataCount());
  2076 		if (iSpaceAvailableSize <= spacecount)
  2077 			{
  2078 			iWriteChannel->DoRequestCallback();
  2079 			iSpaceAvailableRequest = EFalse;		
  2080 			}	
  2081 		}
  2082 	}
  2083 
  2084 TBool DPipe::IsReadEndOpened()
  2085 /**
  2086 Returns information regarding the read end of the current pipe instance.
  2087 
  2088 @return TBool	ETrue if read end is Opened, otherwise EFalse
  2089 @pre the pipe mutex must be held
  2090 */
  2091 	{
  2092 	__ASSERT_MUTEX(iPipeMutex);
  2093 	return (iReadChannel != NULL);
  2094 	}
  2095 
  2096 
  2097 TBool DPipe::IsWriteEndOpened()
  2098 /**
  2099 Returns information regarding the write end of the current pipe instance.
  2100 
  2101 @return  TBool ETrue if WriteChannel is opened, otherwise EFalse
  2102 @pre the pipe mutex must be held
  2103 */
  2104 	{
  2105 	__ASSERT_MUTEX(iPipeMutex);
  2106 	return (iWriteChannel != NULL);
  2107 	}
  2108 
  2109 
  2110 TBool DPipe::IsNamedPipe()
  2111 /**
  2112 Returns whether the pipe is named or unnamed.
  2113 
  2114 @return TBool  ETrue if it is a named pipe, otherwise EFalse
  2115 
  2116 */
  2117 	{
  2118 	return (iName.Length() != 0); 
  2119 	}
  2120 
  2121 
  2122 void DPipe::SetReadEnd(DPipeChannel* aChannel)
  2123 /**
  2124 Set the Read end of the pipe as opened and store the pointer for the read channel
  2125 It also notify if there is any pending Wait Request.
  2126 
  2127 @param	aChannel	The pointer to the read channel
  2128 
  2129 @pre the pipe mutex must be held
  2130 @pre The pipe's read end must be closed ie. IsReadEndOpened returns false
  2131 */
  2132 	{
  2133 	__ASSERT_MUTEX(iPipeMutex);
  2134 	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::SetReadEnd ID=%d", OpenId())); 
  2135 
  2136 
  2137 	//A channel must be sure this function
  2138 	//succeeded otherwise the pipe
  2139 	//could be destroyed without the channel's
  2140 	//knowledge
  2141 	__NK_ASSERT_DEBUG(iReadChannel==NULL);
  2142 
  2143 	iReadChannel = aChannel;
  2144 	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::SetReadEnd set iReadChannel=0x%08x", iReadChannel)); 
  2145 	
  2146 	if(iWaitRequest)
  2147 		{
  2148 		if(iWriteChannel)
  2149 			iWriteChannel->DoRequestCallback();
  2150 		iWaitRequest=EFalse;
  2151 		}
  2152 	}
  2153 	
  2154 
  2155 void DPipe::SetWriteEnd(DPipeChannel* aChannel)
  2156 /**
  2157 Set the write end of the pipe as opened and store the pointer to the write channel
  2158 
  2159 @param aChannel		The pointer to the write channel
  2160 
  2161 
  2162 @pre the pipe mutex must be held
  2163 @pre The pipe's write end must be closed ie. IsWriteEndOpened returns false
  2164 */
  2165 	{
  2166 	__ASSERT_MUTEX(iPipeMutex);
  2167 	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::SetWriteEnd ID=%d", OpenId())); 
  2168 
  2169 	//A channel must be sure this function
  2170 	//succeeded otherwise the pipe
  2171 	//could be destroyed without the channel's
  2172 	//knowledge
  2173 	__NK_ASSERT_DEBUG(iWriteChannel==NULL);
  2174 
  2175 	iWriteChannel = aChannel;
  2176 	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::SetWriteEnd set iWriteChannel=0x%08x", iWriteChannel)); 
  2177 
  2178 	if(iWaitRequest)
  2179 		{
  2180 		if(iReadChannel)
  2181 			iReadChannel->DoRequestCallback();
  2182 		iWaitRequest=EFalse;
  2183 		}		
  2184 	}
  2185 
  2186 TInt DPipe::Size()
  2187 /**
  2188 @return The size of the pipe's circular buffer 
  2189 */
  2190 	{
  2191 	//this could be const
  2192 	return iSize;	
  2193 	}
  2194