sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: sl@0: sl@0: sl@0: #ifndef __DPIPE_H__ sl@0: #define __DPIPE_H__ sl@0: sl@0: #define _TEST__ sl@0: sl@0: #if !defined(__KERNEL_H__) sl@0: #include sl@0: #endif sl@0: sl@0: #include sl@0: sl@0: const TInt KIdBase = 0x0; sl@0: sl@0: class DPipe; sl@0: sl@0: class DPipeDevice : public DLogicalDevice sl@0: /** sl@0: The factory class is derived from Dlogical device. The user side calls sl@0: User::LoadLogicalDevice() to load the LDD dll and create the LDD sl@0: factory object in the kernel heap. sl@0: @internalTechnology sl@0: */ sl@0: { sl@0: public: sl@0: /** sl@0: Set the version number sl@0: */ sl@0: DPipeDevice(); sl@0: sl@0: ~DPipeDevice(); sl@0: sl@0: // Inherited from DLogicalDevice sl@0: /** sl@0: Second stage constructor and at least set a name for the sl@0: driver object. sl@0: */ sl@0: virtual TInt Install(); sl@0: sl@0: sl@0: virtual void GetCaps(TDes8& aDes) const; sl@0: sl@0: /** sl@0: Called by the Kernel's Device driver framework to create a logical sl@0: Channel. This called in the context of the user thread. which requested sl@0: the creation of the logical channel.It checks if maximum pipe creation sl@0: has reached before creating a new Kernel pipe object. sl@0: @param aChannel Set to point to the created logical channel sl@0: sl@0: @return KErrNone if successful, otherwise system wide error codes. sl@0: */ sl@0: virtual TInt Create(DLogicalChannelBase*& aChannel); sl@0: sl@0: sl@0: /** sl@0: Called by the Logical channel instance to create DPipe and sl@0: associate itself. sl@0: */ sl@0: TInt CreatePipe(const TDesC& aName, TInt aSize, DPipe*& aPipe, TAny* aCapCheck = NULL); sl@0: sl@0: DPipe* CreatePipe(TInt aSize); sl@0: sl@0: DPipe* FindNamedPipe(const TDesC* aName); sl@0: sl@0: DPipe* FindUnnamedPipe(const TInt aId); sl@0: sl@0: TInt Destroy(const TDesC* aName); sl@0: sl@0: TInt Close(TInt aId); sl@0: sl@0: sl@0: inline DMutex& Mutex() sl@0: { sl@0: return *iMutex; sl@0: } sl@0: sl@0: inline void Wait() sl@0: { sl@0: Kern::MutexWait(*iMutex); sl@0: } sl@0: sl@0: inline void Signal() sl@0: { sl@0: Kern::MutexSignal(*iMutex); sl@0: } sl@0: sl@0: private: sl@0: TInt GenerateId(); sl@0: sl@0: TInt AddPipe(DPipe* aObj); sl@0: sl@0: void RemovePipe(DPipe** aObj); sl@0: sl@0: sl@0: private: sl@0: //! Represents the Data in a pipe. sl@0: DPipe **iDpipes; sl@0: sl@0: DMutex *iMutex; sl@0: sl@0: TInt iAllocated; sl@0: sl@0: TInt iCount; sl@0: sl@0: TInt iIdindex; sl@0: sl@0: }; sl@0: sl@0: sl@0: sl@0: class DPipeChannel : public DLogicalChannelBase sl@0: /** sl@0: DPipe Channel provides the Kernel interface to the DPipe. The request from the RPipe handler sl@0: in the context of user thread, is transfered to DPipeChannel class. This is the interface sl@0: between the DPipe kernel object and the user request through RPipe handler. sl@0: sl@0: @internalTechnology sl@0: */ sl@0: { sl@0: public: sl@0: DPipeChannel(); sl@0: virtual ~DPipeChannel(); sl@0: sl@0: // inherited from DObject sl@0: virtual TInt RequestUserHandle (DThread* aThread, TOwnerType aType); sl@0: sl@0: // inherited from DLogicalChannelBase sl@0: virtual TInt DoCreate (TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); sl@0: sl@0: virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2); sl@0: sl@0: sl@0: private: sl@0: sl@0: // The user request is mapped sl@0: TInt DoControl(TInt aFunction, TAny* a1, TAny* a2); sl@0: sl@0: TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, sl@0: TAny* a2); sl@0: sl@0: // This function will be called under DoControl() sl@0: TInt PipeCreate(TAny* a1, TAny* a2); sl@0: sl@0: TInt PipeCreate(TInt aSize); sl@0: sl@0: TInt PipeOpen(const TDesC* aName, RPipe::TChannelType aType); sl@0: sl@0: TInt PipeOpen (const TInt aId); sl@0: sl@0: TInt OpenOnReader(const TDesC* aName); sl@0: sl@0: TInt PipeDestroy(const TDesC* aName); sl@0: sl@0: TInt Read (TAny* aBuff, TInt aSize); sl@0: sl@0: TInt Write (TAny* aBuff, TInt aSize); sl@0: sl@0: TInt Size(); sl@0: sl@0: TInt CloseHandle(); sl@0: sl@0: TBool CheckCap(); sl@0: sl@0: // Registration of the Asynchronous request sl@0: TInt NotifySpaceAvailable (TInt aSize, TRequestStatus* aStat, TBool aAllowDisconnected); sl@0: sl@0: TInt NotifyDataAvailable (TRequestStatus* aStat, TBool aAllowDisconnected); sl@0: sl@0: TInt WaitNotification (TRequestStatus* aStat, TAny* aName , TInt aChoice); sl@0: sl@0: void Flush(); sl@0: sl@0: TBool ValidCancellation(TInt aReqType); sl@0: public: sl@0: sl@0: void CancelRequest (TInt aReqType); sl@0: sl@0: void DoRequestCallback(); sl@0: sl@0: private: sl@0: /////// Accessed within pipe mutex /////// sl@0: sl@0: DThread *iRequestThread; ///< The thread awaiting notification. sl@0: TClientRequest* iClientRequest; sl@0: sl@0: //Allows us to tell if a request cancellation is valid sl@0: TInt iRequestType; ///< Access within Pipe Mutex sl@0: sl@0: ////////////////////////////////////////// sl@0: sl@0: sl@0: // Reference to the DPipe sl@0: DPipe* iData; sl@0: sl@0: //Effectively constant sl@0: RPipe::TChannelType iChannelType; sl@0: }; sl@0: sl@0: sl@0: sl@0: class DPipe:public DBase sl@0: /** sl@0: This class represent the actual Kernel side Pipe. An instance of this class is constructed sl@0: when ever user creates a named/un-named pipe through the methods provided by user handler RPipe. sl@0: The owner of a DPipe instance is the DPipeDevice factory object and associates this DPipe sl@0: instance to the appropriate DPipeChannel instance. Each DPipe object is associated with two sl@0: DPipeChannel instances for read and writes operation sl@0: sl@0: @internalTechnology sl@0: */ sl@0: { sl@0: friend class DPipeChannel; sl@0: friend class DPipeDevice; sl@0: public: sl@0: sl@0: virtual ~DPipe(); sl@0: sl@0: // Creates a Named pipe sl@0: static DPipe* CreatePipe(const TDesC& aName, TInt aSize, TAny* aPolicy = NULL); sl@0: sl@0: // check if the name referring to a created pipe is valid. sl@0: TBool MatchName(const TDesC* aName); sl@0: sl@0: // Check if the id referring to a created pipe is valid. sl@0: TBool MatchId(const TInt aId); sl@0: sl@0: sl@0: // Check if Buffer is Empty sl@0: TInt IsBufferEmpty(); sl@0: sl@0: // Write to Buffer sl@0: TInt Write(TAny* aBuf, TInt aSize); sl@0: sl@0: // Read to Buffer sl@0: TInt Read(TAny* aBuf, TInt aSize); sl@0: sl@0: void SetReadEnd(DPipeChannel * aChannel); sl@0: sl@0: void SetWriteEnd(DPipeChannel * aChannel); sl@0: sl@0: sl@0: // Registering Notification from client thread sl@0: TInt RegisterSpaceAvailableNotification(TInt aSize); sl@0: sl@0: TInt RegisterDataAvailableNotification(); sl@0: sl@0: TInt RegisterWaitNotification(TInt aChoice); sl@0: sl@0: //! Cancellation methods sl@0: void CancelSpaceAvailable(); sl@0: sl@0: void CancelDataAvailable(); sl@0: sl@0: void CancelWaitNotifier(); sl@0: sl@0: TInt CloseReadEnd(); sl@0: sl@0: TInt CloseWriteEnd(); sl@0: sl@0: void CloseAll(); sl@0: sl@0: TBool IsNamedPipe(); sl@0: sl@0: TBool IsPipeClosed(); sl@0: sl@0: TBool IsReadEndOpened(); sl@0: sl@0: TBool IsWriteEndOpened(); sl@0: sl@0: TInt OpenId(); sl@0: sl@0: TInt Size(); sl@0: sl@0: void SetId(TInt aId); sl@0: sl@0: void FlushPipe(); sl@0: sl@0: TInt AvailableDataCount(); sl@0: sl@0: inline TSecurityPolicy* GetCap(){ return &iPolicy;} sl@0: sl@0: sl@0: private: sl@0: TInt ConstructPipe(const TDesC& aName, TInt aSize,TAny* aPolicy = NULL); sl@0: sl@0: inline void Wait() sl@0: { sl@0: Kern::MutexWait(*iPipeMutex); sl@0: DATAPAGING_TEST(Kern::SetRealtimeState(ERealtimeStateOn);) sl@0: } sl@0: sl@0: inline void Signal() sl@0: { sl@0: DATAPAGING_TEST(Kern::SetRealtimeState(ERealtimeStateOff);) sl@0: Kern::MutexSignal(*iPipeMutex); sl@0: } sl@0: sl@0: void MaybeCompleteSpaceNotification(); sl@0: sl@0: inline DMutex& Mutex() sl@0: { sl@0: return *iPipeMutex; sl@0: } sl@0: sl@0: private: sl@0: sl@0: //! constructor sl@0: DPipeChannel *iReadChannel; sl@0: sl@0: DPipeChannel *iWriteChannel; sl@0: sl@0: TKName iName; //! TBuf TKName sl@0: sl@0: TInt iID; sl@0: sl@0: //! Members for Ring buffer sl@0: TInt iSize; sl@0: sl@0: TBool iFull; sl@0: sl@0: TUint8 *iBuffer; sl@0: sl@0: TInt iWritePointer; sl@0: sl@0: TInt iReadPointer; sl@0: sl@0: //! Signify the presence of read and write channel sl@0: sl@0: TBool iSpaceAvailableRequest; sl@0: sl@0: TBool iDataAvailableRequest; sl@0: sl@0: TBool iWaitRequest; sl@0: sl@0: TInt iSpaceAvailableSize; sl@0: sl@0: DMutex *iPipeMutex; sl@0: DMutex *iReadMutex; sl@0: DMutex *iWriteMutex; sl@0: sl@0: sl@0: TSecurityPolicy iPolicy; sl@0: sl@0: }; sl@0: sl@0: /** sl@0: Acquire the given lock on construction and release sl@0: on destruction. sl@0: @internalTechnology sl@0: */ sl@0: template sl@0: class TAutoWait sl@0: { sl@0: public: sl@0: inline TAutoWait(T& aLock) sl@0: :iLock(aLock) sl@0: { sl@0: Wait(); sl@0: } sl@0: sl@0: inline ~TAutoWait() sl@0: { sl@0: Signal(); sl@0: } sl@0: sl@0: sl@0: private: sl@0: TAutoWait(TAutoWait&); sl@0: TAutoWait& operator= (TAutoWait&); sl@0: sl@0: //disallow allocating on the heap since sl@0: //this won't do what we want sl@0: void* operator new(TUint aSize); sl@0: sl@0: inline void Wait(); sl@0: inline void Signal(); sl@0: sl@0: T& iLock; sl@0: }; sl@0: sl@0: template<> sl@0: void TAutoWait::Wait() sl@0: { sl@0: NKern::ThreadEnterCS(); sl@0: Kern::MutexWait(iLock); sl@0: } sl@0: sl@0: template<> sl@0: void TAutoWait::Signal() sl@0: { sl@0: Kern::MutexSignal(iLock); sl@0: NKern::ThreadLeaveCS(); sl@0: } sl@0: sl@0: #endif sl@0: sl@0: sl@0: sl@0: