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