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