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