kernel/eka/drivers/pipe/dpipe.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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