Update contrib.
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <kernel/kern_priv.h>
20 //_LIT(KPipePanicCategory,"PipePanic");
21 const TInt KPipeGranularity = 8;
23 DECLARE_STANDARD_LDD()
25 Standard export function for LDDs. This creates a DLogicalDevice derived
26 object, in this case our DPipeDevice
29 return new DPipeDevice;
32 DPipeDevice::DPipeDevice()
34 DPipeDevice Constructor has minimal implementation such setting the version number
35 Indicate the use of unit number
45 iVersion = RPipe::VersionRequired();
49 DPipeDevice::~DPipeDevice()
51 // Delete the existing pipes
52 for(TInt count = 0; count<iCount; count++)
54 DPipe* pipe=iDpipes[count];
64 TInt DPipeDevice::Install()
66 Second stage constructor and at least set a name for the
67 driver object. Inherited from DLogicalDevice. This must at least set a name
68 for the driver object.
72 @return KErrNone If successful, otherwise one of the system wide error codes.
75 _LIT(KMutexName,"PipeDeviceMutex");
76 TInt err = Kern::MutexCreate(iMutex, KMutexName, KMutexOrdGeneral1);
82 return SetName(&RPipe::Name());
86 void DPipeDevice::GetCaps(TDes8& aDes) const
88 Returns the driver capabilities. Called in the response to
89 an RPipe::GetCaps() request
91 @param aDes Descriptor into which capabilities information
96 // Write it back to user memory
99 Kern::InfoCopy(aDes,(TUint8*)&version, sizeof(version));
103 TInt DPipeDevice::Create(DLogicalChannelBase*& aChannel)
105 Called by the kernel's device driver framework to create a Logical Channel.
106 This is called in the context of the user thread (client) which requested the
107 creation of the Logical Channel.
109 @param aChannel Set to point to the created logical channel
111 @return KErrNone If successful, otherwise system one of the other
115 aChannel = new DPipeChannel;
122 TInt DPipeDevice::CreatePipe(const TDesC& aName, TInt aSize, DPipe*& aPipe, TAny* aCap)
124 Called by DPipeChannel instance to create named DPipe object and
125 associate itself with the newly created named DPipe instance.
127 @param aName name need to be attached to the newly created DPipe object.
128 @param aSize size of the DPipe object.
129 @param aPipe Pointer to DPipe, If successful set the pointer to newly created DPipe instance else NULL
130 @param aCap Pointer to TSecuritypolicy passed as void pointer
132 @return KErrNone If successful, otherwise one of the other system wide error code
133 @pre Calling thread must be in a critical section.
134 @pre Mutex must be held
137 __ASSERT_MUTEX(iMutex);
138 __KTRACE_OPT(KPIPE, Kern::Printf(">DPipeDevice::CreatePipe"));
140 DPipe** pS = iDpipes;
141 DPipe** pE = pS + iCount;
145 if((pO->MatchName(&aName)))
147 err = KErrAlreadyExists;
153 DPipe* pipe = DPipe::CreatePipe(aName, aSize, aCap);
171 __KTRACE_OPT(KPIPE, Kern::Printf("<DPipeDevice::CreatePipe ret=%d", err));
176 DPipe* DPipeDevice::CreatePipe(TInt aSize)
178 Called by DPipeChannel instance to create un-named DPipe instance and
179 associate itself with the newly created un-named DPipe instance.
181 @param aSize size of the DPipe object.
183 @return DPipe* If successful, otherwise NULL
184 @pre Mutex must be held
185 @pre In critical section
189 __ASSERT_MUTEX(iMutex);
191 DPipe* pipe = DPipe::CreatePipe(aName, aSize);
197 TInt r = AddPipe(pipe);
208 TInt DPipeDevice::AddPipe(DPipe* aObj)
210 Add an instance of Dpipe to the array.
211 @param aObj Pointer to DPipe object
212 @return KErrNone If the call is successful otherwise one of the other
213 system wide error code.
215 @pre Calling thread must be in a critical section.
216 @pre Mutex to be held
219 __ASSERT_CRITICAL; //otherwise iDPipes and iCount could go out of sync
220 __ASSERT_MUTEX(iMutex);
221 // store the current instance to the array
222 if(iCount == iAllocated)
224 TInt newAlloc = iAllocated + KPipeGranularity;
225 TInt r = Kern::SafeReAlloc((TAny*&)iDpipes, iCount * sizeof(DPipe*), newAlloc * sizeof(DPipe*));
230 iAllocated = newAlloc;
232 TInt id = GenerateId();
234 iDpipes[iCount++]= aObj;
236 __KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::AddPipe Pipe added ID=%d", id));
242 void DPipeDevice::RemovePipe(DPipe** aObj)
244 Remove an instance of DPipe from the array
246 @param Pointer to Dpipe Array
250 @pre Calling thread must not be in a critical section.
251 @pre Mutex to be held
254 __ASSERT_MUTEX(iMutex);
255 __ASSERT_CRITICAL; //we don't want to leave the array inconsistant
257 DPipe** pE = (iDpipes + iCount) - 1;
260 //bump along array elements to close the gap
261 wordmove((TAny*)aObj, (TAny*)(aObj+1), TInt(pE)- TInt(aObj));
264 if(iCount % KPipeGranularity == 0)
266 Kern::SafeReAlloc((TAny*&)iDpipes, iAllocated*sizeof(DPipe*), iCount* sizeof(DPipe*));
272 DPipe* DPipeDevice::FindNamedPipe(const TDesC* aName)
274 Called by the DPipeChannel to check if a named DPipe instance exist with a name
275 as specified by aName parameter.
277 @param aName The name of the DPipe instance to search for.
279 @return DPipe* If successful, otherwise NULL
281 @pre Device mutex to be held
284 __ASSERT_MUTEX(iMutex);
285 DPipe** pS = iDpipes;
286 DPipe** pE = pS + iCount;
291 if(pO->MatchName(aName))
299 DPipe* DPipeDevice::FindUnnamedPipe(const TInt aId)
301 Called by the DPipeChannel to check if an un-named DPipe instance exist with an ID
302 as specified by aId parameter.
304 @param aId The ID of the DPipe instance to search for.
306 @return DPipe* If successful, otherwise NULL
307 @pre Device mutex to be held
310 __ASSERT_MUTEX(iMutex);
311 DPipe** pS = iDpipes;
312 DPipe** pE = pS + iCount;
324 TInt DPipeDevice::Destroy(const TDesC* aName)
326 This method is called to destroy a named DPipe instance. The caller needs to have
327 sufficient capabilities to delete a named pipe. This method will fail if there are
328 any handles still open on the pipe.
330 @param aName Name of the DPipe instance to be deleted.
332 @return KErrNone If successful, otherwise one of the other system wide error.
336 TAutoWait<DMutex> autoMutex(*iMutex);
337 DPipe** pS = iDpipes;
338 DPipe** pE = pS + iCount;
339 TInt err = KErrNotFound;
345 if(((*pO)->MatchName(aName)))
350 if(!(pipe->GetCap()->CheckPolicy(&Kern::CurrentThread())))
352 err = KErrPermissionDenied;
356 // Check if any handles still opened on the pipe.
358 if (!pipe->IsPipeClosed())
361 pipe->Signal(); //need to signal if we won't be destroying pipe
364 __KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Destroy remove ID=%d", pipe->OpenId()));
365 delete iDpipes[count];
376 TInt DPipeDevice::Close(TInt aId)
378 This method is called to close both named and un-named DPipe. In case of un-named DPipe
379 if there is no further reference of a DPipeChannel exist, the corresponding un-named DPipe
382 @param aId ID of the pipe that need to be closed.
384 @return KErrNone If successful otherwise one of the other system wide error.
388 TAutoWait<DMutex> autoMutex(*iMutex);
389 DPipe** pS = iDpipes;
390 DPipe** pE = pS + iCount;
391 TInt err = KErrNotFound;
396 if(pipe->MatchId(aId))
398 __KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Close found ID=%d", pipe->OpenId()));
399 //even if we can't delete the pipe, we have
400 //found it so don't return KErrNotFound
405 // we can only delete an unamed pipe with both ends closed
406 if(!pipe->IsNamedPipe() && pipe->IsPipeClosed())
408 __KTRACE_OPT(KPIPE, Kern::Printf("DPipeDevice::Close remove ID=%d", pipe->OpenId()));
422 TInt DPipeDevice::GenerateId()
424 Generate a ID and store for a Named pipe while creating.
427 @return TInt ID for the name pipe
429 @pre Mutex to be held
433 __ASSERT_MUTEX(iMutex);
435 return (KIdBase + iIdindex);
439 DPipeChannel::DPipeChannel()
440 :iClientRequest(NULL), iData(NULL), iChannelType(RPipe::EChannelUnset)
448 DPipeChannel::~DPipeChannel()
455 Kern::DestroyClientRequest(iClientRequest); //null ptr is safe
460 TInt DPipeChannel::RequestUserHandle (DThread* aThread, TOwnerType aType)
462 Inherited from DObject. This method is called when a user thread requests
463 a handle to this channel. Minimal implantation here is capability check
465 @param aThread DThread instance reference that requests a handle to this channel.
466 @param aType Ownership type for the handle.
468 @return KErrNone If successful otherwise one the system wide error.
478 TInt DPipeChannel::DoCreate (TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
480 Inherited from DLogicalChannelBase class. This method represents the second stage
481 constructor called by the kernel's device driver framework. This is called in the
482 context of the user thread (client) which requested the creation of the Logical
483 Channel. The thread is in critical section.
485 @param aUnit The unit argument supplied by the client
486 @param aInfo The info argument supplied by the client
487 @param aVer The version argument supplied by the client
489 @return KErrNone If successful, otherwise one of the other system wide error codes.
496 if (!Kern::QueryVersionSupported(RPipe::VersionRequired(),aVer))
497 return KErrNotSupported;
499 TInt r = Kern::CreateClientRequest(iClientRequest);
510 TInt DPipeChannel::Request(TInt aReqNo, TAny* a1, TAny* a2)
512 Called by the Device driver framework upon user request. Stores the
513 Thread pointer under whose context this function is called.
515 @param aFunction A number identifying the message type
516 @param a1 A 32-bit Value passed by the user
517 @param a2 A 32-bit Value passed by the user
519 @return KErrNone If successful, otherwise one of the system wide error code
527 err = Kern::HalFunction(EHalGroupVM, EVMHalFlushCache, 0, 0);
534 if(aReqNo == KMaxTInt)
536 CancelRequest((TInt)a1);
542 TAny *array[2] = {0,0};
543 TRequestStatus * pStat = (TRequestStatus*)a1;
544 kumemget32(&array[0], a2, 2*sizeof(TAny*));
545 err = DoRequest(~aReqNo, pStat, array[0], array[1]);
547 Kern::RequestComplete(pStat, err);
553 err = DoControl(aReqNo, a1, a2);
559 TInt DPipeChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
561 Processes Synchronous 'control' requests. This function is called to service
562 any synchronous calls through the user side RPipe handle.
564 @param aFunction A number identifying the message type
565 @param a1 A 32-bit Value passed by the user
566 @param a2 A 32-bit Value passed by the user
568 @return KErrNone If the call is successful, otherwise one of the other
577 case RPipe::EDefineNamedPipe:
578 return PipeCreate(a1, a2);
580 case RPipe::EOpenToReadNamedPipe:
581 return PipeOpen((const TDesC*)a1, RPipe::EReadChannel);
583 case RPipe::EOpenToWriteNamedPipe:
584 return PipeOpen((const TDesC*)a1, RPipe::EWriteChannel);
586 case RPipe::EOpenToWriteButFailOnNoReaderNamedPipe:
587 return OpenOnReader((const TDesC*)a1);
589 case RPipe::EDestroyNamedPipe:
590 return PipeDestroy((const TDesC*)a1);
592 case RPipe::ECreateUnNamedPipe:
593 kumemget((TAny*)&aSize, a1, sizeof(TInt));
594 return PipeCreate( aSize);
596 case RPipe::EOpenUnNamedPipe:
597 kumemget((TAny*)&aId, a1, sizeof(TInt));
598 return PipeOpen(aId);
601 kumemget((TAny*)&aSize, a2, sizeof(TInt));
602 return Read (a1, aSize);
605 kumemget((TAny*)&aSize, a2, sizeof(TInt));
606 return Write (a1, aSize);
611 case RPipe::EDataAvailableCount:
613 TAutoWait<DMutex> autoMutex(iData->Mutex());
614 return iData->AvailableDataCount();
617 case RPipe::EFlushPipe:
621 case RPipe::EGetPipeInfo:
622 umemput(a1,(TAny*)&iChannelType, sizeof(TInt));
624 umemput(a2,(TAny*)&aSize, sizeof(TInt));
629 return KErrNotSupported;
636 TInt DPipeChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
638 Processes Asynchronous requests This function is called to service
639 any asynchronous calls through the user side RPipe handle.
641 @param aFunction A number identifying the message type
642 @param aStatus Status request to be completed.
643 @param a1 A 32-bit Value passed by the user
644 @param a2 A 32-bit Value passed by the user
646 @return KErrNone If the call is successful, else one of the system wide error
655 case RPipe::EDataAvailable:
656 return NotifyDataAvailable(aStatus, ETrue);
658 case RPipe::ESpaceAvailable:
659 umemget(&aSize, a1, sizeof(aSize));
660 return NotifySpaceAvailable(aSize, aStatus, ETrue);
662 case RPipe::EWaitNotification:
663 // a2 == RPipe::EWaitForReader is for WaitForReader.
664 // a2 == RPipe::EWaitForWriter is for WaitForWriter.
665 umemget(&aChoice, a2, sizeof(aChoice));
666 return WaitNotification(aStatus, a1, aChoice);
668 case RPipe::EReadBlocking:
670 return NotifyDataAvailable(aStatus, EFalse);
673 case RPipe::EWriteBlocking:
675 umemget(&aSize, a1, sizeof(aSize));
676 return NotifySpaceAvailable(aSize, aStatus, EFalse);
679 return KErrNotSupported;
685 TInt DPipeChannel::PipeCreate(TAny* a1, TAny* a2)
687 Creates named pipes with the specified name and size. It calls Pipe Device
688 object to create the pipe and obtained the pointer to it. The pointer is then
689 stored in its iData member data.
690 @param a1 Pointer to TPipeInfo class
692 @param a2 Pointer to TSecurityPolicy class
694 @return KErrNone If successful, otherwise one of the other system wide error code.
699 //this channel already has a pipe
703 // The following code safely gets the 3 arguments into kernel memory.
704 // (The user side API is badly designed,)
705 RPipe::TPipeInfo& info = (*(RPipe::TPipeInfoBuf*)a1)(); // reference to user side 'TPipeInfo'
707 kumemget(&size,&info.isize,sizeof(size));
709 Kern::KUDesGet(name,info.iName);
710 TSecurityPolicy* securityPolicy = 0;
711 TSecurityPolicy securityPolicyBuffer;
714 kumemget(&securityPolicyBuffer,a2,sizeof(securityPolicyBuffer));
715 securityPolicy = &securityPolicyBuffer;
719 DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
721 //must wait on device since after creation
722 //the pipe becomes globably findable
724 TAutoWait<DMutex> outerAutoMutex(device.Mutex());
726 TInt err = ((DPipeDevice*)iDevice)->CreatePipe(name, size, pipe, securityPolicy);
732 TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
733 pipe->SetReadEnd(this);
735 iChannelType = RPipe::EReadChannel;
740 TInt DPipeChannel::PipeCreate(const TInt aSize)
742 Creates unnamed pipes with the specified Id and size. It calls Pipe Device
743 object to create the pipe and obtained the pointer to it. The pointer is then
744 stored in its iData member data. Marked the current channel as read end.
746 @param aSize Size of the unnamed pipe to be created.
748 @return Handle ID if successful, otherwise one of the other system wide error code.
753 //this channel already has a pipe
757 DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
759 TAutoWait<DMutex> outerAutoMutex(device.Mutex());
761 DPipe* pipe = device.CreatePipe(aSize);
767 TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
769 pipe->SetReadEnd(this);
771 iChannelType = RPipe::EReadChannel;
773 return iData->OpenId();
777 TInt DPipeChannel::OpenOnReader(const TDesC* aName)
779 Opens a named pipe identified by the name parameter. It calls Pipe Device object
780 to open the Pipe identified by the name and obtained the pointer to the pipe. The
781 pointer is them stored in its iData member data. Marked the current channel as write
783 @param aName The name of the pipe to be opened.
785 @return KErrNone If successful, otherwise one of the other system wide error code.
790 //this channel already has a pipe
795 Kern::KUDesGet(PName, *aName);
797 DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
799 //need to hold the device mutex to
800 //prevent the pipe getting deleted before we can call
802 TAutoWait<DMutex> outerAutoMutex(device.Mutex());
803 DPipe* pipe = device.FindNamedPipe(&PName);
810 TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
811 if (!pipe->IsReadEndOpened())
821 return KErrPermissionDenied;
824 if(pipe->IsWriteEndOpened())
830 iData->SetWriteEnd(this);
831 iChannelType = RPipe::EWriteChannel;
836 TInt DPipeChannel::PipeDestroy(const TDesC* aName)
838 Destroys the named pipe.
839 @param aName Name of the Kernel pipe to be destroyed.
841 @return KErrNone If the pipe is successfully destroyed, otherwise one of the
842 other system wide error codes
846 Kern::KUDesGet(PName, *aName);
847 return ((DPipeDevice*)iDevice)->Destroy(&PName);
850 TInt DPipeChannel::PipeOpen(const TInt aId)
852 Opens a unnamed pipe identified by the specified id. It calls Pipe Device object
853 to open a unnamed pipe identified by the specified id and obtain the pointer to the
854 pipe. The pipe reference is then stored in its iData member data and marked the
855 current channel as write end.
857 @param aId Id of the unnamed pipe to be opened.
859 @return KErrNone If successful, otherwise one of the system wide error code.
864 //this channel already has a pipe
868 DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
869 TAutoWait<DMutex> outerAutoMutex(device.Mutex());
871 DPipe* pipe = device.FindUnnamedPipe(aId);
877 TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
878 if (pipe->IsWriteEndOpened() )
883 pipe->SetWriteEnd(this);
885 iChannelType = RPipe::EWriteChannel;
892 TInt DPipeChannel::PipeOpen(const TDesC* aName, RPipe::TChannelType aType)
894 This function will be called under DoControl();
895 Attempts to open the pipe for reading (iReadEnd) or writing (iWriteEnd)
896 @param aName Name of the pipe to be opened
898 @param aType Type of operation to be performed.
900 @return KErrNone Pipe successfully created, otherwise one of the other system wide
906 //this channel already has a pipe
911 Kern::KUDesGet(PName, *aName);
913 DPipeDevice& device = *static_cast<DPipeDevice*>(iDevice);
915 TAutoWait<DMutex> outerAutoMutex(device.Mutex());
917 DPipe* pipe = device.FindNamedPipe(&PName);
924 TAutoWait<DMutex> innerAutoMutex(pipe->Mutex());
926 //! Check capabilitity if applicalble
930 return KErrPermissionDenied;
933 // Check if the pipe is already opened.
934 if(aType == RPipe::EReadChannel)
936 if(iData->IsReadEndOpened())
941 iData->SetReadEnd(this);
945 if(iData->IsWriteEndOpened())
950 iData->SetWriteEnd(this);
953 iChannelType = aType;
960 TBool DPipeChannel::CheckCap()
962 Check if Security policy is installed, if so, checks if the current thread
963 has required capabilities
967 @return TBool ETrue if The current thread has required capabilities and also if
968 no capabilities is installed, otherwise EFlase.
972 //iData->GetCap is always true
974 return iData->GetCap()->CheckPolicy(&Kern::CurrentThread());
981 TInt DPipeChannel::Read (TAny* aBuff, TInt aSize)
983 Synchronous, non-blocking read operation. If the pipe is empty it will
984 return immediately with KErrUnderflow. A successful DPipe::Read() operation
985 will free up more space in the pipe. If a request status object has been registered
986 for Space Available notification, it will complete. Note that there is no
987 guarantee that the amount of space freed up in the pipe will be sufficient
988 for the next DPipe::Write() operation.
990 @param aBuff Buffer from which data need to be read
992 @param aSize Size of the data to be read
994 @return:>0 Amount of data read in octets.
995 KErrArgument Invalid Length Amount of data to be read is invalid (e.g. negative)
996 KErrNotReady If the write end is closed,
997 otherwise one of the other system wide error code
1001 if( iChannelType != RPipe::EReadChannel)
1002 return KErrAccessDenied;
1005 TAutoWait<DMutex> outerAutoMutex(*iData->iReadMutex);
1006 TAutoWait<DMutex> innerAutoMutex(iData->Mutex());
1008 if(!iData->IsWriteEndOpened() && iData->IsBufferEmpty())
1010 //it is ok to read from a broken pipe provided there is data in it
1011 return KErrNotReady;
1014 return iData->Read(aBuff, aSize);
1018 TInt DPipeChannel::Write (TAny* aBuff, TInt aSize)
1020 Synchronous, non-blocking write operation. If the pipe is full it will
1021 return immediately with KErrOverflow. A successful DPipe::Write() operation will
1022 return amount of data written to the pipe.If a request status object has been registered
1023 for Data Available notification, it will complete.
1026 @param aBuf Buffer from which data need to be written to the pipe.
1028 @param aSize Amount of data to be written to the pipe.
1030 @return >0 Amount of data written to the pipe, in octets.
1031 KErrOverflow The pipe is full no data is written.
1032 KErrArgument if the amount of data to be written in invalid
1033 KErrNotReady if the read end is not opened.
1034 otherwise one of the other system wide error code
1038 if(iChannelType!= RPipe::EWriteChannel)
1039 return KErrAccessDenied;
1041 TAutoWait<DMutex> outerAutoMutex(*iData->iWriteMutex);
1042 TAutoWait<DMutex> innerAutoMutex(iData->Mutex());
1044 if(!(iData->IsReadEndOpened()))
1046 return KErrNotReady;
1049 return iData->Write(aBuff, aSize);
1054 TInt DPipeChannel::CloseHandle()
1056 Attempts to close the pipe for reading or writing .
1060 @return KErrNone Success.
1061 KErrCouldNotDisconnect The pipe is already closed for that operation.
1070 __KTRACE_OPT(KPIPE, Kern::Printf("DPipeChannel::CloseHandle ID=%d, ChannelType=%d", iData->OpenId(), iChannelType));
1072 NKern::ThreadEnterCS();
1074 TInt err = KErrNone;
1075 if(iChannelType == RPipe::EReadChannel)
1077 CancelRequest(RPipe::EDataAvailable);
1078 err = iData->CloseReadEnd();
1080 else if(iChannelType == RPipe::EWriteChannel)
1082 CancelRequest(RPipe::ESpaceAvailable);
1083 err = iData->CloseWriteEnd();
1087 FAULT(); //iChannelType should be set correctly if iData was non-null
1089 // If we had a pointer to the pipe but it had no back pointer
1090 // to us something has gone wrong.
1091 __NK_ASSERT_DEBUG(err == KErrNone);
1093 const TInt pipeId=iData->OpenId();
1097 // The return code from close would inform us if
1098 // the device had no record of the pipe.
1099 // However, for a named pipe there is no gurrantee that the pipe
1100 // hasn't been deleted once we close our end of the pipe and
1102 static_cast<DPipeDevice*>(iDevice)->Close(pipeId);
1104 NKern::ThreadLeaveCS();
1111 TInt DPipeChannel::NotifySpaceAvailable ( TInt aSize,TRequestStatus* aStat, TBool aAllowDisconnected)
1113 Registers the request status object to be completed when space becomes
1114 available in the pipe.
1116 @param aSize The size for which the user has requested for notification
1118 @param aStat Status request to be registered
1119 @param aAllowDisconnected If false then confirm that the pipe has a reader
1121 @return KErrNone Success in registering the request
1122 KErrAccessDenied If the correct end is not used to register the request
1123 KErrInUse A notifier of this type has already been registered.
1124 otherwise one of the other system wide error code.
1125 KErrNotReady The pipe has no reader
1129 //! Check if correct end is used
1130 if(iChannelType!= RPipe::EWriteChannel)
1132 return KErrAccessDenied;
1135 TAutoWait<DMutex> autoMutex(iData->Mutex());
1136 //Check if there is already a pending Space Available request.
1137 if(iClientRequest->StatusPtr())
1143 if(!aAllowDisconnected && !(iData->IsReadEndOpened()) )
1144 return KErrNotReady;
1146 TInt r = iClientRequest->SetStatus(aStat);
1147 __NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
1148 DThread* const currThread = &Kern::CurrentThread();
1150 if((iData->RegisterSpaceAvailableNotification(aSize))==KErrCompletion)
1152 Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
1156 iRequestThread = currThread;
1157 // Open a reference on client thread so its control block can't disappear until
1158 // this channel has finished with it.
1159 iRequestThread->Open();
1160 iRequestType = RPipe::ESpaceAvailable;
1167 TInt DPipeChannel::NotifyDataAvailable (TRequestStatus* aStat, TBool aAllowDisconnected)
1169 Registers the request status object to be completed when data becomes
1170 available in the pipe.
1172 @param aStat Status request to be registered
1173 @param aAllowDisconnected If false then fail if the pipe is empty with no writer.
1175 @return KErrNone Success in registering the request
1176 KErrAccessDenied If the correct end is not used to register the request
1177 KErrInUse A notifier of this type has already been registered.
1178 otherwise one of the other system wide error code.
1179 KErrNotReady The pipe was empty and had no writer
1183 //! Check if correct end is used
1184 if(iChannelType!= RPipe::EReadChannel)
1186 return KErrAccessDenied;
1189 // Check if there is already a pending Data Available request.
1190 TAutoWait<DMutex> autoMutex(iData->Mutex() );
1191 if(iClientRequest->StatusPtr())
1197 if(!aAllowDisconnected)
1199 if(iData->IsBufferEmpty() && (!iData->IsWriteEndOpened()))
1200 return KErrNotReady;
1203 TInt r = iClientRequest->SetStatus(aStat);
1204 __NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
1205 DThread* const currThread = &Kern::CurrentThread();
1207 if((iData->RegisterDataAvailableNotification()) == KErrCompletion)
1209 Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
1213 iRequestThread = currThread;
1214 // Open a reference on client thread so its control block can't disappear until
1215 // this channel has finished with it.
1216 iRequestThread->Open();
1217 iRequestType = RPipe::EDataAvailable;
1224 TInt DPipeChannel::WaitNotification(TRequestStatus* aStat, TAny* aName, TInt aChoice)
1226 Registers the request status object to be completed when other end of the pipe
1227 is opened for reading (or writing).This method completes immediately if the other end of the
1228 pipe is already opened.
1231 @param aName Pointer to the a name passed as void pointer
1233 @param aStat Status request to be registered
1235 @param aChoice EWaitForReader,wait notification for Read end Opened.
1236 EWaitForWriter,wait notification for Write end Opened.
1238 @return KErrNone Success in registering the request
1239 KErrInUse A notifier of this type has already been registered.
1240 KErrAccessDenied If the correct end is not used to register the request
1241 otherwise one of the other system wide error code
1245 //! Check if correct end is used
1246 if(((aChoice == RPipe::EWaitForReader) && (iChannelType!= RPipe::EWriteChannel))
1247 || ((aChoice == RPipe::EWaitForWriter) && (iChannelType!= RPipe::EReadChannel)))
1249 return KErrAccessDenied;
1253 Kern::KUDesGet(PName, *(TDesC*)aName);
1255 TAutoWait<DMutex> autoMutex(iData->Mutex());
1256 if(iData->MatchName(&PName)== EFalse)
1258 return KErrNotFound;
1260 // Check if there is already a pending request.
1261 else if(iClientRequest->StatusPtr())
1267 TInt r = iClientRequest->SetStatus(aStat);
1268 __NK_ASSERT_ALWAYS(KErrNone == r); //we just checked StatusPtr
1269 DThread* const currThread = &Kern::CurrentThread();
1271 //register the request.
1272 if((iData->RegisterWaitNotification((TInt )aChoice))== KErrCompletion)
1274 Kern::QueueRequestComplete(currThread, iClientRequest, KErrNone);
1278 iRequestThread = currThread;
1279 // Open a reference on client thread so its control block can't disappear until
1280 // this channel has finished with it.
1281 iRequestThread->Open();
1282 iRequestType = RPipe::EWaitNotification;
1290 For a given request return true if the notification
1291 we are cancelling is outstanding. If not, or
1292 if the supplied request is not a valid cancllation
1295 TBool DPipeChannel::ValidCancellation(TInt aReqType)
1299 case RPipe::ECancelDataAvailable:
1300 return (iRequestType==RPipe::EDataAvailable);
1301 case RPipe::ECancelSpaceAvailable:
1302 return (iRequestType==RPipe::ESpaceAvailable);
1303 case RPipe::ECancelWaitNotification:
1304 return (iRequestType==RPipe::EWaitNotification);
1310 void DPipeChannel::CancelRequest ( TInt aReqType)
1312 Cancels an outstanding space available notifier request.
1314 @param aReqType A number identifying the message type
1319 TAutoWait<DMutex> autoMutex(iData->Mutex() );
1320 if(iClientRequest->StatusPtr() && ValidCancellation(aReqType))
1324 case RPipe::ECancelDataAvailable:
1325 iData->CancelDataAvailable();
1328 case RPipe::ECancelSpaceAvailable:
1329 iData->CancelSpaceAvailable();
1332 case RPipe::ECancelWaitNotification:
1333 iData->CancelWaitNotifier();
1339 Kern::QueueRequestComplete(iRequestThread, iClientRequest, KErrCancel);
1340 // Close our reference on the client thread
1341 Kern::SafeClose((DObject*&)iRequestThread,NULL);
1342 iRequestThread = NULL;
1348 TInt DPipeChannel::Size()
1350 Returns the size of the Pipe's buffer
1354 @return TInt Return the size of the pipe, otherwise one of the other system wide
1358 return KErrNotReady;
1360 return iData->Size();
1364 void DPipeChannel::Flush()
1366 Flush the content of the pipe
1369 @pre Must be in a critical section.
1373 //The flush is, in effect, a read where the data is ignored
1374 TAutoWait<DMutex> autoMutex(*iData->iReadMutex);
1382 // Called from the DPipe
1384 void DPipeChannel::DoRequestCallback()
1386 It is called from the DPipe to complete the Outstanding request
1393 __ASSERT_MUTEX(&iData->Mutex());
1394 __NK_ASSERT_DEBUG(iRequestThread);
1395 Kern::QueueRequestComplete(iRequestThread, iClientRequest, KErrNone);
1396 Kern::SafeClose((DObject*&)iRequestThread,NULL);
1397 iRequestThread=NULL;
1402 // DPipe the Kernel side pipe representing class
1411 iPipeMutex->Close(NULL);
1413 iReadMutex->Close(NULL);
1415 iWriteMutex->Close(NULL);
1419 // Creates a Named pipe
1420 DPipe* DPipe::CreatePipe(const TDesC& aName, TInt aSize, TAny *aPolicy)
1422 Static method to Create a Named pipe.
1423 @param aName Reference to the Name to be set to the current named pipe.
1424 @param aSize Size of the Pipe.
1425 @param TAny Pointer to TSecurityPolicy passed as void pointer
1427 @return DPipe* Reference to DPipe* instance if successful, otherwise NULL
1431 DPipe* tmp = new DPipe;
1436 if(tmp->ConstructPipe(aName, aSize, aPolicy)!= KErrNone)
1445 TInt DPipe::ConstructPipe(const TDesC& aName, TInt aSize,TAny* aPolicy)
1447 Second phase constructor
1449 @param aName The name of the pipe to be created
1450 @param aSize The size of the pipe to be created
1451 @param TAny Pointer to TSecurityPolicy passed as void pointer
1453 @return KErrNone If successful, otherwise one of the other system wide error code
1456 // check the size parameter.
1460 memcpy(&iPolicy,aPolicy,sizeof(TSecurityPolicy));
1465 TSecurityPolicy apolicy(ECapability_None);
1466 memcpy(&iPolicy,&apolicy,sizeof(TSecurityPolicy));
1469 if(aName.Length() != 0)
1474 iBuffer = static_cast<TUint8*>(Kern::AllocZ(aSize));
1476 return KErrNoMemory;
1479 _LIT(KMutexName,"PipeMutex");
1480 TInt err = Kern::MutexCreate(iPipeMutex, KMutexName, KMutexOrdGeneral0);
1485 _LIT(KReadMutex,"ReadMutex");
1486 err = Kern::MutexCreate(iReadMutex, KReadMutex, KMutexOrdGeneral1);
1492 _LIT(KWriteMutex,"WriteMutex");
1493 err = Kern::MutexCreate(iWriteMutex, KWriteMutex, KMutexOrdGeneral1);
1500 iWritePointer = iReadPointer = 0;
1506 TInt DPipe::OpenId()
1508 Returns the id of the Pipe
1512 @return iID ID of the pipe
1520 void DPipe::SetId(TInt aId)
1522 Set the id of the Pipe
1524 @param aId The id to be set
1529 //this is only called by the pipe device
1530 //it could also be set at construction time
1535 TBool DPipe::IsPipeClosed()
1537 Check if the Pipe is Closed.
1539 @return TBool ETure if Successful, otherwise EFalse;
1542 __ASSERT_MUTEX(iPipeMutex);
1544 return !(iReadChannel || iWriteChannel);
1548 TBool DPipe::MatchName(const TDesC8* aName)
1550 Check if the current instance of DPipe Name is matching with aName parameter
1552 @param aName Name to be checked with the current DPipe's name.
1554 @return TBool ETrue if match found, otherwise EFalse
1557 //name could be const
1558 return (iName.Compare(*aName) == 0);
1562 TBool DPipe::MatchId(const TInt aId)
1564 Checks if the current instance of DPipe is matching with the aId parameter
1566 @param aId ID to be checked with the current DPipe's id
1568 @return TBool ETure if match found , otherwise EFalse;
1571 return (iID == aId);
1575 TBool DPipe::IsBufferEmpty()
1577 Checks if the Buffer is Empty
1580 @return ETrue if buffer is empty
1583 return (AvailableDataCount()==0);
1587 TInt DPipe::Write(TAny* aBuf, TInt aSize)
1589 Synchronous, non-blocking write operation. If the pipe is full it will
1590 return immediately with KErrOverflow. A successful DPipe::Write() operation will
1591 return amount of data written to the pipe.If a request status object has been registered
1592 for Data Available notification, it will complete.
1594 @param aBuf Buffer from which data need to be written to the pipe.
1595 @param aSize Amount of data to be written to the pipe.
1597 @return >0 Amount of data written to the pipe, in octets.
1598 KErrNone No data written to the pipe.
1599 KErrOverflow Pipe is full, cannot write any more data.
1600 KErrArgument If the amount of data to be written is invalid.
1601 Otherwise one of the other system wide error code
1603 @pre iPipeMutex held
1604 @pre iWriteMutex held
1606 @note Write enters and exists with the pipe mutex held - but releases and reaquires internally
1609 __KTRACE_OPT(KPIPE, Kern::Printf("DPipe::Write(aBuf=0x%08x, aSize=%d)", aBuf, aSize));
1611 __ASSERT_MUTEX(iPipeMutex);
1612 __ASSERT_MUTEX(iWriteMutex);
1613 // Check for the Invalid Length
1616 return KErrArgument;
1624 //Since only one thread can be writing to the write end
1625 //of a pipe it is sufficient that AvailableDataCount
1626 //holds the pipe mutex. After it returns the
1627 //available space may increase
1628 //but can not decrease
1629 const TInt spaceavailable = (iSize - AvailableDataCount());
1630 if (spaceavailable < aSize)
1632 //Though the API may suggest otherwise - partial writes are not supported.
1633 return KErrOverflow;
1636 //release mutex before IPC read
1640 const TDesC8* pBuf = (const TDesC8*)aBuf;
1642 const TInt distanceToEnd = iSize - iWritePointer;
1643 const TInt firstHalf = Min(distanceToEnd, aSize);
1644 TPtr ptr(&iBuffer[iWritePointer], firstHalf);
1646 DThread* const currThread = &Kern::CurrentThread();
1647 TInt r=Kern::ThreadDesRead(currThread, pBuf, ptr, 0, KChunkShiftBy0);
1650 Wait(); //we must exit with mutex held
1655 const TInt secondHalf = aSize - firstHalf;
1656 __NK_ASSERT_DEBUG( secondHalf >= 0);
1659 ptr.Set(&iBuffer[0], secondHalf, secondHalf);
1661 r = Kern::ThreadDesRead(currThread, pBuf, ptr, firstHalf, KChunkShiftBy0);
1664 Wait(); //we must exit with mutex held
1669 Wait(); //reaquire mutex for state update
1670 iWritePointer = (iWritePointer + aSize)% iSize;
1672 if(iWritePointer == iReadPointer)
1677 if(iDataAvailableRequest)
1679 iReadChannel->DoRequestCallback();
1680 iDataAvailableRequest = EFalse;
1687 TInt DPipe::Read(TAny* aBuf, TInt aSize)
1689 Synchronous, non-blocking read operation. If the pipe is empty it will
1690 return immediately with KErrUnderflow. A successful DPipe::Read() operation
1691 will free up more space in the pipe. If a request status object has been registered
1692 for Space Available notification, it will complete. Note that there is no
1693 guarantee that the amount of space freed up in the pipe will be sufficient
1694 for the next DPipe::Write() operation.
1696 @param aBuff Buffer to which data need to be written.
1697 @param aSize Size of the data to be read from the pipe.
1699 @return >0 Amount of data read from the pipe, in octets.
1700 KErrNone The pipe is empty , no data was read from the pipe.
1701 KErrArgument If the amount of data to be read is invalid.
1702 Otherwise one of the system wide error code
1703 @pre iPipeMutex held
1704 @pre iReadMutex held
1706 @note Read enters and exists with the pipe mutex held - but releases and reaquires internally
1709 __KTRACE_OPT(KPIPE, Kern::Printf("DPipe::Read(aBuf=0x%08x, aSize=%d)", aBuf, aSize));
1710 __ASSERT_MUTEX(iPipeMutex);
1711 __ASSERT_MUTEX(iReadMutex);
1715 return KErrArgument;
1718 const TInt totalToRead = Min(AvailableDataCount(), aSize);
1721 if(totalToRead == 0)
1728 const TInt distanceToEnd = iSize - iReadPointer;
1729 __NK_ASSERT_DEBUG(distanceToEnd>=0);
1730 const TInt firstHalf = Min(totalToRead, distanceToEnd);
1732 TPtrC8 pipeBuffer(&iBuffer[iReadPointer], firstHalf);
1733 TDes8* userBuffer = (TDes8*)aBuf;
1735 DThread* const currThread = &Kern::CurrentThread();
1736 TInt r = Kern::ThreadDesWrite(currThread, userBuffer, pipeBuffer, 0, KChunkShiftBy0, NULL);
1739 Wait(); //we must exit with mutex held
1743 const TInt secondHalf=totalToRead-firstHalf;
1744 __NK_ASSERT_DEBUG(secondHalf>=0);
1748 pipeBuffer.Set(&iBuffer[0], secondHalf);
1749 r = Kern::ThreadDesWrite(currThread, userBuffer, pipeBuffer, firstHalf, KChunkShiftBy0, NULL);
1752 Wait(); //we must exit with mutex held
1756 __NK_ASSERT_DEBUG(firstHalf+secondHalf==totalToRead);
1758 Wait(); //Reaquire mutex for state update
1760 iReadPointer = (iReadPointer + totalToRead)% iSize;
1762 MaybeCompleteSpaceNotification();
1764 __ASSERT_MUTEX(iReadMutex);
1768 TInt DPipe::AvailableDataCount()
1770 Returns the Data available in the pipe.
1774 @return TInt Amount of data available in the pipe
1778 __ASSERT_MUTEX(iPipeMutex);
1780 if ( iWritePointer > iReadPointer )
1782 size = iWritePointer - iReadPointer;
1784 else if ( iReadPointer > iWritePointer )
1786 size = iSize - iReadPointer + iWritePointer;
1790 //iReadPointer == iWritePointer
1791 size = iFull ? iSize : 0;
1796 TInt DPipe::RegisterSpaceAvailableNotification(TInt aSize)
1798 Registers the request status object to be completed when space becomes
1799 available in the pipe.
1801 @param aSize The size for which the space availability be notified.
1803 @return KErrNone Success.
1804 KErrCompletion The request is not registered as it completes immediately
1805 otherwise one of the system wide error code.
1806 @pre Mutex must be held.
1807 @pre Must be in a critical section.
1810 __ASSERT_MUTEX(iPipeMutex);
1811 __NK_ASSERT_DEBUG(Rng(1, aSize, iSize));
1813 // Check if Specified size is available.
1814 TInt err = KErrNone;
1815 if ((aSize <= (iSize - AvailableDataCount())))
1817 iSpaceAvailableRequest = EFalse;
1818 err = KErrCompletion;
1822 iSpaceAvailableSize = aSize;
1823 iSpaceAvailableRequest = ETrue;
1829 TInt DPipe::RegisterDataAvailableNotification()
1831 Registers the request status object to be completed when data becomes
1832 available in the pipe.
1836 @return KErrNone If successful, otherwise one of the other system wide
1838 @pre Mutex must be held.
1839 @pre Must be in a critical section.
1842 __ASSERT_MUTEX(iPipeMutex);
1844 TInt err = KErrNone;
1845 // Check if Data is available.
1846 if(AvailableDataCount())
1848 iDataAvailableRequest = EFalse;
1849 err = KErrCompletion;
1853 iDataAvailableRequest = ETrue;
1859 TInt DPipe::RegisterWaitNotification(TInt aChoice)
1861 Registers the request status object to be completed when other end of the pipe
1862 is opened for reading. This method completes immediately if the other end of the
1863 pipe is already opened.
1867 @return KErrNone Successfully registered, otherwise one of the other system wide
1869 @pre Mutex must be held.
1870 @pre Must be in a critical section.
1873 __ASSERT_MUTEX(iPipeMutex);
1875 TInt err = KErrNone;
1876 // Check if Read end is opened
1877 if (aChoice == RPipe::EWaitForReader)
1879 if(IsReadEndOpened())
1881 iWaitRequest = EFalse;
1882 err = KErrCompletion;
1886 iWaitRequest = ETrue;
1892 if(IsWriteEndOpened())
1894 iWaitRequest = EFalse;
1895 err = KErrCompletion;
1899 iWaitRequest = ETrue;
1907 //! Cancellation methods
1908 void DPipe::CancelSpaceAvailable()
1910 Cancels an outstanding space available notifier request.
1917 __ASSERT_MUTEX(iPipeMutex);
1918 if(iSpaceAvailableRequest)
1919 iSpaceAvailableRequest = EFalse;
1923 void DPipe::CancelDataAvailable()
1925 Cancels an outstanding data available notifier request.
1932 __ASSERT_MUTEX(iPipeMutex);
1933 if(iDataAvailableRequest)
1934 iDataAvailableRequest = EFalse;
1938 void DPipe::CancelWaitNotifier()
1940 Cancel an outstanding wait notifier request
1944 @return KErrNone If Successful, otherwise one of the other system wide error code.
1948 __ASSERT_MUTEX(iPipeMutex);
1949 // Cancel Wait Notifier request
1951 iWaitRequest = EFalse;
1955 void DPipe::CloseAll()
1957 Cancel any outstanding request.
1964 CancelSpaceAvailable();
1965 CancelDataAvailable();
1966 CancelWaitNotifier();
1973 TInt DPipe::CloseReadEnd()
1975 Close the read end of the pipe.
1977 Cancels outstanding requests placed by the *write*
1978 channel and clears pipe's pointer to the read channel.
1979 If this function is called then the read channel's back
1980 pointer to the pipe must also be cleared.
1984 @return KErrNone If the end is closed, else one of the other system
1988 __ASSERT_MUTEX(iPipeMutex);
1989 __KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::CloseReadEnd ID=%d, iReadChannel=0x%08x", OpenId(), iReadChannel));
1992 return KErrCouldNotDisconnect;
1997 iWriteChannel->CancelRequest(RPipe::ECancelSpaceAvailable);
1999 iReadChannel = NULL;
2005 TInt DPipe::CloseWriteEnd()
2007 Close the write end of the pipe
2009 Cancels outstanding requests placed by the *read*
2010 channel and clears pipe's pointer to the write channel.
2011 If this function is called then the write channel's back
2012 pointer to the pipe must also be cleared.
2016 @return KErrNone If the write end is successfully closed, else
2017 one of the other system wide error code.
2020 __ASSERT_MUTEX(iPipeMutex);
2021 __KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::CloseWriteEnd ID=%d, iWriteChannel=0x%08x", OpenId(), iWriteChannel));
2024 return KErrCouldNotDisconnect;
2027 // Cancel RBlocking call if it is there
2030 iReadChannel->CancelRequest(RPipe::ECancelDataAvailable);
2032 iWriteChannel = NULL;
2039 void DPipe::FlushPipe()
2041 Flush all the date from the pipe and reinitialise the buffer pointer.
2047 @pre Pipe Mutex to be held
2048 @pre Read Mutex to be held
2052 __ASSERT_MUTEX(iPipeMutex);
2053 __ASSERT_MUTEX(iReadMutex);
2055 iReadPointer = iWritePointer;
2058 MaybeCompleteSpaceNotification();
2062 If there is an outstanding space request, and
2063 there is enough space to satisfy it then complete
2066 @pre the pipe mutex must be held
2068 void DPipe::MaybeCompleteSpaceNotification()
2070 __ASSERT_MUTEX(iPipeMutex);
2072 // Check if there is writeblocking request
2073 if(iSpaceAvailableRequest)
2075 const TInt spacecount = (iSize - AvailableDataCount());
2076 if (iSpaceAvailableSize <= spacecount)
2078 iWriteChannel->DoRequestCallback();
2079 iSpaceAvailableRequest = EFalse;
2084 TBool DPipe::IsReadEndOpened()
2086 Returns information regarding the read end of the current pipe instance.
2088 @return TBool ETrue if read end is Opened, otherwise EFalse
2089 @pre the pipe mutex must be held
2092 __ASSERT_MUTEX(iPipeMutex);
2093 return (iReadChannel != NULL);
2097 TBool DPipe::IsWriteEndOpened()
2099 Returns information regarding the write end of the current pipe instance.
2101 @return TBool ETrue if WriteChannel is opened, otherwise EFalse
2102 @pre the pipe mutex must be held
2105 __ASSERT_MUTEX(iPipeMutex);
2106 return (iWriteChannel != NULL);
2110 TBool DPipe::IsNamedPipe()
2112 Returns whether the pipe is named or unnamed.
2114 @return TBool ETrue if it is a named pipe, otherwise EFalse
2118 return (iName.Length() != 0);
2122 void DPipe::SetReadEnd(DPipeChannel* aChannel)
2124 Set the Read end of the pipe as opened and store the pointer for the read channel
2125 It also notify if there is any pending Wait Request.
2127 @param aChannel The pointer to the read channel
2129 @pre the pipe mutex must be held
2130 @pre The pipe's read end must be closed ie. IsReadEndOpened returns false
2133 __ASSERT_MUTEX(iPipeMutex);
2134 __KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::SetReadEnd ID=%d", OpenId()));
2137 //A channel must be sure this function
2138 //succeeded otherwise the pipe
2139 //could be destroyed without the channel's
2141 __NK_ASSERT_DEBUG(iReadChannel==NULL);
2143 iReadChannel = aChannel;
2144 __KTRACE_OPT(KPIPE, Kern::Printf("DPipe::SetReadEnd set iReadChannel=0x%08x", iReadChannel));
2149 iWriteChannel->DoRequestCallback();
2150 iWaitRequest=EFalse;
2155 void DPipe::SetWriteEnd(DPipeChannel* aChannel)
2157 Set the write end of the pipe as opened and store the pointer to the write channel
2159 @param aChannel The pointer to the write channel
2162 @pre the pipe mutex must be held
2163 @pre The pipe's write end must be closed ie. IsWriteEndOpened returns false
2166 __ASSERT_MUTEX(iPipeMutex);
2167 __KTRACE_OPT(KPIPE, Kern::Printf(">DPipe::SetWriteEnd ID=%d", OpenId()));
2169 //A channel must be sure this function
2170 //succeeded otherwise the pipe
2171 //could be destroyed without the channel's
2173 __NK_ASSERT_DEBUG(iWriteChannel==NULL);
2175 iWriteChannel = aChannel;
2176 __KTRACE_OPT(KPIPE, Kern::Printf("DPipe::SetWriteEnd set iWriteChannel=0x%08x", iWriteChannel));
2181 iReadChannel->DoRequestCallback();
2182 iWaitRequest=EFalse;
2188 @return The size of the pipe's circular buffer
2191 //this could be const