os/kernelhwsrv/kernel/eka/drivers/pipe/dpipe.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/pipe/dpipe.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2194 @@
     1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +
    1.20 +#include <kernel/kern_priv.h>
    1.21 +#include "dpipe.h"
    1.22 +
    1.23 +//_LIT(KPipePanicCategory,"PipePanic");
    1.24 +const TInt KPipeGranularity   = 8;
    1.25 +
    1.26 +DECLARE_STANDARD_LDD()
    1.27 +/** 
    1.28 +Standard export function for LDDs. This creates a DLogicalDevice derived
    1.29 +object, in this case our DPipeDevice
    1.30 +*/
    1.31 +	{
    1.32 +	return new DPipeDevice;
    1.33 +	}
    1.34 +
    1.35 +DPipeDevice::DPipeDevice()
    1.36 +/**
    1.37 +DPipeDevice Constructor has minimal implementation such setting the version number
    1.38 +Indicate the use of unit number
    1.39 +
    1.40 +@param		None
    1.41 +
    1.42 +@return 	None
    1.43 +*/ 
    1.44 +	{
    1.45 +	iCount = 0;
    1.46 +    iIdindex = 0;
    1.47 +    iAllocated = 0;
    1.48 +	iVersion = RPipe::VersionRequired();
    1.49 +	}
    1.50 +
    1.51 +
    1.52 +DPipeDevice::~DPipeDevice()
    1.53 +	{
    1.54 +	// Delete the existing pipes
    1.55 +	for(TInt count = 0; count<iCount; count++)
    1.56 +		{
    1.57 +		DPipe* pipe=iDpipes[count];
    1.58 +		pipe->Wait();
    1.59 +		pipe->CloseAll();
    1.60 +		delete pipe;
    1.61 +		}
    1.62 +	Kern::Free(iDpipes);
    1.63 +	iMutex->Close(NULL);
    1.64 +	}
    1.65 +
    1.66 +
    1.67 +TInt DPipeDevice::Install()
    1.68 +/**
    1.69 +Second stage constructor and at least set a name for the 
    1.70 +driver object. Inherited from DLogicalDevice. This must at least set a name
    1.71 +for the driver object.
    1.72 +
    1.73 +@param		None
    1.74 +
    1.75 +@return 	KErrNone 	If successful, otherwise one of the system wide error codes.
    1.76 +*/
    1.77 +	{
    1.78 +	_LIT(KMutexName,"PipeDeviceMutex");
    1.79 +	TInt err = Kern::MutexCreate(iMutex, KMutexName, KMutexOrdGeneral1);
    1.80 +	if (err)
    1.81 +		{
    1.82 +		return err;
    1.83 +		}
    1.84 +	
    1.85 +	return SetName(&RPipe::Name());
    1.86 +	}
    1.87 +
    1.88 +
    1.89 +void DPipeDevice::GetCaps(TDes8& aDes) const
    1.90 +/**
    1.91 +Returns the driver capabilities. Called in the response to
    1.92 +an RPipe::GetCaps() request
    1.93 +
    1.94 +@param  	aDes 		Descriptor into which capabilities information 
    1.95 +					    is to be written
    1.96 +@return 	None
    1.97 +*/
    1.98 +	{
    1.99 +	// Write it back to user memory
   1.100 +	TVersion version;
   1.101 +	version = iVersion;
   1.102 +	Kern::InfoCopy(aDes,(TUint8*)&version, sizeof(version));
   1.103 +	}
   1.104 +
   1.105 +
   1.106 +TInt DPipeDevice::Create(DLogicalChannelBase*& aChannel)
   1.107 +/**
   1.108 +Called by the kernel's device driver framework to create a Logical Channel. 
   1.109 +This is called in the context of the user thread (client) which requested the
   1.110 +creation of the Logical Channel. 
   1.111 +
   1.112 + @param 	aChannel 	Set to point to the created logical channel
   1.113 +
   1.114 + @return 	KErrNone 	If successful, otherwise system one of the other
   1.115 + 						wide error codes.
   1.116 + */
   1.117 +	{
   1.118 +	aChannel = new DPipeChannel;
   1.119 +	if (!aChannel)
   1.120 +		return KErrNoMemory;
   1.121 +	return KErrNone;
   1.122 +	}
   1.123 +
   1.124 +
   1.125 +TInt  DPipeDevice::CreatePipe(const TDesC& aName, TInt aSize, DPipe*& aPipe, TAny* aCap)
   1.126 +/**
   1.127 +Called by DPipeChannel instance to create named DPipe object and 
   1.128 +associate itself with the newly created named DPipe instance.
   1.129 +
   1.130 +@param aName			name need to be attached to the newly created DPipe object.
   1.131 +@param aSize			size of the DPipe object.
   1.132 +@param aPipe	 		Pointer to DPipe, If successful set the pointer to newly created DPipe					instance else NULL						
   1.133 +@param aCap				Pointer to TSecuritypolicy passed as void pointer
   1.134 +
   1.135 +@return  KErrNone 		If successful, otherwise one of the other system wide error code	
   1.136 +@pre    Calling thread must be in a critical section.
   1.137 +@pre    Mutex must be held
   1.138 +*/	
   1.139 +	{	
   1.140 +	__ASSERT_MUTEX(iMutex);
   1.141 +	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipeDevice::CreatePipe")); 
   1.142 +	TInt err = KErrNone;
   1.143 +	DPipe** pS = iDpipes;
   1.144 +	DPipe** pE = pS + iCount;
   1.145 +	while(pS < pE)
   1.146 +		{
   1.147 +		DPipe* pO = *pS++;
   1.148 +		if((pO->MatchName(&aName)))
   1.149 +			{ 
   1.150 +			err = KErrAlreadyExists;
   1.151 +			break;
   1.152 +			}
   1.153 +		}
   1.154 +	if(err == KErrNone)
   1.155 +		{
   1.156 +		DPipe* pipe = DPipe::CreatePipe(aName, aSize, aCap);	
   1.157 +		if(pipe)
   1.158 +			{
   1.159 +		 	err = AddPipe(pipe);
   1.160 +			if(err!= KErrNone)
   1.161 +				{
   1.162 +				delete pipe;
   1.163 +				}
   1.164 +			else
   1.165 +				{
   1.166 +				aPipe = pipe;		
   1.167 +				}
   1.168 +			}
   1.169 +		else
   1.170 +			{
   1.171 +			err = KErrNoMemory;
   1.172 +			}
   1.173 +		}
   1.174 +	__KTRACE_OPT(KPIPE, Kern::Printf("<DPipeDevice::CreatePipe ret=%d", err)); 
   1.175 +	return err;
   1.176 +	}
   1.177 +
   1.178 +
   1.179 +DPipe*  DPipeDevice::CreatePipe(TInt aSize)
   1.180 +/**
   1.181 +Called by DPipeChannel instance to create un-named DPipe instance and 
   1.182 +associate itself with the newly created un-named DPipe instance.
   1.183 +
   1.184 +@param aSize		size of the DPipe object.
   1.185 +				
   1.186 +@return  DPipe*	    If successful, otherwise NULL
   1.187 +@pre    Mutex must be held
   1.188 +@pre	In critical section
   1.189 +*/
   1.190 +	{
   1.191 +	__ASSERT_CRITICAL;
   1.192 +	__ASSERT_MUTEX(iMutex);
   1.193 +	TKName aName;
   1.194 +	DPipe* pipe =  DPipe::CreatePipe(aName, aSize);
   1.195 +	if(!pipe)
   1.196 +		{
   1.197 +		return NULL;
   1.198 +		}
   1.199 +		
   1.200 +	TInt r = AddPipe(pipe);
   1.201 +	if (r != KErrNone)
   1.202 +		{
   1.203 +		delete pipe;
   1.204 +		return NULL;
   1.205 +		}		
   1.206 +	return pipe;	
   1.207 +	}
   1.208 +
   1.209 +
   1.210 +	
   1.211 +TInt DPipeDevice::AddPipe(DPipe* aObj)
   1.212 +/**
   1.213 +Add an instance of Dpipe to the array. 
   1.214 +@param aObj			Pointer to  DPipe object
   1.215 +@return KErrNone 	If the call is successful otherwise  one of the other
   1.216 +					system wide error code.
   1.217 +					
   1.218 +@pre    Calling thread must be in a critical section.
   1.219 +@pre    Mutex to be held
   1.220 +*/
   1.221 +	{
   1.222 +	__ASSERT_CRITICAL; //otherwise iDPipes and iCount could go out of sync
   1.223 +	__ASSERT_MUTEX(iMutex);
   1.224 +	// store the current instance to the array
   1.225 +	if(iCount == iAllocated)
   1.226 +		{
   1.227 +		TInt newAlloc = iAllocated + KPipeGranularity;
   1.228 +		TInt r = Kern::SafeReAlloc((TAny*&)iDpipes, iCount * sizeof(DPipe*), newAlloc * sizeof(DPipe*));
   1.229 +		if (r!= KErrNone)
   1.230 +			{
   1.231 +			return r;
   1.232 +			}
   1.233 +		iAllocated = newAlloc;
   1.234 +		}
   1.235 +	TInt id = GenerateId();	
   1.236 +	aObj->SetId(id);
   1.237 +	iDpipes[iCount++]= aObj;
   1.238 +
   1.239 +	__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::AddPipe Pipe added ID=%d", id)); 
   1.240 +	return KErrNone;
   1.241 +	}
   1.242 +	
   1.243 +
   1.244 +	
   1.245 +void DPipeDevice::RemovePipe(DPipe** aObj)
   1.246 +/**
   1.247 +Remove an instance of DPipe from the array
   1.248 +
   1.249 +@param	Pointer to Dpipe Array
   1.250 +
   1.251 +@return None
   1.252 +
   1.253 +@pre    Calling thread must not be in a critical section.
   1.254 +@pre    Mutex to be held
   1.255 +*/
   1.256 +	{
   1.257 +	__ASSERT_MUTEX(iMutex);
   1.258 +	__ASSERT_CRITICAL; //we don't want to leave the array inconsistant
   1.259 +
   1.260 + 	DPipe**	pE = (iDpipes + iCount) - 1;
   1.261 + 	if(aObj<pE)
   1.262 +		{
   1.263 +		//bump along array elements to close the gap
   1.264 +		wordmove((TAny*)aObj, (TAny*)(aObj+1), TInt(pE)- TInt(aObj));
   1.265 +		}
   1.266 +	--iCount;
   1.267 +	if(iCount % KPipeGranularity == 0)
   1.268 +		{
   1.269 +			Kern::SafeReAlloc((TAny*&)iDpipes, iAllocated*sizeof(DPipe*), iCount* sizeof(DPipe*));
   1.270 +			iAllocated = iCount;
   1.271 +		}
   1.272 +	}
   1.273 +	
   1.274 +
   1.275 +DPipe* DPipeDevice::FindNamedPipe(const TDesC* aName)
   1.276 +/**
   1.277 +Called by the DPipeChannel to check if a named DPipe instance exist with a name
   1.278 +as specified by aName parameter.
   1.279 +
   1.280 +@param aName		The name of the DPipe instance to search for. 
   1.281 +
   1.282 +@return  DPipe*	    If successful, otherwise NULL
   1.283 +
   1.284 +@pre Device mutex to be held
   1.285 +*/
   1.286 +	{
   1.287 +	__ASSERT_MUTEX(iMutex);
   1.288 +	DPipe** pS = iDpipes;
   1.289 +	DPipe** pE = pS + iCount;
   1.290 +	
   1.291 +	while(pS < pE)
   1.292 +		{
   1.293 +		DPipe* pO = *pS++;
   1.294 +		if(pO->MatchName(aName))
   1.295 +			{ 
   1.296 +			return pO;
   1.297 +			}
   1.298 +		}
   1.299 +	return NULL;
   1.300 +	}
   1.301 +		
   1.302 +DPipe* DPipeDevice::FindUnnamedPipe(const TInt aId)
   1.303 +/**
   1.304 +Called by the DPipeChannel to check if an un-named DPipe instance exist with an ID
   1.305 +as specified by aId parameter.
   1.306 +
   1.307 +@param aId			The ID of the DPipe instance to search for. 
   1.308 +	
   1.309 +@return  DPipe*	   If successful, otherwise NULL
   1.310 +@pre Device mutex to be held
   1.311 +*/
   1.312 +	{
   1.313 +	__ASSERT_MUTEX(iMutex);
   1.314 +	DPipe** pS = iDpipes;
   1.315 +	DPipe** pE = pS + iCount;	
   1.316 +	while(pS < pE)
   1.317 +		{
   1.318 +		DPipe* pO = *pS++;
   1.319 +		if(pO->MatchId(aId))
   1.320 +			{
   1.321 +			return pO;
   1.322 +			}
   1.323 +		}
   1.324 +	return NULL;
   1.325 +	}
   1.326 +
   1.327 +TInt DPipeDevice::Destroy(const TDesC* aName)
   1.328 +/**
   1.329 +This method is called to destroy a named DPipe instance. The caller needs to have 
   1.330 +sufficient capabilities to delete a named pipe. This method will fail if there are
   1.331 +any handles still open on the pipe. 
   1.332 +
   1.333 +@param	aName		Name of the DPipe instance to be deleted.
   1.334 +
   1.335 +@return	KErrNone 	If successful, otherwise one of the other system wide error.
   1.336 +
   1.337 +*/
   1.338 +	{
   1.339 +	TAutoWait<DMutex> autoMutex(*iMutex);
   1.340 +	DPipe** pS = iDpipes;
   1.341 +	DPipe**	pE = pS + iCount;
   1.342 +	TInt err = KErrNotFound;
   1.343 +	TInt count = 0;
   1.344 +	while(pS < pE)
   1.345 +		{
   1.346 +		DPipe** pO = pS++;
   1.347 +		DPipe* pipe = *pO;
   1.348 +		if(((*pO)->MatchName(aName)))
   1.349 +			{
   1.350 +			//! Check capability 
   1.351 +			if(pipe->GetCap())
   1.352 +				{
   1.353 +				if(!(pipe->GetCap()->CheckPolicy(&Kern::CurrentThread())))
   1.354 +					{
   1.355 +					err = KErrPermissionDenied;
   1.356 +					break;
   1.357 +					}
   1.358 +				}
   1.359 +			// Check if any handles still opened on the pipe.
   1.360 +			pipe->Wait();
   1.361 +			if (!pipe->IsPipeClosed())
   1.362 +				{
   1.363 +				err = KErrInUse;
   1.364 +				pipe->Signal(); //need to signal if we won't be destroying pipe
   1.365 +				break;
   1.366 +				}
   1.367 +			__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Destroy remove ID=%d", pipe->OpenId())); 
   1.368 +			delete iDpipes[count];
   1.369 +			RemovePipe(pO);
   1.370 +			err = KErrNone;
   1.371 +			break;
   1.372 +			}
   1.373 +		count ++;
   1.374 +		}
   1.375 +	return err;
   1.376 +	}
   1.377 +
   1.378 +
   1.379 +TInt DPipeDevice::Close(TInt aId)
   1.380 +/**
   1.381 +This method is called to close both named and un-named DPipe. In case of un-named DPipe
   1.382 +if there is no further reference of a DPipeChannel exist, the corresponding un-named DPipe
   1.383 +will be deleted. 
   1.384 +
   1.385 +@param aId		 	ID of the pipe that need to be closed.
   1.386 +
   1.387 +@return KErrNone 	If successful otherwise one of the other system wide error.
   1.388 +
   1.389 +*/
   1.390 +	{
   1.391 +	TAutoWait<DMutex> autoMutex(*iMutex);
   1.392 +	DPipe** pS = iDpipes;
   1.393 +	DPipe**	pE = pS + iCount;
   1.394 +	TInt err = KErrNotFound;
   1.395 +	while(pS < pE)
   1.396 +		{
   1.397 +		DPipe** pO = pS++;
   1.398 +		DPipe* pipe = *pO;
   1.399 +		if(pipe->MatchId(aId))
   1.400 +			{
   1.401 +			__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Close found ID=%d", pipe->OpenId())); 
   1.402 +			//even if we can't delete the pipe, we have
   1.403 +			//found it so don't return KErrNotFound
   1.404 +			err = KErrNone;
   1.405 +
   1.406 +			pipe->Wait();
   1.407 +			
   1.408 +			// we can only delete an unamed pipe with both ends closed
   1.409 +		 	if(!pipe->IsNamedPipe() && pipe->IsPipeClosed())
   1.410 +		 		{
   1.411 +				__KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Close remove ID=%d", pipe->OpenId())); 
   1.412 +				delete pipe;
   1.413 +				RemovePipe(pO); 
   1.414 +				break;
   1.415 +		 		}
   1.416 +			pipe->Signal(); 
   1.417 +
   1.418 +			}
   1.419 +		}
   1.420 +	return err;
   1.421 +	}
   1.422 +
   1.423 +
   1.424 +
   1.425 +TInt DPipeDevice::GenerateId()
   1.426 +/**
   1.427 +Generate a ID  and store for a Named pipe while creating.
   1.428 +
   1.429 +@param 	 None
   1.430 +@return  TInt	ID for the name pipe
   1.431 +
   1.432 +@pre    Mutex to be held
   1.433 +
   1.434 +*/
   1.435 +	{
   1.436 +	__ASSERT_MUTEX(iMutex);
   1.437 +	iIdindex++;
   1.438 +	return (KIdBase + iIdindex);		
   1.439 +	}
   1.440 +
   1.441 +
   1.442 +DPipeChannel::DPipeChannel()
   1.443 +	:iClientRequest(NULL), iData(NULL), iChannelType(RPipe::EChannelUnset)
   1.444 +/**
   1.445 +Constructor
   1.446 +*/
   1.447 +	{
   1.448 +	}
   1.449 +
   1.450 +
   1.451 +DPipeChannel::~DPipeChannel()
   1.452 +/**
   1.453 +Destructor
   1.454 +*/
   1.455 +	{
   1.456 +	CloseHandle();
   1.457 +	
   1.458 +	Kern::DestroyClientRequest(iClientRequest); //null ptr is safe
   1.459 +	}
   1.460 +
   1.461 +
   1.462 +
   1.463 +TInt DPipeChannel::RequestUserHandle (DThread* aThread, TOwnerType aType)
   1.464 +/**
   1.465 +Inherited from DObject. This method is called when a user thread requests
   1.466 +a handle to this channel. Minimal implantation here is capability check
   1.467 +
   1.468 +@param aThread		DThread instance reference that requests a handle to this channel.
   1.469 +@param aType		Ownership type for the handle.
   1.470 +
   1.471 +@return  KErrNone  If successful otherwise one the system wide error.
   1.472 +*/
   1.473 +	{
   1.474 +	(void)aThread;
   1.475 +	(void)aType;
   1.476 + 	return KErrNone;
   1.477 +	}
   1.478 +
   1.479 +
   1.480 +    
   1.481 +TInt DPipeChannel::DoCreate (TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
   1.482 +/**
   1.483 +Inherited from DLogicalChannelBase class.  This method represents the second stage
   1.484 +constructor called by the kernel's device driver framework. This is called in the
   1.485 +context of the user thread (client) which requested the creation of the Logical
   1.486 +Channel. The thread is in critical section.
   1.487 +
   1.488 +@param aUnit		The unit argument supplied by the client
   1.489 +@param aInfo		The info argument supplied by the client 
   1.490 +@param aVer			The version argument supplied by the client 
   1.491 +
   1.492 +@return KErrNone 	If successful, otherwise one of the other system wide error codes.
   1.493 +*/
   1.494 +	{
   1.495 +	(void)aInfo;
   1.496 +	(void)aUnit;
   1.497 +	
   1.498 +  	// Check version
   1.499 +    if (!Kern::QueryVersionSupported(RPipe::VersionRequired(),aVer))
   1.500 +        return KErrNotSupported;
   1.501 +
   1.502 +	TInt r = Kern::CreateClientRequest(iClientRequest);
   1.503 +	if(r != KErrNone)
   1.504 +		{
   1.505 +		return r;
   1.506 +		}
   1.507 +
   1.508 +	// Done 
   1.509 +	return KErrNone;
   1.510 +	}
   1.511 +
   1.512 +
   1.513 +TInt DPipeChannel::Request(TInt aReqNo, TAny* a1, TAny* a2)
   1.514 +/**
   1.515 +Called by the Device driver framework upon user request. Stores the 
   1.516 +Thread pointer under whose context this function is called. 
   1.517 +
   1.518 +@param aFunction	A number identifying the  message type
   1.519 +@param a1			A 32-bit Value passed by the user
   1.520 +@param a2			A 32-bit Value passed by the user
   1.521 +
   1.522 +@return	KErrNone	If successful, otherwise one of the system wide error code
   1.523 +	
   1.524 +*/	
   1.525 +	{
   1.526 +	TInt err = KErrNone;
   1.527 +	
   1.528 +	DATAPAGING_TEST
   1.529 +		(
   1.530 +		err = Kern::HalFunction(EHalGroupVM, EVMHalFlushCache, 0, 0);
   1.531 +		if(err != KErrNone)
   1.532 +			{
   1.533 +			return err;
   1.534 +			}
   1.535 +		)
   1.536 +
   1.537 +	if(aReqNo == KMaxTInt)
   1.538 +		{
   1.539 +			CancelRequest((TInt)a1);
   1.540 +			return err;
   1.541 +		}
   1.542 +	if(aReqNo < 0)
   1.543 +		{
   1.544 +		// DoRequest
   1.545 +		TAny *array[2] = {0,0};
   1.546 +		TRequestStatus * pStat = (TRequestStatus*)a1;
   1.547 +		kumemget32(&array[0], a2, 2*sizeof(TAny*));
   1.548 +		err = DoRequest(~aReqNo, pStat, array[0], array[1]);
   1.549 +		if(err!= KErrNone)
   1.550 +			Kern::RequestComplete(pStat, err);
   1.551 +		
   1.552 +		}
   1.553 +	else
   1.554 +		{
   1.555 +		// DoControl
   1.556 +		err = DoControl(aReqNo, a1, a2);
   1.557 +		}
   1.558 +		return err;
   1.559 +	}
   1.560 +
   1.561 +
   1.562 +TInt DPipeChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   1.563 +/**
   1.564 +Processes Synchronous 'control' requests. This function is called to service
   1.565 +any synchronous calls through the  user side RPipe handle. 
   1.566 +
   1.567 +@param aFunction		A number identifying the  message type
   1.568 +@param a1				A 32-bit Value passed by the user
   1.569 +@param a2				A 32-bit Value passed by the user
   1.570 +
   1.571 +@return KErrNone 		If the call is successful, otherwise one of the other
   1.572 +						system wide error
   1.573 +*/
   1.574 +	{
   1.575 +	TInt aSize = 0;
   1.576 +	TInt aId = 0;
   1.577 +	
   1.578 +    switch(aFunction)
   1.579 +		{
   1.580 +		case RPipe::EDefineNamedPipe:
   1.581 +			return PipeCreate(a1, a2);
   1.582 +			
   1.583 +		case RPipe::EOpenToReadNamedPipe:
   1.584 +			return PipeOpen((const TDesC*)a1, RPipe::EReadChannel);
   1.585 +		
   1.586 +		case RPipe::EOpenToWriteNamedPipe:
   1.587 +			return PipeOpen((const TDesC*)a1, RPipe::EWriteChannel);
   1.588 +		
   1.589 +		case RPipe::EOpenToWriteButFailOnNoReaderNamedPipe:
   1.590 +			return OpenOnReader((const TDesC*)a1);
   1.591 +		
   1.592 +		case RPipe::EDestroyNamedPipe:
   1.593 +			return PipeDestroy((const TDesC*)a1);	
   1.594 +		
   1.595 +		case RPipe::ECreateUnNamedPipe:
   1.596 +			kumemget((TAny*)&aSize, a1, sizeof(TInt));
   1.597 +			return PipeCreate( aSize);
   1.598 +		
   1.599 +		case RPipe::EOpenUnNamedPipe:
   1.600 +			kumemget((TAny*)&aId, a1, sizeof(TInt));
   1.601 +			return PipeOpen(aId);
   1.602 +		
   1.603 +		case RPipe::ERead:
   1.604 +			kumemget((TAny*)&aSize, a2, sizeof(TInt));
   1.605 +			return Read (a1, aSize);
   1.606 +		
   1.607 +		case RPipe::EWrite:
   1.608 +			kumemget((TAny*)&aSize, a2, sizeof(TInt));
   1.609 +			return Write (a1, aSize);
   1.610 +				
   1.611 +		case RPipe::ESize:
   1.612 +			 return Size();
   1.613 +		
   1.614 +		case RPipe::EDataAvailableCount:
   1.615 +			 {		
   1.616 +			 TAutoWait<DMutex> autoMutex(iData->Mutex());
   1.617 +			 return iData->AvailableDataCount();
   1.618 +			 }
   1.619 +			 
   1.620 +		case RPipe::EFlushPipe:
   1.621 +			 Flush();
   1.622 +			 return KErrNone;
   1.623 +			 
   1.624 +		case RPipe::EGetPipeInfo:
   1.625 +			 umemput(a1,(TAny*)&iChannelType, sizeof(TInt));
   1.626 +			 aSize = Size();
   1.627 +			 umemput(a2,(TAny*)&aSize, sizeof(TInt));
   1.628 +			 return KErrNone;
   1.629 +			
   1.630 +	
   1.631 +		default:
   1.632 +			 return KErrNotSupported;
   1.633 +			 
   1.634 +		}
   1.635 +
   1.636 +	}
   1.637 +
   1.638 +
   1.639 +TInt DPipeChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   1.640 +/**
   1.641 +Processes Asynchronous requests This function is called to service
   1.642 +any asynchronous calls through the  user side RPipe handle. 
   1.643 +
   1.644 +@param aFunction		A number identifying the  message type
   1.645 +@param aStatus 			Status request to be completed. 
   1.646 +@param a1				A 32-bit Value passed by the user
   1.647 +@param a2				A 32-bit Value passed by the user
   1.648 +
   1.649 +@return  KErrNone 		If the call is successful, else one of the system wide error
   1.650 +*/
   1.651 +	{
   1.652 +	(void)a2;
   1.653 +	TInt aSize = 0;
   1.654 +	TInt aChoice = 0;
   1.655 +
   1.656 +    switch(aReqNo)
   1.657 +		{
   1.658 +		case RPipe::EDataAvailable:
   1.659 +				return NotifyDataAvailable(aStatus, ETrue);	
   1.660 +			
   1.661 +		case RPipe::ESpaceAvailable:
   1.662 +				umemget(&aSize, a1, sizeof(aSize));
   1.663 +				return NotifySpaceAvailable(aSize, aStatus, ETrue);
   1.664 +		
   1.665 +		case RPipe::EWaitNotification:
   1.666 +				// a2 == RPipe::EWaitForReader is for WaitForReader.
   1.667 +				// a2 == RPipe::EWaitForWriter is for WaitForWriter.
   1.668 +				umemget(&aChoice, a2, sizeof(aChoice));
   1.669 +				return WaitNotification(aStatus, a1, aChoice);
   1.670 +				
   1.671 +		case RPipe::EReadBlocking:
   1.672 +			{
   1.673 +				return NotifyDataAvailable(aStatus, EFalse);
   1.674 +			}
   1.675 +				
   1.676 +		case RPipe::EWriteBlocking:
   1.677 +			{
   1.678 +				umemget(&aSize, a1, sizeof(aSize));
   1.679 +				return NotifySpaceAvailable(aSize, aStatus, EFalse);
   1.680 +			}
   1.681 +		default:
   1.682 +				return KErrNotSupported;
   1.683 +		}
   1.684 +	}
   1.685 +
   1.686 +
   1.687 +		
   1.688 +TInt DPipeChannel::PipeCreate(TAny* a1,  TAny* a2)
   1.689 +/**
   1.690 +Creates named pipes with the specified name  and size. It calls Pipe Device 
   1.691 +object to create the pipe and obtained the pointer to it. The pointer is then
   1.692 +stored in its iData member data.
   1.693 +@param a1		Pointer to TPipeInfo class
   1.694 +
   1.695 +@param a2		Pointer to TSecurityPolicy class
   1.696 +
   1.697 +@return KErrNone	If successful, otherwise one of the other system wide error code.
   1.698 +*/
   1.699 +	{
   1.700 +	if(iData)
   1.701 +		{
   1.702 +		//this channel already has a pipe
   1.703 +		return KErrInUse;
   1.704 +		}
   1.705 +
   1.706 +	// The following code safely gets the 3 arguments into kernel memory.
   1.707 +	// (The user side API is badly designed,)
   1.708 +	RPipe::TPipeInfo& info = (*(RPipe::TPipeInfoBuf*)a1)(); // reference to user side 'TPipeInfo'
   1.709 +	TInt size;
   1.710 +	kumemget(&size,&info.isize,sizeof(size));
   1.711 +	TKName name;
   1.712 +	Kern::KUDesGet(name,info.iName);
   1.713 +	TSecurityPolicy* securityPolicy = 0;
   1.714 +	TSecurityPolicy securityPolicyBuffer;
   1.715 +	if(a2)
   1.716 +		{
   1.717 +		kumemget(&securityPolicyBuffer,a2,sizeof(securityPolicyBuffer));
   1.718 +		securityPolicy = &securityPolicyBuffer;
   1.719 +		}
   1.720 +
   1.721 +	DPipe * pipe = NULL;
   1.722 +	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   1.723 +
   1.724 +	//must wait on device since after creation
   1.725 +	//the pipe becomes globably findable 
   1.726 +	//and destroyable
   1.727 +	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   1.728 +
   1.729 +	TInt err = ((DPipeDevice*)iDevice)->CreatePipe(name, size, pipe, securityPolicy);
   1.730 +	if(err!= KErrNone)
   1.731 +		{
   1.732 +		return err;
   1.733 +		}
   1.734 +
   1.735 +	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   1.736 +	pipe->SetReadEnd(this);
   1.737 +	iData = pipe;
   1.738 +	iChannelType = RPipe::EReadChannel;
   1.739 +	return err;
   1.740 +	}
   1.741 +
   1.742 +
   1.743 +TInt DPipeChannel::PipeCreate(const TInt aSize)
   1.744 +/**
   1.745 +Creates unnamed pipes with the specified Id and size. It calls Pipe Device 
   1.746 +object to create the pipe and obtained the pointer to it. The pointer is then
   1.747 +stored in its iData member data. Marked the current channel as read end.  
   1.748 +
   1.749 +@param aSize		Size of the unnamed pipe to be created.
   1.750 +
   1.751 +@return	Handle ID if successful, otherwise one of the other system wide error code.
   1.752 +*/
   1.753 +	{
   1.754 +	if(iData)
   1.755 +		{
   1.756 +		//this channel already has a pipe
   1.757 +		return KErrInUse;
   1.758 +		}
   1.759 +
   1.760 +	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   1.761 +
   1.762 +	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   1.763 +
   1.764 +	DPipe* pipe = device.CreatePipe(aSize);
   1.765 +	if(pipe == NULL)
   1.766 +		{
   1.767 +		return KErrNoMemory;
   1.768 +		}
   1.769 +
   1.770 +	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   1.771 +
   1.772 +	pipe->SetReadEnd(this);
   1.773 +	iData = pipe;
   1.774 +	iChannelType = RPipe::EReadChannel;
   1.775 +
   1.776 +	return iData->OpenId();
   1.777 +	}
   1.778 +
   1.779 +
   1.780 +TInt DPipeChannel::OpenOnReader(const TDesC* aName)
   1.781 +/**
   1.782 +Opens a named pipe identified by the name parameter. It calls Pipe Device object
   1.783 +to open the Pipe identified by the name and obtained the pointer to the pipe. The
   1.784 +pointer is them stored in its iData member data. Marked the current channel as write
   1.785 +end. 
   1.786 +@param 	aName		The name of the pipe to be opened.
   1.787 +
   1.788 +@return KErrNone	If successful, otherwise one of the other system wide error code. 
   1.789 +*/
   1.790 +	{
   1.791 +	if(iData)
   1.792 +		{
   1.793 +		//this channel already has a pipe
   1.794 +		return KErrInUse;
   1.795 +		}
   1.796 +
   1.797 +	TKName PName;
   1.798 +	Kern::KUDesGet(PName, *aName);
   1.799 +
   1.800 +	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   1.801 +
   1.802 +	//need to hold the device mutex to
   1.803 +	//prevent the pipe getting deleted before we can call
   1.804 +	//SetWriteEnd
   1.805 +	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   1.806 +	DPipe* pipe = device.FindNamedPipe(&PName);
   1.807 +
   1.808 +	if(pipe == NULL)
   1.809 +		{
   1.810 +		return KErrNotFound;
   1.811 +		}
   1.812 +
   1.813 +	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   1.814 +	if (!pipe->IsReadEndOpened())
   1.815 +		{
   1.816 +		return KErrNotReady;
   1.817 +		}
   1.818 +	
   1.819 +	iData = pipe;
   1.820 +
   1.821 +	if(!CheckCap())
   1.822 +		{
   1.823 +		iData = NULL;
   1.824 +		return KErrPermissionDenied;
   1.825 +		}
   1.826 +	
   1.827 +	if(pipe->IsWriteEndOpened())
   1.828 +		{
   1.829 +		iData = NULL;
   1.830 +		return KErrInUse;
   1.831 +		}	
   1.832 +
   1.833 +	iData->SetWriteEnd(this);
   1.834 +	iChannelType = RPipe::EWriteChannel;
   1.835 +	return KErrNone;
   1.836 +	}
   1.837 +
   1.838 +
   1.839 +TInt DPipeChannel::PipeDestroy(const TDesC* aName)
   1.840 +/**
   1.841 +Destroys the named pipe.
   1.842 +@param	aName 			Name of the Kernel pipe to be destroyed.
   1.843 +
   1.844 +@return KErrNone		If the pipe is successfully destroyed, otherwise one of the
   1.845 +						other system wide error codes
   1.846 +*/
   1.847 +	{	
   1.848 +	TKName PName;
   1.849 +	Kern::KUDesGet(PName, *aName);
   1.850 +	return ((DPipeDevice*)iDevice)->Destroy(&PName);
   1.851 +	}
   1.852 +
   1.853 +TInt DPipeChannel::PipeOpen(const TInt aId)
   1.854 +/**
   1.855 +Opens a unnamed pipe identified by the specified id. It calls Pipe Device object
   1.856 +to open a unnamed pipe identified by the specified id and obtain the pointer to the
   1.857 +pipe. The pipe reference is then stored in its iData member data and marked the 
   1.858 +current channel as write end. 
   1.859 +
   1.860 +@param 	aId 		Id of the unnamed pipe to be opened.
   1.861 +
   1.862 +@return KErrNone	If successful, otherwise one of the system wide error code. 
   1.863 +*/
   1.864 +	{
   1.865 +	if(iData)
   1.866 +		{
   1.867 +		//this channel already has a pipe
   1.868 +		return KErrInUse;
   1.869 +		}
   1.870 +
   1.871 +	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   1.872 +	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   1.873 +
   1.874 +	DPipe* pipe = device.FindUnnamedPipe(aId);
   1.875 +	if(pipe == NULL)
   1.876 +		{
   1.877 +		return KErrNotFound;
   1.878 +		}
   1.879 +
   1.880 +	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   1.881 +	if (pipe->IsWriteEndOpened() )
   1.882 +		{
   1.883 +		return KErrInUse;
   1.884 +		}
   1.885 +
   1.886 +	pipe->SetWriteEnd(this);
   1.887 +
   1.888 +	iChannelType = RPipe::EWriteChannel;
   1.889 +	iData = pipe;
   1.890 +	
   1.891 +	return KErrNone;
   1.892 +	}
   1.893 +
   1.894 +
   1.895 +TInt DPipeChannel::PipeOpen(const TDesC* aName, RPipe::TChannelType aType)
   1.896 +/**
   1.897 +This function will be called under DoControl();
   1.898 +Attempts to open the pipe for reading (iReadEnd) or writing (iWriteEnd)
   1.899 +@param  aName 		Name of the pipe to be opened
   1.900 +
   1.901 +@param  aType	 	Type of operation to be performed.
   1.902 +
   1.903 +@return KErrNone	Pipe successfully created, otherwise one of the other system wide
   1.904 +					error code
   1.905 +*/ 
   1.906 +	{
   1.907 +	if(iData)
   1.908 +		{
   1.909 +		//this channel already has a pipe
   1.910 +		return KErrInUse;
   1.911 +		}
   1.912 +
   1.913 +	TKName PName;
   1.914 +	Kern::KUDesGet(PName, *aName);
   1.915 +	
   1.916 +	DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
   1.917 +
   1.918 +	TAutoWait<DMutex> outerAutoMutex(device.Mutex());
   1.919 +
   1.920 +	DPipe* pipe = device.FindNamedPipe(&PName);
   1.921 +	if(pipe == NULL)
   1.922 +		{
   1.923 +		return KErrNotFound;
   1.924 +		}
   1.925 +
   1.926 +
   1.927 +	TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
   1.928 +	iData = pipe;
   1.929 +	//! Check capabilitity if applicalble
   1.930 +	if(!CheckCap())
   1.931 +		{
   1.932 +		iData = NULL;
   1.933 +		return KErrPermissionDenied;
   1.934 +		}
   1.935 +
   1.936 +	// Check if the pipe is already opened.
   1.937 +	if(aType == RPipe::EReadChannel)
   1.938 +		{
   1.939 +		if(iData->IsReadEndOpened())
   1.940 +			{
   1.941 +			iData = NULL;
   1.942 +			return KErrInUse;
   1.943 +			}
   1.944 +		iData->SetReadEnd(this);
   1.945 +		}
   1.946 +	else
   1.947 +		{
   1.948 +		if(iData->IsWriteEndOpened())
   1.949 +			{
   1.950 +			iData = NULL;
   1.951 +			return KErrInUse;
   1.952 +			}
   1.953 +		iData->SetWriteEnd(this);	
   1.954 +		}
   1.955 +
   1.956 +	iChannelType = aType;
   1.957 +
   1.958 +	return KErrNone;	
   1.959 +	}
   1.960 +
   1.961 +
   1.962 +
   1.963 +TBool DPipeChannel::CheckCap()
   1.964 +/**
   1.965 +Check if Security policy is installed, if so, checks if the current thread
   1.966 +has required capabilities
   1.967 +
   1.968 +@param 	None
   1.969 +
   1.970 +@return TBool  ETrue if The current thread has required capabilities and also if
   1.971 +			  no capabilities is installed, otherwise EFlase.
   1.972 +			  
   1.973 +*/
   1.974 +	{
   1.975 +	//iData->GetCap is always true
   1.976 +	if(iData->GetCap())
   1.977 +		return iData->GetCap()->CheckPolicy(&Kern::CurrentThread());
   1.978 +	else 
   1.979 +		return ETrue;
   1.980 +	}
   1.981 +
   1.982 +
   1.983 +
   1.984 +TInt DPipeChannel::Read (TAny* aBuff, TInt aSize)
   1.985 +/**
   1.986 +Synchronous, non-blocking read operation. If the pipe is empty it will 
   1.987 +return immediately with KErrUnderflow. A successful DPipe::Read() operation 
   1.988 +will free up more space in the pipe. If a request status object has been registered
   1.989 +for Space Available notification, it will complete. Note that there is no 
   1.990 +guarantee that the amount of space freed up in the pipe will be sufficient 
   1.991 +for the next DPipe::Write() operation.
   1.992 +
   1.993 +@param	aBuff			Buffer from which data need to be read
   1.994 +
   1.995 +@param	aSize			Size of the data to be read
   1.996 +
   1.997 +@return:>0				Amount of data read  in octets.
   1.998 +		 KErrArgument   Invalid Length	Amount of data to be read is invalid (e.g. negative) 
   1.999 +		 KErrNotReady	If the write end is closed,
  1.1000 +		  				otherwise one of the other system wide error code  		
  1.1001 +*/
  1.1002 +	{
  1.1003 +	
  1.1004 +	if( iChannelType != RPipe::EReadChannel)
  1.1005 +		return KErrAccessDenied;
  1.1006 +	
  1.1007 +
  1.1008 +	TAutoWait<DMutex> outerAutoMutex(*iData->iReadMutex);
  1.1009 +	TAutoWait<DMutex> innerAutoMutex(iData->Mutex());
  1.1010 +	//iData->Wait();
  1.1011 +	if(!iData->IsWriteEndOpened() && iData->IsBufferEmpty())
  1.1012 +		{
  1.1013 +		//it is ok to read from a broken pipe provided there is data in it
  1.1014 +		return KErrNotReady;	
  1.1015 +		}
  1.1016 +
  1.1017 +	return iData->Read(aBuff, aSize);
  1.1018 +	}
  1.1019 +
  1.1020 +
  1.1021 +TInt DPipeChannel::Write (TAny* aBuff, TInt aSize)
  1.1022 +/**
  1.1023 +Synchronous, non-blocking write operation. If the pipe is full it will 
  1.1024 +return immediately with KErrOverflow. A successful DPipe::Write() operation will
  1.1025 +return amount of data written to the pipe.If a request status object has been registered
  1.1026 +for Data Available notification, it will complete.
  1.1027 +
  1.1028 +
  1.1029 +@param aBuf				Buffer from which data need to be written to the pipe.
  1.1030 +				
  1.1031 +@param aSize			Amount of data to be written to the pipe.
  1.1032 +	 
  1.1033 +@return >0				Amount of data written to the pipe, in octets.
  1.1034 +		KErrOverflow	The pipe is full no data is written.
  1.1035 +		KErrArgument	if the amount of data to be written in invalid
  1.1036 +		KErrNotReady	if the read end is not opened.
  1.1037 +						otherwise one of the other system wide error code
  1.1038 +*/
  1.1039 +	{
  1.1040 +	
  1.1041 +	if(iChannelType!= RPipe::EWriteChannel)
  1.1042 +		return KErrAccessDenied;
  1.1043 +		
  1.1044 +	TAutoWait<DMutex> outerAutoMutex(*iData->iWriteMutex);
  1.1045 +	TAutoWait<DMutex> innerAutoMutex(iData->Mutex());
  1.1046 +	
  1.1047 +	if(!(iData->IsReadEndOpened()))
  1.1048 +		{
  1.1049 +		return KErrNotReady;
  1.1050 +		}
  1.1051 +
  1.1052 +	return iData->Write(aBuff, aSize);	
  1.1053 +	}
  1.1054 +
  1.1055 +
  1.1056 +
  1.1057 +TInt DPipeChannel::CloseHandle()
  1.1058 +/**
  1.1059 +Attempts to close the pipe for reading  or writing .
  1.1060 +
  1.1061 +@param	None
  1.1062 +
  1.1063 +@return KErrNone				Success.
  1.1064 +		KErrCouldNotDisconnect	The pipe is already closed for that operation.
  1.1065 +
  1.1066 +*/
  1.1067 +	{
  1.1068 +	if(iData==NULL)
  1.1069 +		{
  1.1070 +		return KErrNone;
  1.1071 +		}
  1.1072 +
  1.1073 +	__KTRACE_OPT(KPIPE, Kern::Printf("DPipeChannel::CloseHandle ID=%d, ChannelType=%d", iData->OpenId(), iChannelType)); 
  1.1074 +	
  1.1075 +	NKern::ThreadEnterCS();
  1.1076 +	iData->Wait();
  1.1077 +	TInt err = KErrNone;
  1.1078 +	if(iChannelType == RPipe::EReadChannel)
  1.1079 +	 	{
  1.1080 +	 	CancelRequest(RPipe::EDataAvailable);
  1.1081 +	 	err = iData->CloseReadEnd();
  1.1082 +	 	}
  1.1083 +	else if(iChannelType == RPipe::EWriteChannel)
  1.1084 +	 	{
  1.1085 +	 	CancelRequest(RPipe::ESpaceAvailable);
  1.1086 +	 	err = iData->CloseWriteEnd();
  1.1087 +	 	}
  1.1088 +	else
  1.1089 +	 	{
  1.1090 +		FAULT(); //iChannelType should be set correctly if iData was non-null
  1.1091 +	 	}
  1.1092 +	// If we had a pointer to the pipe but it had no back pointer
  1.1093 +	// to us something has gone wrong.
  1.1094 +	__NK_ASSERT_DEBUG(err == KErrNone); 
  1.1095 +
  1.1096 +	const TInt pipeId=iData->OpenId();
  1.1097 +	iData->Signal();
  1.1098 +	iData = NULL;
  1.1099 +
  1.1100 +	// The return code from close would inform us if
  1.1101 +	// the device had no record of the pipe.
  1.1102 +	// However, for a named pipe there is no gurrantee that the pipe
  1.1103 +	// hasn't been deleted once we close our end of the pipe and
  1.1104 +	// Signal.
  1.1105 +	static_cast<DPipeDevice*>(iDevice)->Close(pipeId);
  1.1106 +
  1.1107 +	NKern::ThreadLeaveCS();
  1.1108 +	 
  1.1109 +	return err;
  1.1110 +	}
  1.1111 +
  1.1112 +
  1.1113 +
  1.1114 +TInt DPipeChannel::NotifySpaceAvailable ( TInt aSize,TRequestStatus* aStat, TBool aAllowDisconnected)
  1.1115 +/**
  1.1116 +Registers the request status object to be completed when space becomes 
  1.1117 +available in the pipe. 
  1.1118 +
  1.1119 +@param 	aSize			The size for which the user has requested for notification
  1.1120 +
  1.1121 +@param	aStat			Status request to be registered
  1.1122 +@param	aAllowDisconnected If false then confirm that the pipe has a reader
  1.1123 +
  1.1124 +@return KErrNone		 Success in registering the request
  1.1125 +		KErrAccessDenied If the correct end is not used to register the request
  1.1126 +		KErrInUse		 A notifier of this type has already been registered.
  1.1127 +						 otherwise one of the other system wide error code.
  1.1128 +		KErrNotReady	The pipe has no reader
  1.1129 +*/
  1.1130 +	{
  1.1131 +	
  1.1132 +	//! Check if correct end is used
  1.1133 +	if(iChannelType!= RPipe::EWriteChannel)
  1.1134 +		{
  1.1135 +		return KErrAccessDenied;
  1.1136 +		}
  1.1137 +	
  1.1138 +	TAutoWait<DMutex> autoMutex(iData->Mutex());
  1.1139 +	//Check if there is already a pending Space Available request.
  1.1140 +	if(iClientRequest->StatusPtr())
  1.1141 +		{
  1.1142 +		return KErrInUse;
  1.1143 +		}
  1.1144 +	else
  1.1145 +		{
  1.1146 +		if(!aAllowDisconnected && !(iData->IsReadEndOpened()) )
  1.1147 +			return KErrNotReady;
  1.1148 +
  1.1149 +		TInt r = iClientRequest->SetStatus(aStat);
  1.1150 +		__NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
  1.1151 +		DThread* const currThread = &Kern::CurrentThread();
  1.1152 +
  1.1153 +		if((iData->RegisterSpaceAvailableNotification(aSize))==KErrCompletion)
  1.1154 +			{
  1.1155 +			Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
  1.1156 +			}
  1.1157 +		else
  1.1158 +			{
  1.1159 +			iRequestThread = currThread;
  1.1160 +			// Open a reference on client thread so its control block can't disappear until
  1.1161 +			// this channel has finished with it.
  1.1162 +			iRequestThread->Open();   
  1.1163 +			iRequestType = RPipe::ESpaceAvailable;
  1.1164 +			}
  1.1165 +		}
  1.1166 +	return KErrNone;
  1.1167 +	}
  1.1168 +
  1.1169 +
  1.1170 +TInt DPipeChannel::NotifyDataAvailable (TRequestStatus* aStat, TBool aAllowDisconnected)
  1.1171 +/**
  1.1172 +Registers the request status object to be completed when data becomes 
  1.1173 +available in the pipe. 
  1.1174 +
  1.1175 +@param	aStat			Status request to be registered
  1.1176 +@param	aAllowDisconnected  If false then fail if the pipe is empty with no writer.
  1.1177 +
  1.1178 +@return KErrNone		 Success in registering the request
  1.1179 +		KErrAccessDenied If the correct end is not used to register the request 
  1.1180 +		KErrInUse		 A notifier of this type has already been registered.
  1.1181 +						 otherwise one of the other system wide error code.
  1.1182 +		KErrNotReady	 The pipe was empty and had no writer
  1.1183 +*/
  1.1184 +	{	
  1.1185 +
  1.1186 +	//! Check if correct end is used
  1.1187 +	if(iChannelType!= RPipe::EReadChannel)
  1.1188 +		{
  1.1189 +		return KErrAccessDenied;
  1.1190 +		}
  1.1191 +
  1.1192 +	// Check if there is already a pending Data Available request.	
  1.1193 +	TAutoWait<DMutex> autoMutex(iData->Mutex() );
  1.1194 +	if(iClientRequest->StatusPtr())
  1.1195 +		{
  1.1196 +		return KErrInUse;
  1.1197 +		}
  1.1198 +	else
  1.1199 +		{
  1.1200 +		if(!aAllowDisconnected)
  1.1201 +			{
  1.1202 +			if(iData->IsBufferEmpty() && (!iData->IsWriteEndOpened()))
  1.1203 +				return KErrNotReady;
  1.1204 +			}
  1.1205 +		
  1.1206 +		TInt r = iClientRequest->SetStatus(aStat);
  1.1207 +		__NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
  1.1208 +		DThread* const currThread = &Kern::CurrentThread();
  1.1209 +
  1.1210 +		if((iData->RegisterDataAvailableNotification()) == KErrCompletion)
  1.1211 +			{
  1.1212 +			Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
  1.1213 +			}
  1.1214 +		else
  1.1215 +			{
  1.1216 +			iRequestThread = currThread;
  1.1217 +			// Open a reference on client thread so its control block can't disappear until
  1.1218 +			// this channel has finished with it.
  1.1219 +			iRequestThread->Open();   
  1.1220 +			iRequestType = RPipe::EDataAvailable;
  1.1221 +			}
  1.1222 +		}
  1.1223 +	return  KErrNone;;
  1.1224 +	}
  1.1225 +
  1.1226 +
  1.1227 +TInt DPipeChannel::WaitNotification(TRequestStatus* aStat, TAny* aName, TInt aChoice)
  1.1228 +/**
  1.1229 +Registers the request status object to be completed when other end of the pipe
  1.1230 +is opened for reading (or writing).This method completes immediately if the other end of the
  1.1231 +pipe is already opened.
  1.1232 +
  1.1233 +
  1.1234 +@param	aName		Pointer to the a name passed as void pointer
  1.1235 +
  1.1236 +@param	aStat		Status request to be registered
  1.1237 +
  1.1238 +@param	aChoice		EWaitForReader,wait notification for Read end Opened.
  1.1239 +					EWaitForWriter,wait notification for Write end Opened.
  1.1240 +
  1.1241 +@return KErrNone		 Success in registering the request
  1.1242 +		KErrInUse		 A notifier of this type has already been registered.
  1.1243 +		KErrAccessDenied If the correct end is not used to register the request 
  1.1244 +						 otherwise one of the other system wide error code
  1.1245 +
  1.1246 +*/
  1.1247 +	{
  1.1248 +	//! Check if correct end is used
  1.1249 +	if(((aChoice == RPipe::EWaitForReader) && (iChannelType!= RPipe::EWriteChannel))
  1.1250 +		|| ((aChoice == RPipe::EWaitForWriter) && (iChannelType!= RPipe::EReadChannel)))
  1.1251 +		{
  1.1252 +		return KErrAccessDenied;
  1.1253 +		}
  1.1254 +
  1.1255 +	TKName PName;
  1.1256 +	Kern::KUDesGet(PName, *(TDesC*)aName);
  1.1257 +
  1.1258 +	TAutoWait<DMutex> autoMutex(iData->Mutex());
  1.1259 +	if(iData->MatchName(&PName)== EFalse)
  1.1260 +		{
  1.1261 +		return KErrNotFound;
  1.1262 +		}
  1.1263 +	// Check if there is already a pending request.
  1.1264 +	else if(iClientRequest->StatusPtr())
  1.1265 +		{
  1.1266 +		return KErrInUse;
  1.1267 +		}
  1.1268 +	else
  1.1269 +		{
  1.1270 +		TInt r = iClientRequest->SetStatus(aStat);
  1.1271 +		__NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
  1.1272 +		DThread* const currThread = &Kern::CurrentThread();
  1.1273 +
  1.1274 +		//register the request.
  1.1275 +		if((iData->RegisterWaitNotification((TInt )aChoice))== KErrCompletion)
  1.1276 +			{
  1.1277 +			Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
  1.1278 +			}
  1.1279 +		else
  1.1280 +			{
  1.1281 +			iRequestThread = currThread;
  1.1282 +			// Open a reference on client thread so its control block can't disappear until
  1.1283 +			// this channel has finished with it.
  1.1284 +			iRequestThread->Open();   
  1.1285 +			iRequestType = RPipe::EWaitNotification;
  1.1286 +			}
  1.1287 +		}
  1.1288 +	return KErrNone;
  1.1289 +	}
  1.1290 +
  1.1291 +
  1.1292 +/**
  1.1293 +For a given request return true if the notification
  1.1294 +we are cancelling is outstanding. If not, or
  1.1295 +if the supplied request is not a valid cancllation
  1.1296 +return false
  1.1297 +*/
  1.1298 +TBool DPipeChannel::ValidCancellation(TInt aReqType)
  1.1299 +{
  1.1300 +	switch(aReqType)
  1.1301 +	{
  1.1302 +	case RPipe::ECancelDataAvailable:
  1.1303 +		return (iRequestType==RPipe::EDataAvailable);
  1.1304 +	case RPipe::ECancelSpaceAvailable:
  1.1305 +		return (iRequestType==RPipe::ESpaceAvailable);
  1.1306 +	case RPipe::ECancelWaitNotification:
  1.1307 +		return (iRequestType==RPipe::EWaitNotification);
  1.1308 +	default:
  1.1309 +		return EFalse;
  1.1310 +	}
  1.1311 +}
  1.1312 +
  1.1313 +void DPipeChannel::CancelRequest ( TInt aReqType)
  1.1314 +/**
  1.1315 +Cancels an outstanding space available notifier request.
  1.1316 +
  1.1317 +@param 	aReqType A number identifying the  message type
  1.1318 +
  1.1319 +@return  None
  1.1320 +*/
  1.1321 +{
  1.1322 +	TAutoWait<DMutex> autoMutex(iData->Mutex() );
  1.1323 +	if(iClientRequest->StatusPtr() && ValidCancellation(aReqType))
  1.1324 +		{
  1.1325 +		switch(aReqType)
  1.1326 +			{
  1.1327 +			case RPipe::ECancelDataAvailable:
  1.1328 +				iData->CancelDataAvailable();			
  1.1329 +				break;
  1.1330 +			
  1.1331 +			case RPipe::ECancelSpaceAvailable:
  1.1332 +				iData->CancelSpaceAvailable();
  1.1333 +				break;
  1.1334 +		
  1.1335 +			case RPipe::ECancelWaitNotification:
  1.1336 +				iData->CancelWaitNotifier();
  1.1337 +				break;
  1.1338 +	
  1.1339 +			default:
  1.1340 +				FAULT();
  1.1341 +			}
  1.1342 +		Kern::QueueRequestComplete(iRequestThread, iClientRequest, KErrCancel);
  1.1343 +		// Close our reference on the client thread
  1.1344 +		Kern::SafeClose((DObject*&)iRequestThread,NULL);
  1.1345 +		iRequestThread = NULL;
  1.1346 +		}
  1.1347 +	return;	
  1.1348 +	}
  1.1349 +
  1.1350 +
  1.1351 +TInt DPipeChannel::Size()
  1.1352 +/**
  1.1353 +Returns the size of the Pipe's buffer
  1.1354 +
  1.1355 +@param None
  1.1356 +
  1.1357 +@return TInt	Return the size of the pipe, otherwise one of the other system wide 
  1.1358 +				error code.
  1.1359 +*/	{
  1.1360 +	if(!iData)
  1.1361 +		return KErrNotReady;
  1.1362 +	else
  1.1363 +		return iData->Size();
  1.1364 +	}
  1.1365 +
  1.1366 +    
  1.1367 +void DPipeChannel::Flush()
  1.1368 +/*
  1.1369 +Flush the content of the pipe
  1.1370 +
  1.1371 +@param	None
  1.1372 +@pre   Must be in a critical section.
  1.1373 +@return	None
  1.1374 +
  1.1375 +*/	{
  1.1376 +	//The flush is, in effect, a read where the data is ignored
  1.1377 +	TAutoWait<DMutex> autoMutex(*iData->iReadMutex);
  1.1378 +
  1.1379 +	iData->Wait();
  1.1380 +	iData->FlushPipe();
  1.1381 +	iData->Signal();
  1.1382 +	}
  1.1383 +	
  1.1384 +
  1.1385 +// Called from the DPipe  
  1.1386 +	
  1.1387 +void DPipeChannel::DoRequestCallback()
  1.1388 +/**
  1.1389 +It is called from the DPipe to complete the Outstanding request
  1.1390 +
  1.1391 +@param None
  1.1392 +
  1.1393 +@return None
  1.1394 +*/
  1.1395 +	{
  1.1396 +	__ASSERT_MUTEX(&iData->Mutex());
  1.1397 +	__NK_ASSERT_DEBUG(iRequestThread);
  1.1398 +	Kern::QueueRequestComplete(iRequestThread, iClientRequest, KErrNone);
  1.1399 +	Kern::SafeClose((DObject*&)iRequestThread,NULL);
  1.1400 +	iRequestThread=NULL;
  1.1401 +	}
  1.1402 +
  1.1403 +
  1.1404 +
  1.1405 +// DPipe the Kernel side pipe representing class
  1.1406 +
  1.1407 +DPipe::~DPipe()
  1.1408 +/**
  1.1409 +Destructor
  1.1410 +*/
  1.1411 +	{
  1.1412 +	delete iBuffer;
  1.1413 +	if (iPipeMutex)
  1.1414 +		iPipeMutex->Close(NULL);
  1.1415 +	if (iReadMutex)
  1.1416 +		iReadMutex->Close(NULL);
  1.1417 +	if(iWriteMutex)
  1.1418 +		iWriteMutex->Close(NULL);
  1.1419 +	}
  1.1420 +	
  1.1421 +
  1.1422 +// Creates a Named pipe
  1.1423 +DPipe* DPipe::CreatePipe(const TDesC& aName, TInt aSize, TAny *aPolicy)
  1.1424 +/**
  1.1425 +Static method to Create a Named pipe. 
  1.1426 +@param	aName		Reference to the Name to be set to the current named pipe.
  1.1427 +@param	aSize		Size of the Pipe.
  1.1428 +@param TAny			Pointer to TSecurityPolicy passed as void pointer
  1.1429 +
  1.1430 +@return DPipe*  	Reference to DPipe* instance if successful, otherwise NULL
  1.1431 +*/
  1.1432 +	{
  1.1433 +
  1.1434 +	DPipe* tmp = new DPipe;
  1.1435 +	if (!tmp)
  1.1436 +		{
  1.1437 +		return NULL;
  1.1438 +		}
  1.1439 +	if(tmp->ConstructPipe(aName, aSize, aPolicy)!= KErrNone)
  1.1440 +		{
  1.1441 +		delete tmp;
  1.1442 +		return NULL;
  1.1443 +		}
  1.1444 +	return tmp;
  1.1445 +	}
  1.1446 +	
  1.1447 +	
  1.1448 +TInt DPipe::ConstructPipe(const TDesC& aName, TInt aSize,TAny* aPolicy)
  1.1449 +/**
  1.1450 +Second phase constructor
  1.1451 +
  1.1452 +@param	aName		The name of the pipe to be created
  1.1453 +@param	aSize		The size of the pipe to be created
  1.1454 +@param TAny			Pointer to TSecurityPolicy passed as void pointer
  1.1455 +
  1.1456 +@return KErrNone	If successful, otherwise one of the other system wide error code
  1.1457 +*/
  1.1458 +	{
  1.1459 +	// check the size parameter.
  1.1460 +	if(aPolicy)
  1.1461 +		{
  1.1462 +		
  1.1463 +		memcpy(&iPolicy,aPolicy,sizeof(TSecurityPolicy));
  1.1464 +		
  1.1465 +		}
  1.1466 +	else
  1.1467 +		{
  1.1468 +		TSecurityPolicy apolicy(ECapability_None);
  1.1469 +		memcpy(&iPolicy,&apolicy,sizeof(TSecurityPolicy));
  1.1470 +		}
  1.1471 +
  1.1472 +	if(aName.Length() != 0)
  1.1473 +		{
  1.1474 +		iName.Copy(aName);	
  1.1475 +		}
  1.1476 +		
  1.1477 +	iBuffer = static_cast<TUint8*>(Kern::AllocZ(aSize));
  1.1478 +	if(!iBuffer)
  1.1479 +		return KErrNoMemory;
  1.1480 +		
  1.1481 +	// Initialisation
  1.1482 +	_LIT(KMutexName,"PipeMutex");
  1.1483 +	TInt err = Kern::MutexCreate(iPipeMutex, KMutexName, KMutexOrdGeneral0);
  1.1484 +	if (err)
  1.1485 +		{
  1.1486 +		return err;
  1.1487 +		}
  1.1488 +	_LIT(KReadMutex,"ReadMutex");
  1.1489 +	err = Kern::MutexCreate(iReadMutex, KReadMutex, KMutexOrdGeneral1);
  1.1490 +	if (err)
  1.1491 +		{
  1.1492 +		return err;
  1.1493 +		}
  1.1494 +
  1.1495 +	_LIT(KWriteMutex,"WriteMutex");
  1.1496 +	err = Kern::MutexCreate(iWriteMutex, KWriteMutex, KMutexOrdGeneral1);
  1.1497 +	if (err)
  1.1498 +		{
  1.1499 +		return err;
  1.1500 +		}
  1.1501 +
  1.1502 +	iSize = aSize;
  1.1503 +	iWritePointer = iReadPointer = 0;
  1.1504 +	iFull = EFalse;	
  1.1505 +	return KErrNone;		
  1.1506 +	}	
  1.1507 +
  1.1508 +
  1.1509 +TInt DPipe::OpenId()
  1.1510 +/**
  1.1511 +Returns the id of the Pipe
  1.1512 +
  1.1513 +@param	None
  1.1514 +
  1.1515 +@return iID			 ID of the pipe
  1.1516 +*/
  1.1517 +	{
  1.1518 +	//could be const
  1.1519 +	return iID;
  1.1520 +	}
  1.1521 +
  1.1522 +
  1.1523 +void DPipe::SetId(TInt aId)
  1.1524 +/**
  1.1525 +Set the id of the Pipe
  1.1526 +
  1.1527 +@param 	aId		 	The id to be set 
  1.1528 +
  1.1529 +@return None
  1.1530 +*/
  1.1531 +	{
  1.1532 +	//this is only called by the pipe device
  1.1533 +	//it could also be set at construction time
  1.1534 +	iID = aId;	
  1.1535 +	}
  1.1536 +
  1.1537 +
  1.1538 +TBool DPipe::IsPipeClosed()
  1.1539 +/**
  1.1540 +Check if the Pipe is Closed.
  1.1541 +@param	None
  1.1542 +@return TBool		ETure if Successful, otherwise EFalse;
  1.1543 +*/
  1.1544 +	{
  1.1545 +	__ASSERT_MUTEX(iPipeMutex);
  1.1546 +
  1.1547 +	return !(iReadChannel || iWriteChannel);
  1.1548 +	}
  1.1549 +
  1.1550 +
  1.1551 +TBool DPipe::MatchName(const TDesC8* aName)
  1.1552 +/**
  1.1553 +Check if the current instance of DPipe Name is matching with aName parameter
  1.1554 +
  1.1555 +@param	aName		Name to be checked with the current DPipe's name.
  1.1556 +
  1.1557 +@return TBool	  	ETrue if match found, otherwise EFalse
  1.1558 +*/
  1.1559 +	{
  1.1560 +	//name could be const
  1.1561 + 	return (iName.Compare(*aName) == 0);
  1.1562 +	}
  1.1563 +	
  1.1564 +
  1.1565 +TBool DPipe::MatchId(const TInt aId)
  1.1566 +/**
  1.1567 +Checks if the current instance of DPipe is matching with the aId parameter
  1.1568 +
  1.1569 +@param	aId	 		ID to be checked with the current DPipe's id
  1.1570 +
  1.1571 +@return TBool		ETure if match found , otherwise EFalse;
  1.1572 +*/
  1.1573 +	{
  1.1574 +	return (iID == aId);
  1.1575 +	}
  1.1576 +
  1.1577 +
  1.1578 +TBool DPipe::IsBufferEmpty()
  1.1579 +/**
  1.1580 +Checks if the Buffer is Empty
  1.1581 +
  1.1582 +@param   None
  1.1583 +@return ETrue if buffer is empty
  1.1584 +*/
  1.1585 +	{
  1.1586 +	return (AvailableDataCount()==0);
  1.1587 +	}
  1.1588 +
  1.1589 +
  1.1590 +TInt DPipe::Write(TAny* aBuf, TInt aSize)
  1.1591 +/**
  1.1592 +Synchronous, non-blocking write operation. If the pipe is full it will 
  1.1593 +return immediately with KErrOverflow. A successful DPipe::Write() operation will
  1.1594 +return amount of data written to the pipe.If a request status object has been registered
  1.1595 +for Data Available notification, it will complete.
  1.1596 +
  1.1597 +@param	aBuf		Buffer from which data need to be written to the pipe.
  1.1598 +@param	aSize		Amount of data to be written to the pipe.
  1.1599 +	 
  1.1600 +@return >0			 Amount of data written to the pipe, in octets.
  1.1601 +		KErrNone	 No data written to the pipe.
  1.1602 +		KErrOverflow Pipe is full, cannot write any more data. 
  1.1603 +		KErrArgument If the amount of data to be written is invalid.
  1.1604 +					 Otherwise one of the other system wide error code
  1.1605 +
  1.1606 +@pre iPipeMutex held
  1.1607 +@pre iWriteMutex held
  1.1608 +
  1.1609 +@note Write enters and exists with the pipe mutex held - but releases and reaquires internally
  1.1610 +*/
  1.1611 +	{
  1.1612 +	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::Write(aBuf=0x%08x, aSize=%d)", aBuf, aSize));
  1.1613 +	
  1.1614 +	__ASSERT_MUTEX(iPipeMutex);
  1.1615 +	__ASSERT_MUTEX(iWriteMutex);
  1.1616 +	// Check for the Invalid  Length
  1.1617 +	if(aSize < 0)
  1.1618 +		{
  1.1619 +		return KErrArgument;
  1.1620 +		}
  1.1621 +
  1.1622 +	if(aSize == 0)
  1.1623 +		{
  1.1624 +		return KErrNone;
  1.1625 +		}
  1.1626 +	
  1.1627 +	//Since only one thread can be writing to the write end
  1.1628 +	//of a pipe it is sufficient that AvailableDataCount
  1.1629 +	//holds the pipe mutex. After it returns the 
  1.1630 +	//available space may increase
  1.1631 +	//but can not decrease
  1.1632 +	const TInt spaceavailable = (iSize - AvailableDataCount());
  1.1633 +	if (spaceavailable < aSize)
  1.1634 +		{
  1.1635 +		//Though the API may suggest otherwise - partial writes are not supported.
  1.1636 +		return KErrOverflow;
  1.1637 +		}
  1.1638 +		
  1.1639 +	//release mutex before IPC read
  1.1640 +	Signal();
  1.1641 +
  1.1642 +	//First half
  1.1643 +	const TDesC8*  pBuf = (const TDesC8*)aBuf;
  1.1644 +
  1.1645 +	const TInt distanceToEnd =  iSize - iWritePointer;
  1.1646 +	const TInt firstHalf = Min(distanceToEnd, aSize);
  1.1647 +	TPtr ptr(&iBuffer[iWritePointer], firstHalf);
  1.1648 +
  1.1649 +	DThread* const currThread = &Kern::CurrentThread();
  1.1650 +	TInt r=Kern::ThreadDesRead(currThread, pBuf, ptr, 0, KChunkShiftBy0);
  1.1651 +	if(r!=KErrNone)
  1.1652 +		{
  1.1653 +		Wait(); //we must exit with mutex held
  1.1654 +		return r;
  1.1655 +		}
  1.1656 +
  1.1657 +	//Second half
  1.1658 +	const TInt secondHalf = aSize - firstHalf;
  1.1659 +	__NK_ASSERT_DEBUG( secondHalf >= 0);
  1.1660 +	if(secondHalf != 0)	
  1.1661 +		{
  1.1662 +		ptr.Set(&iBuffer[0], secondHalf, secondHalf);
  1.1663 +
  1.1664 +		r = Kern::ThreadDesRead(currThread, pBuf, ptr, firstHalf, KChunkShiftBy0);
  1.1665 +		if(r!=KErrNone)
  1.1666 +			{
  1.1667 +			Wait(); //we must exit with mutex held
  1.1668 +			return r;
  1.1669 +			}
  1.1670 +		}
  1.1671 +	
  1.1672 +	Wait(); //reaquire mutex for state update
  1.1673 +	iWritePointer = (iWritePointer + aSize)% iSize;	
  1.1674 +		
  1.1675 +	if(iWritePointer == iReadPointer)
  1.1676 +		{
  1.1677 +		iFull = ETrue;
  1.1678 +		}
  1.1679 +		
  1.1680 +	if(iDataAvailableRequest)
  1.1681 +		{
  1.1682 +		iReadChannel->DoRequestCallback();
  1.1683 +		iDataAvailableRequest = EFalse;		
  1.1684 +		}
  1.1685 +
  1.1686 +	return aSize;
  1.1687 +	}
  1.1688 +
  1.1689 +
  1.1690 +TInt DPipe::Read(TAny* aBuf, TInt aSize)
  1.1691 +/**
  1.1692 +Synchronous, non-blocking read operation. If the pipe is empty it will 
  1.1693 +return immediately with KErrUnderflow. A successful DPipe::Read() operation 
  1.1694 +will free up more space in the pipe. If a request status object has been registered
  1.1695 +for Space Available notification, it will complete. Note that there is no 
  1.1696 +guarantee that the amount of space freed up in the pipe will be sufficient 
  1.1697 +for the next DPipe::Write() operation.
  1.1698 +
  1.1699 +@param	aBuff		Buffer to which data need to be written.
  1.1700 +@param	aSize		Size of the data to be read from the pipe.
  1.1701 +
  1.1702 +@return	>0			 Amount of data read from the pipe, in octets.
  1.1703 +		KErrNone	 The pipe is empty , no data was read from the pipe.
  1.1704 +		KErrArgument If the amount of data to be read is invalid.
  1.1705 +					 Otherwise one of the system wide error code
  1.1706 +@pre iPipeMutex held
  1.1707 +@pre iReadMutex held
  1.1708 +
  1.1709 +@note Read enters and exists with the pipe mutex held - but releases and reaquires internally
  1.1710 +*/
  1.1711 +	{	
  1.1712 +	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::Read(aBuf=0x%08x, aSize=%d)", aBuf, aSize));
  1.1713 +	__ASSERT_MUTEX(iPipeMutex);
  1.1714 +	__ASSERT_MUTEX(iReadMutex);
  1.1715 +		
  1.1716 +	if(aSize < 0)
  1.1717 +		{
  1.1718 +		return KErrArgument;
  1.1719 +		}
  1.1720 +	
  1.1721 +	const TInt totalToRead = Min(AvailableDataCount(), aSize);
  1.1722 +	
  1.1723 +
  1.1724 +	if(totalToRead == 0)
  1.1725 +		return 0;
  1.1726 +
  1.1727 +	Signal();
  1.1728 +
  1.1729 +
  1.1730 +	//! First half	
  1.1731 +	const TInt distanceToEnd = iSize - iReadPointer;
  1.1732 +	__NK_ASSERT_DEBUG(distanceToEnd>=0);
  1.1733 +	const TInt firstHalf = Min(totalToRead, distanceToEnd);
  1.1734 +
  1.1735 +	TPtrC8 pipeBuffer(&iBuffer[iReadPointer], firstHalf);
  1.1736 +	TDes8* userBuffer = (TDes8*)aBuf;
  1.1737 +
  1.1738 +	DThread* const currThread = &Kern::CurrentThread();
  1.1739 +	TInt r = Kern::ThreadDesWrite(currThread, userBuffer, pipeBuffer, 0, KChunkShiftBy0, NULL); 
  1.1740 +	if(r!=KErrNone)
  1.1741 +		{
  1.1742 +		Wait(); //we must exit with mutex held
  1.1743 +		return r;
  1.1744 +		}
  1.1745 +	
  1.1746 +	const TInt secondHalf=totalToRead-firstHalf;
  1.1747 +	__NK_ASSERT_DEBUG(secondHalf>=0);
  1.1748 +	if(secondHalf!=0)
  1.1749 +		{
  1.1750 +	    //! Second half
  1.1751 +		pipeBuffer.Set(&iBuffer[0], secondHalf);
  1.1752 +		r = Kern::ThreadDesWrite(currThread, userBuffer, pipeBuffer, firstHalf, KChunkShiftBy0, NULL);
  1.1753 +		if(r!=KErrNone)
  1.1754 +			{
  1.1755 +			Wait(); //we must exit with mutex held
  1.1756 +			return r;
  1.1757 +			}
  1.1758 +		}
  1.1759 +	__NK_ASSERT_DEBUG(firstHalf+secondHalf==totalToRead);
  1.1760 +
  1.1761 +	Wait(); //Reaquire mutex for state update
  1.1762 +
  1.1763 +	iReadPointer = (iReadPointer + totalToRead)% iSize;
  1.1764 +	iFull = EFalse;
  1.1765 +	MaybeCompleteSpaceNotification();
  1.1766 +		
  1.1767 +	__ASSERT_MUTEX(iReadMutex);
  1.1768 +	return totalToRead;			
  1.1769 +	}
  1.1770 +
  1.1771 +TInt DPipe::AvailableDataCount()
  1.1772 +/**
  1.1773 +Returns the Data available in the pipe. 
  1.1774 +
  1.1775 +@param	None
  1.1776 +
  1.1777 +@return TInt  Amount of data available in the pipe
  1.1778 +
  1.1779 +*/
  1.1780 +	{
  1.1781 +	__ASSERT_MUTEX(iPipeMutex);
  1.1782 +	TInt size=-1;
  1.1783 +	if ( iWritePointer > iReadPointer )
  1.1784 +		{
  1.1785 +		size = iWritePointer - iReadPointer;
  1.1786 +		}
  1.1787 +	else if ( iReadPointer > iWritePointer )
  1.1788 +		{
  1.1789 +		size = iSize - iReadPointer + iWritePointer;
  1.1790 +		}
  1.1791 +	else 
  1.1792 +		{
  1.1793 +		//iReadPointer == iWritePointer
  1.1794 +		size = iFull ? iSize : 0;
  1.1795 +		}
  1.1796 +	return size;
  1.1797 +	}
  1.1798 +
  1.1799 +TInt DPipe::RegisterSpaceAvailableNotification(TInt aSize)
  1.1800 +/**
  1.1801 +Registers the request status object to be completed when space becomes 
  1.1802 +available in the pipe. 
  1.1803 +
  1.1804 +@param	aSize			The size for which the space availability be notified.
  1.1805 +
  1.1806 +@return KErrNone		Success.
  1.1807 +	    KErrCompletion	The request is not registered as it completes immediately
  1.1808 +	    				otherwise one of the system wide error code.
  1.1809 +@pre   Mutex must be held.
  1.1810 +@pre   Must be in a critical section.
  1.1811 +*/
  1.1812 +	{
  1.1813 +	__ASSERT_MUTEX(iPipeMutex);
  1.1814 +	__NK_ASSERT_DEBUG(Rng(1, aSize, iSize));
  1.1815 +
  1.1816 +	// Check if Specified size is available.
  1.1817 +	TInt err = KErrNone;
  1.1818 +	if ((aSize <= (iSize - AvailableDataCount())))
  1.1819 +		{
  1.1820 +		iSpaceAvailableRequest = EFalse;
  1.1821 +		err = KErrCompletion;
  1.1822 +		}
  1.1823 +	else
  1.1824 +		{
  1.1825 +		iSpaceAvailableSize  = aSize;
  1.1826 +		iSpaceAvailableRequest = ETrue;	
  1.1827 +		}
  1.1828 +    return err;
  1.1829 +	}
  1.1830 +
  1.1831 +
  1.1832 +TInt DPipe::RegisterDataAvailableNotification()
  1.1833 +/**
  1.1834 +Registers the request status object to be completed when data becomes 
  1.1835 +available in the pipe. 
  1.1836 +
  1.1837 +@param	None
  1.1838 +
  1.1839 +@return KErrNone	If successful, otherwise one of the other system wide
  1.1840 +					error code.
  1.1841 +@pre   Mutex must be held.
  1.1842 +@pre   Must be in a critical section.
  1.1843 +*/
  1.1844 +	{
  1.1845 +	__ASSERT_MUTEX(iPipeMutex);
  1.1846 +
  1.1847 +	TInt err = KErrNone;
  1.1848 +	// Check if Data is available.
  1.1849 +	if(AvailableDataCount())
  1.1850 +		{
  1.1851 +		iDataAvailableRequest = EFalse;
  1.1852 +		err = KErrCompletion;
  1.1853 +		}
  1.1854 +	else
  1.1855 +		{
  1.1856 +		iDataAvailableRequest = ETrue;
  1.1857 +		}	
  1.1858 + 	return err;
  1.1859 +	}
  1.1860 +
  1.1861 +
  1.1862 +TInt DPipe::RegisterWaitNotification(TInt aChoice)	
  1.1863 +/**
  1.1864 +Registers the request status object to be completed when other end of the pipe
  1.1865 +is opened for reading. This method completes immediately if the other end of the
  1.1866 +pipe is already opened.
  1.1867 +
  1.1868 +@param 	None
  1.1869 +
  1.1870 +@return KErrNone	Successfully registered, otherwise one of the other system wide
  1.1871 +					error code.
  1.1872 +@pre Mutex must be held.
  1.1873 +@pre Must be in a critical section.
  1.1874 +*/
  1.1875 +	{
  1.1876 +	__ASSERT_MUTEX(iPipeMutex);
  1.1877 +
  1.1878 +	TInt err = KErrNone;
  1.1879 +	// Check if Read end is opened
  1.1880 +	if (aChoice == RPipe::EWaitForReader) 
  1.1881 +		{
  1.1882 +		if(IsReadEndOpened())
  1.1883 +			{	
  1.1884 +			iWaitRequest = EFalse;
  1.1885 +			err = KErrCompletion;
  1.1886 +			}
  1.1887 +		else
  1.1888 +			{
  1.1889 +			iWaitRequest = ETrue;
  1.1890 +			}	
  1.1891 +			
  1.1892 +		}
  1.1893 +	else 
  1.1894 +		{
  1.1895 +		if(IsWriteEndOpened())
  1.1896 +			{	
  1.1897 +			iWaitRequest = EFalse;
  1.1898 +			err = KErrCompletion;
  1.1899 +			}
  1.1900 +		else
  1.1901 +			{
  1.1902 +			iWaitRequest = ETrue;
  1.1903 +			}	
  1.1904 +		}
  1.1905 +	
  1.1906 +	return err;
  1.1907 +	}
  1.1908 +
  1.1909 +
  1.1910 +//! Cancellation methods
  1.1911 +void DPipe::CancelSpaceAvailable()
  1.1912 +/**
  1.1913 +Cancels an outstanding space available notifier request.
  1.1914 +
  1.1915 +@param  None
  1.1916 +
  1.1917 +@return None
  1.1918 +*/
  1.1919 +	{	
  1.1920 +	__ASSERT_MUTEX(iPipeMutex);
  1.1921 +	if(iSpaceAvailableRequest)	
  1.1922 +		iSpaceAvailableRequest = EFalse;
  1.1923 +	}
  1.1924 +
  1.1925 +
  1.1926 +void DPipe::CancelDataAvailable()
  1.1927 +/**
  1.1928 +Cancels an outstanding data available notifier request.
  1.1929 +
  1.1930 +@param None
  1.1931 +
  1.1932 +@return None
  1.1933 +*/
  1.1934 +	{
  1.1935 +	__ASSERT_MUTEX(iPipeMutex);
  1.1936 +	if(iDataAvailableRequest)
  1.1937 +		iDataAvailableRequest = EFalse;
  1.1938 +	}
  1.1939 +
  1.1940 +
  1.1941 +void DPipe::CancelWaitNotifier()
  1.1942 +/**
  1.1943 +Cancel an outstanding wait notifier request
  1.1944 +
  1.1945 +@param	None
  1.1946 +
  1.1947 +@return	KErrNone		If Successful, otherwise one of the other system wide error code.
  1.1948 +	
  1.1949 +*/
  1.1950 +	{
  1.1951 +	__ASSERT_MUTEX(iPipeMutex);
  1.1952 +	// Cancel Wait Notifier request
  1.1953 +	if(iWaitRequest)
  1.1954 +		iWaitRequest = EFalse;
  1.1955 +	}
  1.1956 +
  1.1957 +
  1.1958 +void DPipe::CloseAll()
  1.1959 +/**
  1.1960 +Cancel any outstanding request. 
  1.1961 +
  1.1962 +@param	 None
  1.1963 +
  1.1964 +@return  None
  1.1965 +*/
  1.1966 +	{
  1.1967 +	CancelSpaceAvailable();
  1.1968 +	CancelDataAvailable();
  1.1969 +	CancelWaitNotifier();
  1.1970 +	
  1.1971 +	CloseWriteEnd();
  1.1972 +  	CloseReadEnd(); 
  1.1973 +	}
  1.1974 +
  1.1975 +
  1.1976 +TInt DPipe::CloseReadEnd()
  1.1977 +/**
  1.1978 +Close the read end of the pipe.
  1.1979 +
  1.1980 +Cancels outstanding requests placed by the *write*
  1.1981 +channel and clears pipe's pointer to the read channel.
  1.1982 +If this function is called then the read channel's back
  1.1983 +pointer to the pipe must also be cleared.
  1.1984 +
  1.1985 +@param	None
  1.1986 +
  1.1987 +@return KErrNone 	If the end is closed, else  one  of the other system 
  1.1988 +					wide error code
  1.1989 +*/
  1.1990 +	{
  1.1991 +	__ASSERT_MUTEX(iPipeMutex);
  1.1992 +	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::CloseReadEnd ID=%d, iReadChannel=0x%08x", OpenId(), iReadChannel)); 
  1.1993 +
  1.1994 +	if (!iReadChannel)
  1.1995 +		return KErrCouldNotDisconnect;
  1.1996 +	else
  1.1997 +		{
  1.1998 +		if(iWriteChannel)
  1.1999 +			{
  1.2000 +			iWriteChannel->CancelRequest(RPipe::ECancelSpaceAvailable);	
  1.2001 +			}
  1.2002 +		iReadChannel = NULL;
  1.2003 +		}		
  1.2004 +	return KErrNone;
  1.2005 +	}
  1.2006 +
  1.2007 +
  1.2008 +TInt  DPipe::CloseWriteEnd()
  1.2009 +/**
  1.2010 +Close the write end of the pipe
  1.2011 +
  1.2012 +Cancels outstanding requests placed by the *read*
  1.2013 +channel and clears pipe's pointer to the write channel.
  1.2014 +If this function is called then the write channel's back
  1.2015 +pointer to the pipe must also be cleared.
  1.2016 +
  1.2017 +@param	None
  1.2018 +
  1.2019 +@return KErrNone 	If the write end is successfully closed, else
  1.2020 +	                one of the other system wide error code.
  1.2021 +*/
  1.2022 +	{
  1.2023 +	__ASSERT_MUTEX(iPipeMutex);
  1.2024 +	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::CloseWriteEnd ID=%d, iWriteChannel=0x%08x", OpenId(), iWriteChannel)); 
  1.2025 +
  1.2026 +	if (!iWriteChannel)
  1.2027 +		return KErrCouldNotDisconnect;
  1.2028 +	else
  1.2029 +		{
  1.2030 +		// Cancel RBlocking call if it is there
  1.2031 +		if(iReadChannel)
  1.2032 +			{
  1.2033 +			iReadChannel->CancelRequest(RPipe::ECancelDataAvailable);	
  1.2034 +			}
  1.2035 +		iWriteChannel = NULL;	
  1.2036 +		}
  1.2037 +	return KErrNone;				
  1.2038 +	}
  1.2039 +	
  1.2040 +	
  1.2041 +
  1.2042 +void DPipe::FlushPipe()
  1.2043 +/**
  1.2044 +Flush all the date from the pipe and reinitialise the buffer pointer.
  1.2045 +
  1.2046 +@param 	None
  1.2047 +
  1.2048 +@return None
  1.2049 +
  1.2050 +@pre 	Pipe Mutex to be held
  1.2051 +@pre 	Read Mutex to be held
  1.2052 +
  1.2053 +*/
  1.2054 +	{
  1.2055 +	__ASSERT_MUTEX(iPipeMutex);
  1.2056 +	__ASSERT_MUTEX(iReadMutex);
  1.2057 +
  1.2058 +	iReadPointer = iWritePointer;
  1.2059 +	iFull	= EFalse;
  1.2060 +	
  1.2061 +	MaybeCompleteSpaceNotification();	
  1.2062 +	}
  1.2063 +
  1.2064 +/**
  1.2065 +If there is an outstanding space request, and
  1.2066 +there is enough space to satisfy it then complete
  1.2067 +and clear request.
  1.2068 +
  1.2069 +@pre the pipe mutex must be held
  1.2070 +*/
  1.2071 +void DPipe::MaybeCompleteSpaceNotification()
  1.2072 +	{
  1.2073 +	__ASSERT_MUTEX(iPipeMutex);
  1.2074 +
  1.2075 +	// Check if there is writeblocking request
  1.2076 +	if(iSpaceAvailableRequest) 
  1.2077 +		{
  1.2078 +		const TInt spacecount = (iSize - AvailableDataCount());
  1.2079 +		if (iSpaceAvailableSize <= spacecount)
  1.2080 +			{
  1.2081 +			iWriteChannel->DoRequestCallback();
  1.2082 +			iSpaceAvailableRequest = EFalse;		
  1.2083 +			}	
  1.2084 +		}
  1.2085 +	}
  1.2086 +
  1.2087 +TBool DPipe::IsReadEndOpened()
  1.2088 +/**
  1.2089 +Returns information regarding the read end of the current pipe instance.
  1.2090 +
  1.2091 +@return TBool	ETrue if read end is Opened, otherwise EFalse
  1.2092 +@pre the pipe mutex must be held
  1.2093 +*/
  1.2094 +	{
  1.2095 +	__ASSERT_MUTEX(iPipeMutex);
  1.2096 +	return (iReadChannel != NULL);
  1.2097 +	}
  1.2098 +
  1.2099 +
  1.2100 +TBool DPipe::IsWriteEndOpened()
  1.2101 +/**
  1.2102 +Returns information regarding the write end of the current pipe instance.
  1.2103 +
  1.2104 +@return  TBool ETrue if WriteChannel is opened, otherwise EFalse
  1.2105 +@pre the pipe mutex must be held
  1.2106 +*/
  1.2107 +	{
  1.2108 +	__ASSERT_MUTEX(iPipeMutex);
  1.2109 +	return (iWriteChannel != NULL);
  1.2110 +	}
  1.2111 +
  1.2112 +
  1.2113 +TBool DPipe::IsNamedPipe()
  1.2114 +/**
  1.2115 +Returns whether the pipe is named or unnamed.
  1.2116 +
  1.2117 +@return TBool  ETrue if it is a named pipe, otherwise EFalse
  1.2118 +
  1.2119 +*/
  1.2120 +	{
  1.2121 +	return (iName.Length() != 0); 
  1.2122 +	}
  1.2123 +
  1.2124 +
  1.2125 +void DPipe::SetReadEnd(DPipeChannel* aChannel)
  1.2126 +/**
  1.2127 +Set the Read end of the pipe as opened and store the pointer for the read channel
  1.2128 +It also notify if there is any pending Wait Request.
  1.2129 +
  1.2130 +@param	aChannel	The pointer to the read channel
  1.2131 +
  1.2132 +@pre the pipe mutex must be held
  1.2133 +@pre The pipe's read end must be closed ie. IsReadEndOpened returns false
  1.2134 +*/
  1.2135 +	{
  1.2136 +	__ASSERT_MUTEX(iPipeMutex);
  1.2137 +	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::SetReadEnd ID=%d", OpenId())); 
  1.2138 +
  1.2139 +
  1.2140 +	//A channel must be sure this function
  1.2141 +	//succeeded otherwise the pipe
  1.2142 +	//could be destroyed without the channel's
  1.2143 +	//knowledge
  1.2144 +	__NK_ASSERT_DEBUG(iReadChannel==NULL);
  1.2145 +
  1.2146 +	iReadChannel = aChannel;
  1.2147 +	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::SetReadEnd set iReadChannel=0x%08x", iReadChannel)); 
  1.2148 +	
  1.2149 +	if(iWaitRequest)
  1.2150 +		{
  1.2151 +		if(iWriteChannel)
  1.2152 +			iWriteChannel->DoRequestCallback();
  1.2153 +		iWaitRequest=EFalse;
  1.2154 +		}
  1.2155 +	}
  1.2156 +	
  1.2157 +
  1.2158 +void DPipe::SetWriteEnd(DPipeChannel* aChannel)
  1.2159 +/**
  1.2160 +Set the write end of the pipe as opened and store the pointer to the write channel
  1.2161 +
  1.2162 +@param aChannel		The pointer to the write channel
  1.2163 +
  1.2164 +
  1.2165 +@pre the pipe mutex must be held
  1.2166 +@pre The pipe's write end must be closed ie. IsWriteEndOpened returns false
  1.2167 +*/
  1.2168 +	{
  1.2169 +	__ASSERT_MUTEX(iPipeMutex);
  1.2170 +	__KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::SetWriteEnd ID=%d", OpenId())); 
  1.2171 +
  1.2172 +	//A channel must be sure this function
  1.2173 +	//succeeded otherwise the pipe
  1.2174 +	//could be destroyed without the channel's
  1.2175 +	//knowledge
  1.2176 +	__NK_ASSERT_DEBUG(iWriteChannel==NULL);
  1.2177 +
  1.2178 +	iWriteChannel = aChannel;
  1.2179 +	__KTRACE_OPT(KPIPE, Kern::Printf("DPipe::SetWriteEnd set iWriteChannel=0x%08x", iWriteChannel)); 
  1.2180 +
  1.2181 +	if(iWaitRequest)
  1.2182 +		{
  1.2183 +		if(iReadChannel)
  1.2184 +			iReadChannel->DoRequestCallback();
  1.2185 +		iWaitRequest=EFalse;
  1.2186 +		}		
  1.2187 +	}
  1.2188 +
  1.2189 +TInt DPipe::Size()
  1.2190 +/**
  1.2191 +@return The size of the pipe's circular buffer 
  1.2192 +*/
  1.2193 +	{
  1.2194 +	//this could be const
  1.2195 +	return iSize;	
  1.2196 +	}
  1.2197 +