sl@0: // Copyright (c) 1995-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: // e32\include\drivers\comm.h
sl@0: // 
sl@0: //
sl@0: 
sl@0: /**
sl@0:  @file
sl@0:  @internalComponent
sl@0: */
sl@0: 
sl@0: #ifndef __M32COMM_H__
sl@0: #define __M32COMM_H__
sl@0: #include <platform.h>
sl@0: #include <kernel/kpower.h>
sl@0: #include <d32comm.h>
sl@0: #include <e32ver.h>
sl@0: //
sl@0: const TInt KCommsMajorVersionNumber=1;
sl@0: const TInt KCommsMinorVersionNumber=1;
sl@0: const TInt KCommsBuildVersionNumber=KE32BuildVersionNumber;
sl@0: //
sl@0: const TInt KDefaultRxBufferSize=0x800;
sl@0: const TInt KTxBufferSize=0x400;
sl@0: const TInt KMaxHighWaterMark=0x080;
sl@0: //
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: */
sl@0: const TUint KReceiveIsrParityError=0x10000000;
sl@0: 
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: */
sl@0: const TUint KReceiveIsrFrameError=0x20000000;
sl@0: 
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: */
sl@0: const TUint KReceiveIsrOverrunError=0x40000000;
sl@0: 
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: */
sl@0: const TUint KReceiveIsrBreakError=0x80000000;
sl@0: 
sl@0: const TUint KReceiveIsrMaskError=0xF0000000;
sl@0: //
sl@0: const TInt KTxNoChar=-1;
sl@0: //
sl@0: const TUint KReceiveIsrTermChar=0x80000000;
sl@0: const TUint KReceiveIsrMaskComplete=0xf0000000;
sl@0: const TUint KReceiveIsrShift=24;
sl@0: const TUint KReceiveIsrShiftedMask=0x0f;
sl@0: 
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: */
sl@0: const TUint KDTEInputSignals=(KSignalCTS|KSignalDSR|KSignalDCD|KSignalRNG);
sl@0: 
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: 	
sl@0: 	An enumeration listing the stopping modes supported by this driver, to be passed to the Stop function.
sl@0: */
sl@0: enum TStopMode 
sl@0: 	{
sl@0: 	/**
sl@0: 	Stopping due to normal operational reasons.
sl@0: 	*/
sl@0: 	EStopNormal,
sl@0: 	/**
sl@0: 	Stopping due to system power down.
sl@0: 	*/
sl@0: 	EStopPwrDown,
sl@0: 	/**
sl@0: 	Emergency stop. Deprecated.
sl@0: 	*/
sl@0: 	EStopEmergency
sl@0: 	};
sl@0: 	
sl@0: 	 
sl@0: class DChannelComm;
sl@0: 
sl@0: /**
sl@0: 	@publishedPartner
sl@0: 	@released
sl@0: 	
sl@0: 	An abstract class for a serial comm PDD.
sl@0: */
sl@0: class DComm : public DBase
sl@0: 	{
sl@0: public:
sl@0: 	/**
sl@0: 	Starts receiving characters.
sl@0: 	@return KErrNone if successful; otherwise one of the other system wide error codes.
sl@0: 	*/
sl@0: 	virtual TInt Start() =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Stops receiving characters.
sl@0: 	@param aMode The stopping reason as one of TStopMode.
sl@0: 	@see TStopMode
sl@0:  	*/
sl@0: 	virtual void Stop(TStopMode aMode) =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Starts or stop the uart breaking.
sl@0: 	@param aState ETrue to enable break signal(LCR) and EFalse disable break signal(LCR).
sl@0: 	*/
sl@0: 	virtual void Break(TBool aState) =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Starts transmitting characters.
sl@0: 	*/
sl@0: 	virtual void EnableTransmit() =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Read and translate the modem control lines.
sl@0: 	@return State changes. 
sl@0: 			For Example:
sl@0: 			RTS, DSR, RI, Carrier Detect.
sl@0: 	*/
sl@0: 	virtual TUint Signals() const =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Set signals.
sl@0: 	@param aSetMask   A bit mask for those modem control signals which are to be asserted.
sl@0: 	@param aClearMask A bit mask for those modem control signals which are to be de-asserted.
sl@0: 					  Each bit in the bit masks above corresponds to a modem control signal. 
sl@0: 					  Bits are defined as one of:
sl@0: 					  KSignalCTS
sl@0: 					  KSignalDSR
sl@0: 					  KSignalDCD
sl@0: 					  KSignalRNG
sl@0: 					  KSignalRTS
sl@0: 					  KSignalDTR
sl@0: 					  KSignalBreak
sl@0: 	
sl@0: 	*/
sl@0: 	virtual void SetSignals(TUint aSetMask,TUint aClearMask) =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Validates a new configuration.
sl@0: 	@param  aConfig Const reference to the comms configuration structure; to hold the configuration settings for serial comm port.
sl@0: 	@return KErrNone if successful; otherwise one of the other system wide error codes.
sl@0: 	@see TCommConfigV01
sl@0: 	*/
sl@0: 	virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Configures the hardware device. This is device specific API, that provides functionality to configure the uart.
sl@0: 	@param aConfig configuration settings for the device.
sl@0: 	@see TCommConfigV01
sl@0: 	*/
sl@0: 	virtual void Configure(TCommConfigV01 &aConfig) =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Gets the capabilities of the comm PDD.
sl@0: 	@param aCaps On return this descriptor should have been filled with capabilities. 
sl@0: 	*/
sl@0: 	virtual void Caps(TDes8 &aCaps) const =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Checks the configuration.
sl@0: 	@param aConfig A reference to the structure TCommConfigV01 with configuration to check.
sl@0: 	@see TCommConfigV01
sl@0: 	*/
sl@0: 	virtual void CheckConfig(TCommConfigV01& aConfig)=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Disable all IRQs.
sl@0: 	@return The state of the interrupts before disable, which is used to restore the interrupt state.
sl@0: 	*/
sl@0: 	virtual TInt DisableIrqs()=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Restore IRQs to the passed level.
sl@0: 	@param  aIrq The level to restore the IRQs to.
sl@0: 	*/
sl@0: 	virtual void RestoreIrqs(TInt aIrq)=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Returns a pointer to the DFC queue that should be used by the comm LDD.
sl@0: 	@param 	aUnit Unit for which the DfcQ is retrieved.
sl@0: 	@return A Pointer to the DFC queue that should be used by the USB LDD.
sl@0: 	@see TDfcQue
sl@0: 	*/
sl@0: 	virtual TDfcQue* DfcQ(TInt aUnit)=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Checks power status.
sl@0: 	@return ETrue if status is good, EFalse otherwise.
sl@0: 	*/
sl@0: 	inline TBool PowerGood();
sl@0: 	inline void SetCurrent(TInt aCurrent);
sl@0: 	inline void ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff);
sl@0: 	inline TInt TransmitIsr();
sl@0: 	inline void CheckTxBuffer();
sl@0: 	inline void StateIsr(TUint aSignals);
sl@0: 	inline TBool Transmitting();
sl@0: public:
sl@0: 	/**
sl@0: 	Pointer to the logical channel object which is derived from DLogicChannel.
sl@0: 	*/
sl@0: 	DChannelComm *iLdd;
sl@0: 	/**
sl@0: 	A Boolean flag to indicate when transmission is in progress [ETrue=(Trasnmission in progress)].
sl@0: 	*/
sl@0: 	TBool iTransmitting;
sl@0: 	};
sl@0: 
sl@0: /**
sl@0: @internalComponent
sl@0: */
sl@0: class DDeviceComm : public DLogicalDevice
sl@0: 	{
sl@0: public:
sl@0: 	DDeviceComm();
sl@0: 	virtual TInt Install();
sl@0: 	virtual void GetCaps(TDes8 &aDes) const;
sl@0: 	virtual TInt Create(DLogicalChannelBase*& aChannel);
sl@0: 	};
sl@0: 
sl@0: 
sl@0: //
sl@0: // TClientSingleBufferRequest
sl@0: //
sl@0: class TClientSingleBufferRequest
sl@0: {
sl@0: public:
sl@0: 	TClientSingleBufferRequest() 
sl@0: 		{
sl@0: 		Reset();
sl@0: 		}
sl@0: 	~TClientSingleBufferRequest() 
sl@0: 		{
sl@0: 		if (iBufReq)
sl@0: 			Kern::DestroyClientBufferRequest(iBufReq);
sl@0: 		Reset();
sl@0: 		}
sl@0: 	void Reset()
sl@0: 		{
sl@0: 		iBufReq = NULL;
sl@0: 		iBuf = NULL;
sl@0: 		iLen = 0;
sl@0: 		}
sl@0: 	TInt Create()
sl@0: 		{
sl@0: 		if (iBufReq)
sl@0: 			return KErrNone;
sl@0: 		TInt r = Kern::CreateClientBufferRequest(iBufReq, 1, TClientBufferRequest::EPinVirtual);
sl@0: 		return r;
sl@0: 		}
sl@0: 	TInt Setup(TRequestStatus* aStatus, TAny* aDes, TInt aLen=0) 
sl@0: 		{
sl@0: 		TInt r = iBufReq->Setup(iBuf, aStatus, aDes);
sl@0: 		if (r == KErrNone)
sl@0: 			iLen = aLen;
sl@0: 		return r;
sl@0: 		}
sl@0: 	TInt SetupFromPtr(TRequestStatus* aStatus, TLinAddr aPtr, TInt aLen) 
sl@0: 		{
sl@0: 		TInt r = iBufReq->Setup(iBuf, aStatus, aPtr, aLen);
sl@0: 		iLen = aLen;
sl@0: 		return r;
sl@0: 		}
sl@0: 	void Complete(DThread* aClient, TInt aReason) 
sl@0: 		{
sl@0: 		if (iBufReq)
sl@0: 			{
sl@0: 			iBuf = NULL;
sl@0: 			Kern::QueueBufferRequestComplete(aClient, iBufReq, aReason);
sl@0: 			}
sl@0: 		}
sl@0: 	TClientBufferRequest* iBufReq;
sl@0: 	TClientBuffer* iBuf;
sl@0: 	TInt iLen;
sl@0: };
sl@0: 
sl@0: class DCommPowerHandler;
sl@0: /**
sl@0: @internalComponent
sl@0: */
sl@0: class DChannelComm : public DLogicalChannel
sl@0: 	{
sl@0: public:
sl@0: 	enum TState {EOpen,EActive,EClosed};
sl@0: 	enum TRequest {ERx=1, ETx=2, ESigChg=4, EBreak=8, EAll=0xff};
sl@0: 
sl@0: 	DChannelComm();
sl@0: 	~DChannelComm();
sl@0: 	virtual void ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff);
sl@0: 	virtual void CheckTxBuffer();
sl@0: 	virtual void StateIsr(TUint aSignals);
sl@0: 	virtual TInt TransmitIsr();
sl@0: 	virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
sl@0: 
sl@0: 	/**	@publishedPartner
sl@0: 		@released */
sl@0: 	virtual void UpdateSignals(TUint aSignals);
sl@0: 	inline void SetStatus(TState aStatus);
sl@0: 	virtual TInt SendMsg(TMessageBase* aMsg);
sl@0: protected:
sl@0: 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
sl@0: 	virtual void HandleMsg(TMessageBase* aMsg);
sl@0: 	void DoCancel(TInt aMask);
sl@0: 	TInt DoControl(TInt aId, TAny* a1, TAny* a2);
sl@0: 	void DoRequest(TInt aId, TAny* a1, TAny* a2);
sl@0: 	void DoPowerUp();
sl@0: 	void Start();
sl@0: 	TInt Shutdown();
sl@0: 	void BreakOn();
sl@0: 	void BreakOff();
sl@0: 	void AssertFlowControl();
sl@0: 	void ReleaseFlowControl();
sl@0: 	TInt SetRxBufferSize(TInt aSize);
sl@0: 	void ResetBuffers(TBool aResetTx);
sl@0: 	void DoDrainRxBuffer(TInt aEndIndex);
sl@0: 	void DoFillTxBuffer();
sl@0: 	void DoCompleteRx();
sl@0: 	void DoCompleteTx();
sl@0: 	void Complete(TInt aMask, TInt aReason);
sl@0: 	inline void DrainRxBuffer()	{ iRxDrainDfc.Add(); }
sl@0: 	inline void RxComplete();
sl@0: 	inline void TxComplete();
sl@0: protected:
sl@0: 	inline void EnableTransmit();
sl@0: 	inline TInt IsLineFail(TUint aFailSignals);
sl@0: 	inline TInt PddStart();
sl@0: 	inline void Stop(TStopMode aMode);
sl@0: 	inline void PddBreak(TBool aState);
sl@0: 	inline TUint Signals() const;
sl@0: 	inline void SetSignals(TUint aSetMask,TUint aClearMask);
sl@0: 	inline TInt ValidateConfig(const TCommConfigV01 &aConfig) const;
sl@0: 	inline void PddConfigure(TCommConfigV01 &aConfig);
sl@0: 	inline void PddCaps(TDes8 &aCaps) const;
sl@0: 	inline void PddCheckConfig(TCommConfigV01& aConfig);
sl@0: 	inline TBool Transmitting();
sl@0: private:
sl@0: 	static void PowerUpDfc(TAny* aPtr);
sl@0: 	static void PowerDownDfc(TAny* aPtr);
sl@0: 	static void DrainRxDfc(TAny* aPtr);
sl@0: 	static void FillTxDfc(TAny* aPtr);
sl@0: 	static void CompleteRxDfc(TAny* aPtr);
sl@0: 	static void CompleteTxDfc(TAny* aPtr);
sl@0: 	static void TimerDfcFn(TAny* aPtr);
sl@0: 	static void SigNotifyDfc(TAny* aPtr);
sl@0: 	void TimerDfc();
sl@0: 	static void MsCallBack(TAny* aPtr);
sl@0: 	inline TBool IsTerminator(TUint8 aChar);
sl@0: 	inline void SetTerminator(TUint8 aChar);
sl@0: 	inline TInt RxCount();
sl@0: 	inline TInt TxCount();
sl@0: 	inline TBool AreAnyPending() const;
sl@0: 	void InitiateRead(TInt aLength);
sl@0: 	void InitiateWrite();
sl@0: 	void DoSigNotify();
sl@0: 	void UpdateAndProcessSignals();
sl@0: 
sl@0: 	
sl@0: 	TUint FailSignals(TUint aHandshake);
sl@0: 	TUint HoldSignals(TUint aHandshake);
sl@0: 	TUint FlowControlSignals(TUint aHandshake);
sl@0: 	TUint AutoSignals(TUint aHandshake);
sl@0: 	TInt SetConfig(TCommConfigV01& aConfig);
sl@0: 	void CheckOutputHeld();
sl@0: 	void RestartDelayedTransmission();
sl@0: 
sl@0: 	static void FinishBreak(TAny* aSelf); // Called when timer indicating break should finish expires
sl@0: 	void QueueFinishBreakDfc();	// Called to queue dfc to finish break
sl@0: 	static void FinishBreakDfc(TAny* aSelf); // Dfc called to finish break
sl@0: 	void FinishBreakImplementation(TInt aError); // Actual implementation to finish break
sl@0: 
sl@0: public:
sl@0: 	// Port configuration
sl@0: 	TCommConfigV01 iConfig;
sl@0: 
sl@0: 	/**	@publishedPartner
sl@0: 		@released */
sl@0: 	TUint iRxXonChar;
sl@0: 
sl@0: 	/**	@publishedPartner
sl@0: 		@released */
sl@0: 	TUint iRxXoffChar;
sl@0: 
sl@0: 	TInt TurnaroundSet(TUint aNewTurnaroundMilliSeconds);
sl@0: 	TBool TurnaroundStopTimer();
sl@0: 	TInt TurnaroundClear();
sl@0: 	TInt RestartTurnaroundTimer();
sl@0: 	static void TurnaroundStartDfc(TAny* aSelf);
sl@0: 	void TurnaroundStartDfcImplementation(TBool inIsr);
sl@0: 	static void TurnaroundTimeout(TAny* aSelf);
sl@0: 	void TurnaroundTimeoutImplementation();
sl@0: 
sl@0: 	// General items
sl@0: 	DThread* iClient;
sl@0: 	DCommPowerHandler* iPowerHandler;
sl@0: 	TDfc iPowerUpDfc;
sl@0: 	TDfc iPowerDownDfc;
sl@0: 	TState iStatus;
sl@0: 	TDfc iRxDrainDfc;
sl@0: 	TDfc iRxCompleteDfc;
sl@0: 	TDfc iTxFillDfc;
sl@0: 	TDfc iTxCompleteDfc;
sl@0: 	TDfc iTimerDfc;
sl@0: 	TDfc iSigNotifyDfc;
sl@0: 	TUint iFlags;				//
sl@0: 	TUint iSignals;				// State of handshake lines
sl@0: 	TUint iFailSignals;			// 1 bit means line low causes line fail error
sl@0: 	TUint iHoldSignals;			// 1 bit means line low halts TX
sl@0: 	TUint iFlowControlSignals;	// 1 bit means signal is used for RX flow control
sl@0: 	TUint iAutoSignals;			// 1 bit means signal is high when channel is open
sl@0: 	TUint8 iTerminatorMask[32];	// 1 bit means character is a terminator
sl@0: 	TUint8 iStandby;			// ETrue means the machine is transiting to/from standby
sl@0: 	TUint8 iMsgHeld;			// ETrue means a message has been held up waiting the end of from standby transition 
sl@0: 
sl@0: 	// Min Turnaround time between Rx and Tx
sl@0: 	TUint		iTurnaroundMicroSeconds;		// delay after a receive before transmission in us
sl@0: 	TUint		iTurnaroundMinMilliSeconds;		// delay after a receive before transmission in ms
sl@0: 	TUint       iTurnaroundTimerStartTime;      // stores the start time of the turnaround timer.
sl@0: 	TUint8      iTurnaroundTimerStartTimeValid; // stores turnaround timer status 0 after boot, 1 if the timestamp is valid, and 2 if invalid
sl@0: 	TUint8		iTurnaroundTimerRunning;		// a receive has started the timer
sl@0: 	TUint8		iTurnaroundTransmitDelayed;		// a transmission is held until time elapses after a receive
sl@0: 	TUint8		iSpare;
sl@0: 	NTimer	iTurnaroundTimer;				// used to delay transmission after a receive
sl@0: 	TDfc		iTurnaroundDfc;					// used in interrupt space, to trigger a call in user space
sl@0: 
sl@0: 	// RX buffer related items
sl@0: 	TUint8 *iRxCharBuf;			// stores received characters
sl@0: 	TInt iRxBufSize;			// Size of the LDD receive buffer. 
sl@0: 	TUint8 *iRxErrorBuf;		// stores received character error status
sl@0: 	volatile TInt iRxPutIndex;	// Index for next RX char to be stored
sl@0: 	TInt iRxGetIndex;			// Index for next RX char to be retrieved
sl@0: 	TInt iFlowControlLowerThreshold;	// release flow control threshold
sl@0: 	TInt iFlowControlUpperThreshold;	// assert flow control threshold
sl@0: 	TInt iRxDrainThreshold;				// drain rx buffer before completion threshold
sl@0: 	TInt iRxBufCompleteIndex;	// One after last char to be forwarded due to completion
sl@0: 	TBool iInputHeld;			// TRUE if we have asserted flow control
sl@0: 
sl@0: 	// RX client related items
sl@0: 	TClientSingleBufferRequest iRxBufReq;
sl@0: 	TInt iRxDesPos;				// pos of next char to be stored in client descriptor
sl@0: 	TUint8 iRxOutstanding;		// TRUE if a client read is outstanding
sl@0: 	TUint8 iNotifyData;			// TRUE if data available notifier outstanding
sl@0: 	TInt iRxError;
sl@0: 	NTimer iTimer;				// timer for ReadOneOrMore
sl@0: 	TInt iTimeout;				// timeout period for ReadOneOrMore
sl@0: 	TInt iRxOneOrMore;
sl@0: 
sl@0: 	// TX buffer related items
sl@0: 	TUint8 *iTxBuffer;			// stores characters awaiting transmission
sl@0: 	TInt iTxPutIndex;			// Index for next TX char to be stored
sl@0: 	volatile TInt iTxGetIndex;	// Index for next TX char to be output
sl@0: 	TInt iTxBufSize;
sl@0: 	TInt iTxFillThreshold;		// fill tx buffer threshold
sl@0: 	TInt iOutputHeld;			// bits set if peer has asserted flow control
sl@0: 	TInt iJamChar;				// character to jam into TX output stream
sl@0: 
sl@0: 	// TX client related items
sl@0: 	TClientSingleBufferRequest iTxBufReq;
sl@0: 	TInt iTxDesPos;				// pos of next char to be fetched from client descriptor
sl@0: 	TBool iTxOutstanding;		// TRUE if a client write is outstanding
sl@0: 	TInt iTxError;
sl@0: 
sl@0: 	// Signal change notification
sl@0: 	TUint iNotifiedSignals;
sl@0: 	TUint iSigNotifyMask;
sl@0: 	TClientDataRequest<TUint>* iSignalsReq;
sl@0: 
sl@0: 	// hackery
sl@0: 	TVirtualPinObject* iPinObjSetConfig;
sl@0: 	TInt iReceived;
sl@0: 	
sl@0: 	// Break related items
sl@0: 	TInt		 iBreakTimeMicroSeconds;
sl@0: 	TTickLink iBreakTimer; // Used to time how long the break should last for
sl@0: 	TDfc		 iBreakDfc;	
sl@0: 	TClientRequest* iBreakStatus;
sl@0: 	TBool		iBreakDelayedTx;
sl@0: 	TBool		iTurnaroundBreakDelayed;
sl@0: 
sl@0: 	TSpinLock iLock;
sl@0: 	};
sl@0: 
sl@0: /**
sl@0: @internalComponent
sl@0: */
sl@0: class DCommPowerHandler : public DPowerHandler
sl@0: 	{
sl@0: public: // from DPOwerHandler
sl@0: 	void PowerUp();
sl@0: 	void PowerDown(TPowerState);
sl@0: public:
sl@0: 	DCommPowerHandler(DChannelComm* aChannel);
sl@0: public:
sl@0: 	DChannelComm* iChannel;
sl@0: 	};
sl@0: 
sl@0: #include <drivers/comm.inl>
sl@0: 
sl@0: #endif