First public contribution.
1 // Copyright (c) 1995-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.
14 // e32\drivers\ecomm\d_comm.cpp
18 #include <drivers/comm.h>
19 #include <kernel/kern_priv.h>
24 #define LOG_ON(x) Kern::Printf##x
29 //#define __UART_RX_ERROR(x) *(TUint*)0xfeedface=(x)
30 //#define __OVERRUN() *(TUint*)0xfaece5=0
32 #define __UART_RX_ERROR(x)
35 _LIT(KLddName,"Comm");
38 const TUint KXoffSignal=0x80;
40 const TUint KBreaking=0x02;
41 const TUint KBreakPending=0x04;
45 ESetConfigWhileRequestPending,
46 ESetSignalsSetAndClear,
48 ESetReceiveBufferLength,
51 DECLARE_STANDARD_LDD()
53 return new DDeviceComm;
56 DDeviceComm::DDeviceComm()
61 LOG(("DDeviceComm::DDeviceComm"));
62 iParseMask=KDeviceAllowAll;
63 iUnitsMask=0xffffffff; // Leave units decision to the PDD
64 iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
67 TInt DDeviceComm::Install()
69 // Install the device driver.
72 LOG(("DDeviceComm::Install"));
73 return(SetName(&KLddName));
76 void DDeviceComm::GetCaps(TDes8& aDes) const
78 // Return the Comm capabilities.
81 LOG(("DDeviceComm::GetCaps"));
82 TPckgBuf<TCapsDevCommV01> b;
83 b().version=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
84 Kern::InfoCopy(aDes,b);
87 TInt DDeviceComm::Create(DLogicalChannelBase*& aChannel)
89 // Create a channel on the device.
92 LOG(("DDeviceComm::Create"));
93 aChannel=new DChannelComm;
94 return aChannel?KErrNone:KErrNoMemory;
97 DChannelComm::DChannelComm()
101 : iPowerUpDfc(DChannelComm::PowerUpDfc,this,3),
102 iPowerDownDfc(DChannelComm::PowerDownDfc,this,3),
103 iRxDrainDfc(DChannelComm::DrainRxDfc,this,2),
104 iRxCompleteDfc(DChannelComm::CompleteRxDfc,this,2),
105 iTxFillDfc(DChannelComm::FillTxDfc,this,2),
106 iTxCompleteDfc(DChannelComm::CompleteTxDfc,this,2),
107 iTimerDfc(DChannelComm::TimerDfcFn,this,3),
108 iSigNotifyDfc(DChannelComm::SigNotifyDfc,this,2),
109 // iTurnaroundMinMilliSeconds(0),
110 // iTurnaroundTimerRunning(EFalse),
111 // iTurnaroundTransmitDelayed(EFalse),
112 iTurnaroundTimer(DChannelComm::TurnaroundStartDfc, this),
113 iTurnaroundDfc(DChannelComm::TurnaroundTimeout, this, 2),
114 iTimer(DChannelComm::MsCallBack,this),
115 iBreakDfc(DChannelComm::FinishBreakDfc, this, 2),
116 iLock(TSpinLock::EOrderGenericIrqLow3)
118 LOG(("DChannelComm"));
120 // Setup the default config
122 iConfig.iRate=EBps9600;
123 iConfig.iDataBits=EData8;
124 iConfig.iStopBits=EStop1;
125 iConfig.iParity=EParityNone;
126 iConfig.iFifo=EFifoEnable;
127 iConfig.iHandshake=KConfigObeyCTS;
128 iConfig.iParityError=KConfigParityErrorFail;
129 iConfig.iSIREnable=ESIRDisable;
130 // iConfig.iTerminatorCount=0;
131 // iConfig.iTerminator[0]=0;
132 // iConfig.iTerminator[1]=0;
133 // iConfig.iTerminator[2]=0;
134 // iConfig.iTerminator[3]=0;
135 iConfig.iXonChar=0x11; // XON
136 iConfig.iXoffChar=0x13; // XOFF
137 // iConfig.iSpecialRate=0;
138 // iConfig.iParityErrorChar=0;
139 iRxXonChar=0xffffffff;
140 iRxXoffChar=0xffffffff;
146 // iFlowControlSignals=0;
148 // iTerminatorMask[0...31]=0;
155 // iFlowControlLowerThreshold=0;
156 // iFlowControlUpperThreshold=0;
157 // iRxDrainThreshold=0;
158 // iRxBufCompleteIndex=0;
159 // iInputHeld=EFalse;
160 // iRxClientBufReq=NULL;
163 // iRxOutstanding=EFalse;
164 // iRxError=KErrNone;
169 // iTxFillThreshold=0;
175 // iTxOutstanding=EFalse;
176 // iTxError=KErrNone;
179 iTimeout=NKern::TimerTicks(5);
180 iClient=&Kern::CurrentThread();
184 // iSigNotifyStatus=NULL;
186 iNotifiedSignals=0xffffffff;
187 iPinObjSetConfig=NULL;
190 DChannelComm::~DChannelComm()
195 LOG(("~DChannelComm"));
198 iPowerHandler->Remove();
199 delete iPowerHandler;
202 Kern::Free(iRxCharBuf);
204 Kern::Free(iTxBuffer);
206 Kern::DestroyClientRequest(iBreakStatus);
208 Kern::DestroyClientRequest(iSignalsReq);
209 if (iPinObjSetConfig)
210 Kern::DestroyVirtualPinObject(iPinObjSetConfig);
211 Kern::SafeClose((DObject*&)iClient, NULL);
215 void DChannelComm::Complete(TInt aMask, TInt aReason)
217 LOG(("Complete(aMask=%x aReason=%d)", aMask, aReason));
219 iRxBufReq.Complete(iClient, aReason);
221 iTxBufReq.Complete(iClient, aReason);
223 Kern::QueueRequestComplete(iClient, iSignalsReq, aReason);
224 if ((aMask & EBreak) && iBreakStatus && iBreakStatus->IsReady())
225 Kern::QueueRequestComplete(iClient, iBreakStatus, aReason);
228 TInt DChannelComm::Shutdown()
230 __KTRACE_OPT(KPOWER,Kern::Printf("DChannelComm::Shutdown()"));
233 if (iStatus == EActive)
236 Complete(EAll, KErrAbort);
238 // UART interrupts are disabled; must make sure DFCs are not queued.
239 iRxDrainDfc.Cancel();
240 iRxCompleteDfc.Cancel();
242 iTxCompleteDfc.Cancel();
244 iTurnaroundTimer.Cancel();
245 iTurnaroundDfc.Cancel();
247 iSigNotifyDfc.Cancel();
248 iPowerUpDfc.Cancel();
249 iPowerDownDfc.Cancel();
250 iBreakTimer.Cancel();
254 SetSignals(0,iFlowControlSignals|iAutoSignals);
256 return KErrCompletion;
259 TInt DChannelComm::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion &aVer)
261 // Create the channel from the passed info.
264 LOG(("DoCreate(aUnit=%d,...)", aUnit));
265 if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECOMM.LDD (Comm Driver)")))
266 return KErrPermissionDenied;
267 if (!Kern::QueryVersionSupported(TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber),aVer))
268 return KErrNotSupported;
270 // set up the correct DFC queue
271 SetDfcQ(((DComm*)iPdd)->DfcQ(aUnit));
272 iPowerUpDfc.SetDfcQ(iDfcQ);
273 iPowerDownDfc.SetDfcQ(iDfcQ);
274 iRxDrainDfc.SetDfcQ(iDfcQ);
275 iRxCompleteDfc.SetDfcQ(iDfcQ);
276 iTxFillDfc.SetDfcQ(iDfcQ);
277 iTxCompleteDfc.SetDfcQ(iDfcQ);
278 iTimerDfc.SetDfcQ(iDfcQ);
279 iSigNotifyDfc.SetDfcQ(iDfcQ);
280 iTurnaroundDfc.SetDfcQ(iDfcQ);
281 iBreakDfc.SetDfcQ(iDfcQ);
284 // initialise the TX buffer
285 iTxBufSize=KTxBufferSize;
286 iTxBuffer=(TUint8*)Kern::Alloc(iTxBufSize);
289 iTxFillThreshold=iTxBufSize>>1;
291 // initialise the RX buffer
292 iRxBufSize=KDefaultRxBufferSize;
293 iRxCharBuf=(TUint8*)Kern::Alloc(iRxBufSize<<1);
296 iRxErrorBuf=iRxCharBuf+iRxBufSize;
297 iFlowControlLowerThreshold=iRxBufSize>>2;
298 iFlowControlUpperThreshold=3*iRxBufSize>>2;
299 iRxDrainThreshold=iRxBufSize>>1;
301 // Create request objects
302 TInt r = Kern::CreateClientDataRequest(iSignalsReq);
304 r = Kern::CreateClientRequest(iBreakStatus);
306 r = iRxBufReq.Create();
308 r = iTxBufReq.Create();
310 r = Kern::CreateVirtualPinObject(iPinObjSetConfig);
314 ((DComm *)iPdd)->iLdd=this;
315 PddCheckConfig(iConfig);
316 iFailSignals=FailSignals(iConfig.iHandshake);
317 iHoldSignals=HoldSignals(iConfig.iHandshake);
318 iFlowControlSignals=FlowControlSignals(iConfig.iHandshake);
319 iAutoSignals=AutoSignals(iConfig.iHandshake);
321 // create the power handler
322 iPowerHandler=new DCommPowerHandler(this);
325 iPowerHandler->Add();
331 TInt DChannelComm::RequestUserHandle(DThread* aThread, TOwnerType aType)
333 // Ensure that each channel can only be used by a single thread.
334 return (aThread!=iClient) ? KErrAccessDenied : KErrNone;
337 void DChannelComm::MsCallBack(TAny* aPtr)
339 // called from ISR when timer completes
340 DChannelComm *pC=(DChannelComm*)aPtr;
344 void DChannelComm::TimerDfcFn(TAny* aPtr)
346 DChannelComm *pC=(DChannelComm*)aPtr;
350 void DChannelComm::TimerDfc()
352 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
355 if (iRxGetIndex==iRxPutIndex)
357 // buffer empty after timeout period, so complete
358 iRxBufCompleteIndex=iRxPutIndex;
359 iRxOutstanding=EFalse;
361 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
365 // buffer not empty, so drain buffer and requeue timer
366 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
367 DoDrainRxBuffer(iRxPutIndex);
370 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
373 void DChannelComm::DrainRxDfc(TAny* aPtr)
375 DChannelComm *pC=(DChannelComm*)aPtr;
376 pC->DoDrainRxBuffer(pC->iRxPutIndex);
379 // Drain RX buffer in a DFC
380 void DChannelComm::DoDrainRxBuffer(TInt aEndIndex)
382 // if RX completion DFC is queued, leave buffer draining to it
383 if (iRxCompleteDfc.Queued())
386 LOG(("DoDrainRxBuffer(aEndIndex=%d) iRxDesPos=%d iRxBufReq.iLen=%d", aEndIndex, iRxDesPos, iRxBufReq.iLen));
388 // If there's an Rx request with bytes outstanding...
389 if (iRxBufReq.iBuf && iRxDesPos<iRxBufReq.iLen)
391 TInt space=iRxBufReq.iLen-iRxDesPos; // the amount of the client buffer left to fill
392 TInt avail=aEndIndex-iRxGetIndex; // the amount of data in the Rx buffer to copy to the client buffer
393 if (avail<0) // true if the data to drain wraps around the end of the buffer (i.e. the last byte to copy has a linear address less than that of the first byte)
395 TInt len=Min(space,avail); // total number of bytes to drain
397 // Drain up to (but not beyond) the end of the Rx buffer
398 TInt len1=Min(len,iRxBufSize-iRxGetIndex); // number of bytes to the end of the buffer
399 TPtrC8 des(iRxCharBuf+iRxGetIndex,len1);
401 TInt r = Kern::ThreadBufWrite(iClient, iRxBufReq.iBuf, des, iRxDesPos, KChunkShiftBy0, iClient);
409 // Update the client buffer offset and the Rx buffer read pointer with what we've done so far
410 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
413 if (iRxGetIndex>=iRxBufSize)
414 iRxGetIndex-=iRxBufSize;
415 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
417 // If the data wraps around the end of the Rx buffer, now write out the second part
418 // which starts at the beginning of the Rx buffer.
422 des.Set(iRxCharBuf,len);
423 r=Kern::ThreadBufWrite(iClient, iRxBufReq.iBuf, des, iRxDesPos, KChunkShiftBy0, iClient);
431 // Update client buffer offset and Rx buffer read offset
432 irq = __SPIN_LOCK_IRQSAVE(iLock);
435 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
438 // release flow control if necessary
439 if (iInputHeld && RxCount()<=iFlowControlLowerThreshold)
440 ReleaseFlowControl();
442 // if we are doing ReadOneOrMore, start the timer
445 iTimer.OneShot(iTimeout);
451 void DChannelComm::RxComplete()
453 if (NKern::CurrentContext()==NKern::EInterrupt)
454 iRxCompleteDfc.Add();
460 void DChannelComm::CompleteRxDfc(TAny* aPtr)
462 DChannelComm *pC=(DChannelComm*)aPtr;
466 void DChannelComm::DoCompleteRx()
468 LOG(("DoCompleteRx()"));
474 DoDrainRxBuffer(iRxBufCompleteIndex);
475 iRxBufReq.Complete(iClient, iRxError);
479 // start Turnaround timer (got here because it received all data, timed out on a ReadOneOrMore or was terminated
480 // early by FailSignals)
481 RestartTurnaroundTimer();
485 Complete(ERx,KErrNone);
486 // do not start Turnaround (got here on a request Data Available Notification)
491 void DChannelComm::TxComplete()
493 if (NKern::CurrentContext()==NKern::EInterrupt)
494 iTxCompleteDfc.Add();
500 void DChannelComm::FillTxDfc(TAny* aPtr)
502 DChannelComm *pC=(DChannelComm*)aPtr;
503 pC->DoFillTxBuffer();
506 // Fill TX buffer in a DFC
507 void DChannelComm::DoFillTxBuffer()
509 LOG(("DFTB %d =%d",iTxDesPos,iTxBufReq.iLen));
510 if (iTxBufReq.iBuf && iTxDesPos<iTxBufReq.iLen)
512 TInt space=iTxBufSize-TxCount()-1;
513 TInt remaining=iTxBufReq.iLen-iTxDesPos;
514 TInt len=Min(space,remaining); // number of chars to transfer
515 TInt len1=Min(len,iTxBufSize-iTxPutIndex); // number of chars to wrap point
516 TPtr8 des(iTxBuffer+iTxPutIndex,len1,len1);
517 LOG(("DFTxB sp = %d rem = %d iOPH = %d",space, remaining,iOutputHeld));
518 TInt r=Kern::ThreadBufRead(iClient, iTxBufReq.iBuf, des, iTxDesPos, KChunkShiftBy0);
526 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
529 if (iTxPutIndex>=iTxBufSize)
530 iTxPutIndex-=iTxBufSize;
531 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
536 des.Set(iTxBuffer,len,len);
537 r=Kern::ThreadBufRead(iClient, iTxBufReq.iBuf, des, iTxDesPos, KChunkShiftBy0);
545 irq = __SPIN_LOCK_IRQSAVE(iLock);
548 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
550 if (iTxDesPos==iTxBufReq.iLen)
552 // we have used up the client descriptor
553 if (iConfig.iHandshake & KConfigWriteBufferedComplete)
555 iTxOutstanding=EFalse;
559 // if TX buffer not empty and not flow controlled, make sure TX is enabled
560 if (iTxPutIndex!=iTxGetIndex && (!iOutputHeld))
562 LOG(("Calling - DoTxBuff->ETx"));
568 void DChannelComm::CompleteTxDfc(TAny* aPtr)
570 DChannelComm *pC=(DChannelComm*)aPtr;
574 void DChannelComm::DoCompleteTx()
576 Complete(ETx,iTxError);
580 void DChannelComm::Start()
582 // Start the driver receiving.
586 if (iStatus!=EClosed)
588 PddConfigure(iConfig);
591 if ((iConfig.iHandshake & KConfigSendXoff) && iJamChar>=0)
592 EnableTransmit(); // Send XOn if there is one
596 void DChannelComm::BreakOn()
598 // Start the driver breaking.
602 iFlags&=(~KBreakPending);
605 iBreakTimer.OneShot(iBreakTimeMicroSeconds, DChannelComm::FinishBreak, this);
608 void DChannelComm::BreakOff()
610 // Stop the driver breaking.
615 iFlags&=(~(KBreakPending|KBreaking));
618 void DChannelComm::AssertFlowControl()
621 SetSignals(0,iFlowControlSignals);
622 if (iConfig.iHandshake&KConfigSendXoff) // Doing input XON/XOFF
624 iJamChar=iConfig.iXoffChar; // set up to send Xoff
625 EnableTransmit(); // Make sure we are transmitting
629 void DChannelComm::ReleaseFlowControl()
632 SetSignals(iFlowControlSignals,0);
633 if (iConfig.iHandshake&KConfigSendXoff) // Doing input XON/XOFF
635 iJamChar=iConfig.iXonChar; // set up to send Xon
636 EnableTransmit(); // Make sure we are transmitting
640 TInt DChannelComm::SetRxBufferSize(TInt aSize)
642 // Set the receive buffer size.
645 LOG(("SetRxBufferSize(aSize=0x%X)", aSize));
647 TUint8 *newBuf=(TUint8*)Kern::ReAlloc(iRxCharBuf,aSize<<1);
650 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
652 iRxErrorBuf=newBuf+aSize;
654 iFlowControlLowerThreshold=aSize>>2;
655 iFlowControlUpperThreshold=3*aSize>>2;
656 iRxDrainThreshold=aSize>>1;
657 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
658 ResetBuffers(EFalse);
662 TInt DChannelComm::TurnaroundSet(TUint aNewTurnaroundMilliSeconds)
664 LOG(("TurnaroundSet(val=0x%X)", aNewTurnaroundMilliSeconds));
666 iTurnaroundMinMilliSeconds = aNewTurnaroundMilliSeconds;
670 TBool DChannelComm::TurnaroundStopTimer()
671 // Stop the timer and DFC
673 LOG(("TurnaroundStopTimer()"));
675 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
676 TBool result = iTurnaroundTimerRunning;
678 iTurnaroundTimerRunning = EFalse;
679 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
683 iTurnaroundTimer.Cancel();
684 iTurnaroundDfc.Cancel();
689 TInt DChannelComm::TurnaroundClear()
690 // Clear any old timer and start timer based on new turnaround timer
691 // Called for any change: from T > 0 to T == 0 or (T = t1 > 0) to (T = t2 > 0)
692 // POLICY: If a write has already been delayed, it will be started immediately if the requested
693 // turnaround time is elapsed else will only start after it is elapsed.
695 LOG(("TurnaroundClear()"));
699 if(iTurnaroundTimerStartTimeValid == 1)
701 //Calculate the turnaround time elapsed so far.
702 delta = (NKern::TickCount() - iTurnaroundTimerStartTime) * NKern::TickPeriod();
704 if(delta < iTurnaroundMicroSeconds)
706 iTurnaroundMinMilliSeconds = (iTurnaroundMicroSeconds - delta)/1000;
707 iTurnaroundTimerStartTimeValid = 3; //Just to make sure that the turnaround timer start time is not captured.
708 RestartTurnaroundTimer();
712 if(TurnaroundStopTimer())
714 // if a write is waiting, start a DFC to run it
715 TurnaroundStartDfcImplementation(EFalse);
718 iTurnaroundMinMilliSeconds = 0;
722 TInt DChannelComm::RestartTurnaroundTimer()
724 LOG(("RestartTurnaroundTimer()"));
727 // POLICY: if timer is running from a previous read, stop it and re-start it
728 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
729 TBool cancelDfcs = (iTurnaroundMinMilliSeconds > 0) && iTurnaroundTimerRunning;
730 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
733 iTurnaroundTimer.Cancel();
734 iTurnaroundDfc.Cancel();
737 // Start the timer & update driver state to reflect that the timer is running
739 irq = __SPIN_LOCK_IRQSAVE(iLock);
740 if(iTurnaroundMinMilliSeconds > 0)
742 iTurnaroundTimerRunning = ETrue;
743 timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
744 //Record the time stamp of turnaround timer start
745 if(iTurnaroundTimerStartTimeValid != 3)
746 iTurnaroundTimerStartTime = NKern::TickCount();
747 iTurnaroundTimerStartTimeValid = 1;
749 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
751 r=iTurnaroundTimer.OneShot(timeout);
755 void DChannelComm::TurnaroundStartDfc(TAny* aSelf)
757 DChannelComm* self = (DChannelComm*)aSelf;
758 self->TurnaroundStartDfcImplementation(ETrue); // in ISR so Irqs are already disabled
761 void DChannelComm::TurnaroundStartDfcImplementation(TBool aInIsr)
763 LOG(("TurnaroundStartDfcImplementation(inIsr=%d)", aInIsr));
766 irq = __SPIN_LOCK_IRQSAVE(iLock);
770 iTurnaroundTimerRunning = EFalse;
771 if(iTurnaroundTransmitDelayed || iTurnaroundBreakDelayed)
774 iTurnaroundDfc.Add();
778 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
780 __SPIN_UNLOCK(iLock);
781 iTurnaroundDfc.Enque();
786 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
788 __SPIN_UNLOCK(iLock);
791 void DChannelComm::TurnaroundTimeout(TAny* aSelf)
793 DChannelComm* self = (DChannelComm*)aSelf;
794 self->TurnaroundTimeoutImplementation();
797 void DChannelComm::TurnaroundTimeoutImplementation()
799 LOG(("TurnaroundTimeoutImplementation()"));
800 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
802 if(iTurnaroundBreakDelayed)
804 iTurnaroundBreakDelayed=EFalse;
805 if (iStatus==EClosed)
807 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
808 Complete(EBreak, KErrNotReady);
811 else if(IsLineFail(iFailSignals)) // have signals changed in the meantime?
813 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
814 Complete(EBreak, KErrCommsLineFail); // protected -> changed in signals ISR
817 if (iTurnaroundTransmitDelayed)
819 //delay write by break instead of turnaround
820 iBreakDelayedTx = ETrue;
821 iTurnaroundTransmitDelayed=EFalse;
823 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
826 else if(iTurnaroundTransmitDelayed)
828 iTurnaroundTransmitDelayed = EFalse; // protected -> prevent reentrant ISR
829 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
831 RestartDelayedTransmission();
834 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
837 void DChannelComm::ResetBuffers(TBool aResetTx)
839 // Reset the receive and maybe the transmit buffer.
842 LOG(("ResetBuffers(aResetTx=%d)", aResetTx));
843 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
846 iRxBufCompleteIndex=0;
852 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
854 if (iStatus==EActive)
855 ReleaseFlowControl();
859 TInt DChannelComm::TransmitIsr()
861 // Return the next character to be transmitted to the ISR
864 TInt tChar=iJamChar; // Look for control character to jam in
865 if (tChar>=0) // Control character to send
869 else if (!iOutputHeld && iTxGetIndex!=iTxPutIndex)
871 // Get spinlock, disable interrupts to ensure we can reach the unlock
872 // statement. An FIQ before unlock that attempted to get lock would
873 // lead to CPU deadlock
874 TInt irqstate = __SPIN_LOCK_IRQSAVE(iLock);
876 // output not held and buffer not empty, get next char
877 tChar=iTxBuffer[iTxGetIndex++];
878 if (iTxGetIndex==iTxBufSize)
881 __SPIN_UNLOCK_IRQRESTORE(iLock, irqstate);
887 void DChannelComm::ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff)
889 // Handle received character block from the ISR.
890 // aChar points to received characters, aCount=number received,
891 // aXonXoff=1 if XON received, -1 if XOFF received, 0 if neither
896 iOutputHeld &= ~KXoffSignal; // Mark output ok. for XON/XOFF
902 iOutputHeld |= KXoffSignal; // Mark output held for XON/XOFF
904 if (aCount==0) // if only XON or XOFF received
907 // Get spinlock, disable interrupts to ensure we can reach the unlock
908 // statement. An FIQ before unlock that attempted to get lock would
909 // lead to CPU deadlock
910 TInt irqstate = __SPIN_LOCK_IRQSAVE(iLock);
912 TInt count = RxCount();
915 // At or above the high water mark send xoff every other character
916 if (count>=iFlowControlUpperThreshold && ((count&1)!=0 || aCount>1))
919 TUint* pE=aChar+aCount;
925 TInt p=iRxOutstanding?-1:0;
926 TInt thresh=iRxBufReq.iLen-iRxDesPos;
931 // Check for parity errors and replace char if so configured.
932 if (c & KReceiveIsrParityError)
934 // Replace bad character
935 if (iConfig.iParityError==KConfigParityErrorReplaceChar)
936 c = c & ~(0xff|KReceiveIsrParityError) | iConfig.iParityErrorChar;
937 // Ignore parity error
938 if (iConfig.iParityError==KConfigParityErrorIgnore)
939 c = c & ~KReceiveIsrParityError;
944 iRxCharBuf[i]=(TUint8)c;
945 iRxErrorBuf[i]=(TUint8)(c>>24);
947 if (c & KReceiveIsrMaskError)
950 if (c & KReceiveIsrOverrunError)
951 e = KErrCommsOverrun;
952 else if (c & KReceiveIsrBreakError)
954 else if (c & KReceiveIsrFrameError)
956 else if (c & KReceiveIsrParityError)
964 if (e || IsTerminator(TUint8(c)) || count==thresh)
966 // need to complete client request
975 // buffer overrun, discard character
978 // make sure client is informed of overrun error
981 // discard remaining characters and complete
992 // need to complete client request
993 iRxBufCompleteIndex=p;
994 iRxOutstanding=EFalse;
997 else if (count>=iRxDrainThreshold)
999 // drain buffer but don't complete
1002 else if (iRxOneOrMore<0)
1004 // doing read one or more - drain the buffer
1005 // this will start the timer
1011 __SPIN_UNLOCK_IRQRESTORE(iLock, irqstate);
1020 void DChannelComm::CheckTxBuffer()
1022 // if buffer count < threshold, fill from client buffer
1023 TInt count=TxCount();
1024 if (iTxOutstanding && iTxDesPos<iTxBufReq.iLen && count<iTxFillThreshold)
1028 // TX buffer is now empty - see if we need to complete anything
1031 if (iTxBufReq.iLen==0)
1033 // request was a zero-length write - complete if hardware flow control
1035 if ((~iSignals & iHoldSignals)==0)
1037 iTxOutstanding=EFalse;
1043 // request was normal TX - complete now if not doing early completion
1044 if (!(iConfig.iHandshake&KConfigWriteBufferedComplete))
1046 iTxOutstanding=EFalse;
1058 void DChannelComm::UpdateSignals(TUint aSignals)
1060 __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Upd %08x",aSignals));
1061 iSignals=(iSignals&~KDTEInputSignals)|(aSignals&KDTEInputSignals);
1068 Handle a state change from the PDD. Called in ISR or DFC context.
1070 void DChannelComm::StateIsr(TUint aSignals)
1072 iSignals=(iSignals&~KDTEInputSignals)|(aSignals&KDTEInputSignals);
1073 if (iSignalsReq->IsReady() && ((iSignals^iNotifiedSignals)&iSigNotifyMask) )
1075 iSigNotifyDfc.Add();
1077 if (IsLineFail(iFailSignals))
1081 iRxError=KErrCommsLineFail;
1082 iRxBufCompleteIndex=iRxPutIndex;
1083 iRxOutstanding=EFalse;
1088 iTxError = KErrCommsLineFail;
1089 iTxOutstanding=EFalse;
1095 // Now we must determine if output is to be held
1097 TUint status = ~iSignals & iHoldSignals;
1098 if (iOutputHeld & KXoffSignal)
1099 status |= KXoffSignal; // Leave the xon/xoff handshake bit
1101 LOG(("State - ISR - 0x%x",status));
1102 iOutputHeld=status; // record new flow control state
1103 if (iTxGetIndex==iTxPutIndex)
1105 // Tx buffer is empty
1106 if (iTxOutstanding && iTxBufReq.iLen==0 && (status&~KXoffSignal)==0)
1108 // if hardware flow control released, complete zero-length write
1109 iTxOutstanding=EFalse;
1115 // Tx buffer not empty and flow control released, so restart transmission
1116 LOG(("Calling LDD:EnTx"));
1121 // check if transmitter is flow controlled
1122 void DChannelComm::CheckOutputHeld()
1124 iOutputHeld=(iOutputHeld & KXoffSignal) | (~iSignals & iHoldSignals);
1125 LOG(("CheckOPH IOH = %d",iOutputHeld));
1128 void DChannelComm::HandleMsg(TMessageBase* aMsg)
1132 { // postpone message handling to transition from standby
1137 TThreadMessage& m=*(TThreadMessage*)aMsg;
1138 LOG(("HandleMsg(%x a1=%x, a2=%x)", m.iValue, m.Int1(), m.Int2()));
1140 if (id==(TInt)ECloseMsg)
1144 m.Complete(KErrNone, EFalse);
1147 else if (id==KMaxTInt)
1151 m.Complete(KErrNone,ETrue);
1158 DoRequest(~id,m.Ptr1(),m.Ptr2());
1159 m.Complete(KErrNone,ETrue);
1164 TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
1165 m.Complete(r,ETrue);
1169 void DChannelComm::DoCancel(TInt aMask)
1171 // Cancel an outstanding request.
1174 LOG(("DoCancel(%d)", aMask));
1175 if (aMask & RBusDevComm::ERequestReadCancel)
1177 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1178 iRxOutstanding=EFalse;
1184 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1185 iRxCompleteDfc.Cancel();
1186 iRxDrainDfc.Cancel();
1189 Complete(ERx,KErrCancel);
1191 if (aMask & RBusDevComm::ERequestWriteCancel)
1193 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1194 iTurnaroundTransmitDelayed = EFalse;
1197 iTxOutstanding=EFalse;
1201 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1202 iTxCompleteDfc.Cancel();
1203 iTxFillDfc.Cancel();
1204 Complete(ETx,KErrCancel);
1206 if (aMask & RBusDevComm::ERequestNotifySignalChangeCancel)
1208 iSigNotifyDfc.Cancel();
1209 Complete(ESigChg,KErrCancel);
1211 if (aMask & RBusDevComm::ERequestBreakCancel)
1213 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1214 if (iTurnaroundBreakDelayed)
1215 iTurnaroundBreakDelayed=EFalse;
1216 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1219 iBreakTimer.Cancel();
1220 FinishBreakImplementation(KErrCancel);
1225 Intercept messages in client context before they are sent to the DFC queue
1227 TInt DChannelComm::SendMsg(TMessageBase* aMsg)
1232 TThreadMessage* m = (TThreadMessage*)aMsg;
1234 // Handle ECloseMsg & Cancel
1235 TInt id=aMsg->iValue;
1236 if (id==(TInt)ECloseMsg || id==KMaxTInt)
1238 LOG(("SendMsg(%s)", (id==KMaxTInt)?"Cancel":"ECloseMsg"));
1239 // do nothing cos these are handled on the DFC side
1242 // Handle control messages that access user memory here in client context
1245 TAny* a1 = m->iArg[0];
1246 switch (aMsg->iValue)
1248 case RBusDevComm::EControlConfig:
1250 LOG(("SendMsg(EControlConfig, %x)", a1));
1251 TPtrC8 cfg((const TUint8*)&iConfig,sizeof(iConfig));
1252 return Kern::ThreadDesWrite(iClient,a1,cfg,0,KTruncateToMaxLength,iClient);
1254 case RBusDevComm::EControlSetConfig:
1256 LOG(("SendMsg(EControlSetConfig, %x)", a1));
1257 if (AreAnyPending())
1258 ; // r = ESetConfigWhileRequestPending;
1260 r = Kern::PinVirtualMemory(iPinObjSetConfig, (TLinAddr)a1, sizeof(TCommConfigV01));
1263 case RBusDevComm::EControlCaps:
1265 LOG(("SendMsg(EControlCaps, %x)", a1));
1268 return Kern::ThreadDesWrite(iClient,a1,caps,0,KTruncateToMaxLength,iClient);
1271 // Allow other control messages to go to DFC thread
1272 LOG(("SendMsg(Ctrl %d, %x)", aMsg->iValue, a1));
1281 TRequestStatus* status = (TRequestStatus*)m->iArg[0];
1282 TAny* a1 = m->iArg[1];
1283 TAny* a2 = m->iArg[2];
1284 TInt reqNo = ~aMsg->iValue;
1288 case RBusDevComm::ERequestRead:
1291 // If client has *not* provided a buffer pointer, it means they only want
1292 // to know when data becomes available.
1295 irq = __SPIN_LOCK_IRQSAVE(iLock);
1296 TBool isEmpty = (iRxPutIndex==iRxGetIndex);
1297 iNotifyData = isEmpty;
1298 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1299 if (!isEmpty) // if Rx buffer has bytes in it we can complete the request immediately
1301 Kern::RequestComplete(status, KErrNone);
1304 // Do not start the Turnaround timer as this is not a Read request but a request for Data Available notification
1305 LOG(("--Buf Empty--"));
1308 // Get buffer length if one has been given
1310 r = Kern::ThreadRawRead(iClient,a2,&len,sizeof(len));
1312 // Check the client descriptor is valid and large enough to hold the required amount of data.
1313 if (a1 && r==KErrNone)
1315 max = Kern::ThreadGetDesMaxLength(iClient, a1);
1316 if (max<Abs(len) || max<0)
1317 r = KErrGeneral; // do not start the Turnaround timer (invalid Descriptor this read never starts)
1320 LOG(("SendMsg(ERequestRead, %x, len=%d) max=%d r=%d", a1, len, max, r));
1322 // Set client descriptor length to zero & set up client buffer object
1323 if (a1 && r==KErrNone)
1326 r = Kern::ThreadDesWrite(iClient,a1,p,0,0,iClient);
1328 r = iRxBufReq.Setup(status, a1, len);
1337 case RBusDevComm::ERequestWrite:
1338 if (iStatus==EClosed)
1343 r=Kern::ThreadRawRead(iClient, a2, &len, sizeof(len));
1344 LOG(("SendMsg(ERequestWrite, %x, len=%d) r=%d", a1, len, r));
1346 // Setup pending client request for this write
1348 r = iTxBufReq.Setup(status, a1, len);
1353 // ERequestBreak: a1 points to the number of microseconds to break for
1355 case RBusDevComm::ERequestBreak:
1356 r = Kern::ThreadRawRead(iClient, a1, &iBreakTimeMicroSeconds, sizeof(TInt));
1358 r = iBreakStatus->SetStatus(status);
1359 LOG(("SendMsg(ERequestBreak, %x) bktime=%d r=%d", a1, iBreakTimeMicroSeconds, r));
1364 // ERequestNotifySignalChange: a1 points to user-side int to receive the signals bitmask
1365 // a2 points to the bitmask of signals the user is interested in
1367 case RBusDevComm::ERequestNotifySignalChange:
1368 LOG(("SendMsg(ERequestNotifySignalChange, %x, %x)", a1, a2));
1374 // Setup word-sized client buffer
1375 r = Kern::ThreadRawRead(iClient,a2,&iSigNotifyMask,sizeof(TUint));
1376 irq = __SPIN_LOCK_IRQSAVE(iLock);
1379 r = iSignalsReq->SetStatus(status);
1381 iSignalsReq->SetDestPtr(a1);
1383 LOG(("ERequestNotifySignalChange: mask is %x, r is %d", iSigNotifyMask, r));
1384 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1390 LOG(("SendMsg(req %d, %x, %x)", reqNo, a1, a2));
1391 r = KErrNotSupported;
1396 // If the request has an error, complete immediately
1398 Kern::RequestComplete(status, r);
1401 // Send the client request to the DFC queue unless there's been an error
1403 r = DLogicalChannel::SendMsg(aMsg);
1404 LOG(("<SendMsg ret %d", r));
1411 Handle asynchronous requests. Called in DFC context.
1413 void DChannelComm::DoRequest(TInt aReqNo, TAny* a1, TAny* a2)
1415 LOG(("DoRequest(%d %x %x)", aReqNo, a1, a2));
1418 // First check if we have started
1424 SetSignals(iAutoSignals,0);
1426 ReleaseFlowControl();
1429 // Check for a line fail
1431 if (IsLineFail(iFailSignals))
1433 Complete(EAll, KErrCommsLineFail);
1438 // Now we can dispatch the async request
1442 case RBusDevComm::ERequestRead:
1443 InitiateRead(iRxBufReq.iLen);
1446 case RBusDevComm::ERequestWrite:
1449 // See if we need to delay the write
1450 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1451 iTurnaroundTransmitDelayed = iTurnaroundTimerRunning!=0;
1452 iBreakDelayedTx = (iFlags & KBreaking);
1453 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1455 // If we do need to delay the write
1456 if (iTurnaroundTransmitDelayed || iBreakDelayedTx)
1464 case RBusDevComm::ERequestNotifySignalChange:
1465 iNotifiedSignals = iSignals;
1469 case RBusDevComm::ERequestBreak:
1470 if(iTurnaroundTimerRunning)
1471 iTurnaroundBreakDelayed = ETrue;
1480 Called in DFC context upon receipt of ERequestRead
1482 void DChannelComm::InitiateRead(TInt aLength)
1484 LOG(("InitiateRead(%d)", aLength));
1485 iRxOutstanding=EFalse;
1488 // Complete zero-length read immediately
1491 iRxBufReq.Complete(iClient, KErrNone);
1492 RestartTurnaroundTimer();
1496 TBool length_negative = (aLength<0);
1497 if (length_negative)
1499 iRxBufReq.iLen=aLength;
1501 // If the RX buffer is empty, we must wait for more data
1502 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1503 if (iRxPutIndex==iRxGetIndex)
1505 if (length_negative)
1506 iRxOneOrMore=-1; // -1 because timer not started
1507 iRxOutstanding=ETrue;
1508 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1511 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1513 // RX buffer contains characters, must scan buffer and then complete
1514 if (length_negative)
1516 // ReceiveOneOrMore, up to -aLength characters
1519 TInt getIndex=iRxGetIndex;
1522 TBool complete=EFalse;
1525 while(count<aLength && getIndex!=iRxPutIndex)
1527 if ((stat=iRxErrorBuf[getIndex])!=0 || IsTerminator(iRxCharBuf[getIndex]))
1529 // this character will complete the request
1530 if (++getIndex==iRxBufSize)
1536 if (++getIndex==iRxBufSize)
1544 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1545 if (getIndex==iRxPutIndex)
1547 // not enough chars to complete request, so set up to wait for more
1548 iRxOutstanding=ETrue;
1549 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1551 DoDrainRxBuffer(getIndex);
1554 // more characters have arrived, loop again
1555 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1559 // can complete request right now
1564 if (stat & KReceiveIsrOverrunError)
1565 e = KErrCommsOverrun;
1566 else if (stat & KReceiveIsrBreakError)
1568 else if (stat & KReceiveIsrFrameError)
1570 else if (stat & KReceiveIsrParityError)
1571 e = KErrCommsParity;
1573 if (iRxError==KErrNone)
1575 iRxBufCompleteIndex=getIndex;
1580 Called in DFC context to start a write or a delayed write
1582 void DChannelComm::InitiateWrite()
1584 LOG(("InitiateWrite() len=%d", iTxBufReq.iLen));
1587 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1589 iTurnaroundTimerStartTime = 0;
1590 iTurnaroundTimerStartTimeValid = 2;
1591 if (~iSignals & iFailSignals)
1593 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1594 iTxBufReq.Complete(iClient, KErrCommsLineFail);
1597 if (iTxBufReq.iLen==0)
1599 if (iTxPutIndex==iTxGetIndex && (~iSignals & iHoldSignals)==0)
1601 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1602 iTxBufReq.Complete(iClient, KErrNone);
1607 iTxOutstanding=ETrue;
1608 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1609 if (iTxBufReq.iLen!=0)
1613 void DChannelComm::SigNotifyDfc(TAny* aPtr)
1615 ((DChannelComm*)aPtr)->DoSigNotify();
1618 void DChannelComm::DoSigNotify()
1620 // Atomically update iNotifiedSignals and prepare to signal
1621 TBool do_notify = EFalse;
1622 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1623 TUint orig_sig=iNotifiedSignals;
1624 if (iSignalsReq->IsReady() && ( iNotifiedSignals==0xffffffff || ((iSignals^iNotifiedSignals)&iSigNotifyMask) ) )
1626 iNotifiedSignals=iSignals;
1629 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1630 __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Orig=%08x New %08x Mask %08x",orig_sig,iNotifiedSignals,iSigNotifyMask));
1633 TUint changed=iSigNotifyMask;
1634 if (orig_sig!=0xffffffff)
1635 changed&=(orig_sig^iNotifiedSignals);
1636 changed=(changed<<12)|(iNotifiedSignals&iSigNotifyMask);
1638 // Write the result back to client memory and complete the request
1639 __KTRACE_OPT(KHARDWARE,Kern::Printf("CommSig: Notify %08x",changed));
1640 LOG(("DoSigNotify: %08x",changed));
1641 TUint& rr = iSignalsReq->Data();
1643 Kern::QueueRequestComplete(iClient, iSignalsReq, KErrNone);
1649 Manually read and act on signals
1651 void DChannelComm::UpdateAndProcessSignals()
1653 TUint signals=Signals();
1654 TBool notify=EFalse;
1655 TBool complete_rx=EFalse;
1656 TBool complete_tx=EFalse;
1657 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
1658 iSignals=(iSignals&~KDTEInputSignals)|(signals&KDTEInputSignals);
1659 if (iSignalsReq->IsReady() && ((iSignals^iNotifiedSignals)&iSigNotifyMask) )
1663 if (IsLineFail(iFailSignals))
1667 iRxError=KErrCommsLineFail;
1668 iRxBufCompleteIndex=iRxPutIndex;
1669 iRxOutstanding=EFalse;
1674 iTxError = KErrCommsLineFail;
1675 iTxOutstanding=EFalse;
1680 // Now we must determine if output is to be held
1682 TUint status = ~iSignals & iHoldSignals;
1683 if (iOutputHeld & KXoffSignal)
1684 status |= KXoffSignal; // Leave the xon/xoff handshake bit
1686 iOutputHeld=status; // record new flow control state
1687 if (iTxGetIndex==iTxPutIndex)
1689 // Tx buffer is empty
1690 if (iTxOutstanding && iTxBufReq.iLen==0 && (status&~KXoffSignal)==0)
1692 // if hardware flow control released, complete zero-length write
1693 iTxOutstanding=EFalse;
1699 // Tx buffer not empty and flow control released, so restart transmission
1702 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1712 TUint DChannelComm::FailSignals(TUint aHandshake)
1715 if ((aHandshake&(KConfigObeyCTS|KConfigFailCTS))==(KConfigObeyCTS|KConfigFailCTS))
1717 if ((aHandshake&(KConfigObeyDSR|KConfigFailDSR))==(KConfigObeyDSR|KConfigFailDSR))
1719 if ((aHandshake&(KConfigObeyDCD|KConfigFailDCD))==(KConfigObeyDCD|KConfigFailDCD))
1724 TUint DChannelComm::HoldSignals(TUint aHandshake)
1727 if (aHandshake & KConfigObeyCTS)
1729 if (aHandshake & KConfigObeyDSR)
1731 if (aHandshake & KConfigObeyDCD)
1736 TUint DChannelComm::FlowControlSignals(TUint aHandshake)
1739 if (!(aHandshake & KConfigFreeRTS))
1741 else if (!(aHandshake & KConfigFreeDTR))
1746 TUint DChannelComm::AutoSignals(TUint aHandshake)
1749 if (!(aHandshake & KConfigFreeRTS) && !(aHandshake & KConfigFreeDTR))
1754 TInt DChannelComm::SetConfig(TCommConfigV01& c)
1756 LOG(("SetConfig(...)"));
1757 TBool restart = EFalse;
1758 TBool purge = EFalse;
1759 TBool changeTerminators=EFalse;
1763 if(c.iTerminatorCount>KConfigMaxTerminators)
1764 return KErrNotSupported;
1765 if ((r=ValidateConfig(c))!=KErrNone)
1767 TUint failSignals=FailSignals(c.iHandshake);
1768 if (IsLineFail(failSignals))
1769 return KErrCommsLineFail;
1770 if (iConfig.iRate != c.iRate
1771 || iConfig.iDataBits != c.iDataBits
1772 || iConfig.iStopBits != c.iStopBits
1773 || iConfig.iParity != c.iParity
1774 || iConfig.iFifo != c.iFifo
1775 || iConfig.iSpecialRate != c.iSpecialRate
1776 || iConfig.iSIREnable != c.iSIREnable
1777 || iConfig.iSIRSettings != c.iSIRSettings)
1781 else if (iConfig.iParityErrorChar != c.iParityErrorChar
1782 || iConfig.iParityError != c.iParityError
1783 || iConfig.iXonChar != c.iXonChar
1784 || iConfig.iXoffChar != c.iXoffChar
1785 || (iConfig.iHandshake&(KConfigObeyXoff|KConfigSendXoff))
1786 != (c.iHandshake&(KConfigObeyXoff|KConfigSendXoff)))
1792 if (iConfig.iTerminatorCount==c.iTerminatorCount)
1794 for (TInt i=0; i<iConfig.iTerminatorCount; i++)
1796 if (iConfig.iTerminator[i]!=c.iTerminator[i])
1798 changeTerminators=ETrue;
1804 changeTerminators=ETrue;
1805 if (!changeTerminators && c.iHandshake == iConfig.iHandshake)
1806 return r; // nothing to do.
1808 if (iStatus==EActive && (restart || purge))
1810 SetSignals(0,iFlowControlSignals|iAutoSignals); // Drop RTS
1814 ResetBuffers(ETrue);
1816 iFailSignals=failSignals;
1817 iHoldSignals=HoldSignals(c.iHandshake);
1818 iFlowControlSignals=FlowControlSignals(c.iHandshake);
1819 iAutoSignals=AutoSignals(c.iHandshake);
1822 SetSignals(iFlowControlSignals|iAutoSignals,0); // Assert RTS
1823 irq = __SPIN_LOCK_IRQSAVE(iLock);
1827 irq = __SPIN_LOCK_IRQSAVE(iLock);
1829 ResetBuffers(ETrue);
1831 iFailSignals=failSignals;
1832 iHoldSignals=HoldSignals(c.iHandshake);
1833 iFlowControlSignals=FlowControlSignals(c.iHandshake);
1834 iAutoSignals=AutoSignals(c.iHandshake);
1836 if (iConfig.iHandshake&KConfigObeyXoff)
1838 iRxXonChar=c.iXonChar;
1839 iRxXoffChar=c.iXoffChar;
1843 iRxXonChar=0xffffffff;
1844 iRxXoffChar=0xffffffff;
1845 iOutputHeld&=~KXoffSignal;
1847 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
1848 if (iStatus==EActive)
1849 ReleaseFlowControl();
1851 // no request pending here, so no need to protect this against interrupts
1852 if (restart || purge || changeTerminators)
1854 memclr(iTerminatorMask, 32);
1856 for (i=0; i<iConfig.iTerminatorCount; i++)
1858 SetTerminator(iConfig.iTerminator[i]);
1864 TInt DChannelComm::DoControl(TInt aFunction, TAny* a1, TAny* a2)
1869 LOG(("DoControl(aFunction=%d, a1=%x, a2=%x)", aFunction, a1, a2));
1875 case RBusDevComm::EControlSetConfig:
1878 memclr(&c, sizeof(c));
1879 TPtr8 cfg((TUint8*)&c,0,sizeof(c));
1880 r=Kern::ThreadDesRead(iClient,a1,cfg,0,0);
1884 Kern::UnpinVirtualMemory(iPinObjSetConfig);
1887 case RBusDevComm::EControlSignals:
1889 UpdateAndProcessSignals();
1893 case RBusDevComm::EControlSetSignals:
1895 TUint set=(TUint)a1;
1896 TUint clear=(TUint)a2;
1898 ;// Kern::PanicCurrentThread(_L("D32COMM"), ESetSignalsSetAndClear);
1904 if (!(iConfig.iHandshake & KConfigFreeDTR) && !(clear & KSignalDTR))
1905 set|=KSignalDTR; // Assert DTR
1906 if (!(iConfig.iHandshake & KConfigFreeRTS) && !(clear & KSignalRTS))
1907 set|=KSignalRTS; // Assert RTS
1908 if (iConfig.iHandshake & KConfigSendXoff)
1909 iJamChar=iConfig.iXonChar;
1910 iInputHeld = EFalse;
1913 __e32_atomic_axo_ord32(&iSignals, ~(clear|set), set);
1914 SetSignals(set,clear);
1918 case RBusDevComm::EControlQueryReceiveBuffer:
1921 case RBusDevComm::EControlResetBuffers:
1922 if (AreAnyPending())
1923 ;// Kern::PanicCurrentThread(_L("D32COMM"), EResetBuffers);
1925 ResetBuffers(ETrue);
1927 case RBusDevComm::EControlReceiveBufferLength:
1931 case RBusDevComm::EControlSetReceiveBufferLength:
1932 if (AreAnyPending())
1933 ;// iThread->Panic(_L("D32COMM"),ESetReceiveBufferLength);
1935 r=SetRxBufferSize((TInt)a1);
1937 // ***************************************
1939 case RBusDevComm::EControlMinTurnaroundTime:
1940 r = iTurnaroundMicroSeconds; // used saved value
1943 case RBusDevComm::EControlSetMinTurnaroundTime:
1947 iTurnaroundMicroSeconds = (TUint)a1; // save this
1948 TUint newTurnaroundMilliSeconds = (TUint)a1/1000; // convert to ms
1949 if(newTurnaroundMilliSeconds != iTurnaroundMinMilliSeconds)
1951 // POLICY: if a new turnaround time is set before the previous running timer has expired
1952 // then the timer is adjusted depending on the new value and if any
1953 // write request has been queued, transmission will proceed after the timer has expired.
1954 if(iTurnaroundTimerStartTimeValid == 0)
1956 iTurnaroundTimerStartTimeValid = 1;
1957 iTurnaroundTimerStartTime = NKern::TickCount();
1959 if(iTurnaroundTimerStartTimeValid != 2)
1961 if(newTurnaroundMilliSeconds > 0)
1963 r = TurnaroundSet(newTurnaroundMilliSeconds);
1974 void DChannelComm::DoPowerUp()
1976 // Called at switch on and upon Opening.
1979 LOG(("DoPowerUp()"));
1980 __KTRACE_OPT(KPOWER,Kern::Printf("DChannelComm::DoPowerUp()"));
1982 ResetBuffers(ETrue);
1983 iRxOutstanding=EFalse;
1985 iTxOutstanding=EFalse;
1989 // Cancel turnaround
1990 iTurnaroundMinMilliSeconds = 0;
1991 iTurnaroundTimerRunning = EFalse;
1992 iTurnaroundTransmitDelayed = EFalse;
1994 // cancel any DFCs/timers
1995 iRxDrainDfc.Cancel();
1996 iRxCompleteDfc.Cancel();
1997 iTxFillDfc.Cancel();
1998 iTxCompleteDfc.Cancel();
2000 iTurnaroundTimer.Cancel();
2001 iTurnaroundDfc.Cancel();
2003 iSigNotifyDfc.Cancel();
2005 Complete(EAll, KErrAbort);
2006 if (!Kern::PowerGood())
2008 TUint hand=iConfig.iHandshake;
2009 if (hand&(KConfigFreeRTS|KConfigFreeDTR))
2012 if (!Kern::PowerGood())
2014 if (hand&KConfigFreeRTS)
2016 if (iSignals&KSignalRTS)
2017 SetSignals(KSignalRTS,0);
2019 SetSignals(0,KSignalRTS);
2021 if (!Kern::PowerGood())
2023 if (hand&KConfigFreeDTR)
2025 if (iSignals&KSignalDTR)
2026 SetSignals(KSignalDTR,0);
2028 SetSignals(0,KSignalDTR);
2034 if (iStatus==EActive)
2039 void DChannelComm::PowerUpDfc(TAny* aPtr)
2042 DChannelComm* d = (DChannelComm*)aPtr;
2043 __PM_ASSERT(d->iStandby);
2044 if (d->iStatus != EClosed)
2047 // There is racing Close(): driver was already closed (ECloseMsg) but the DPowerHandler was not destroyed yet.
2049 d->iStandby = EFalse;
2050 d->iPowerHandler->PowerUpDone();
2053 __PM_ASSERT(d->iStatus != EClosed);
2054 d->iMsgHeld = EFalse;
2055 d->HandleMsg(d->iMsgQ.iMessage);
2059 void DChannelComm::PowerDownDfc(TAny* aPtr)
2061 DChannelComm* d = (DChannelComm*)aPtr;
2062 __PM_ASSERT(!d->iStandby);
2063 d->iStandby = ETrue;
2064 if (d->iStatus != EClosed)
2067 // There is racing Close(): driver was already closed (ECloseMsg) but the DPowerHandler was not destroyed yet.
2069 d->iPowerHandler->PowerDownDone();
2072 DCommPowerHandler::DCommPowerHandler(DChannelComm* aChannel)
2073 : DPowerHandler(KLddName),
2078 void DCommPowerHandler::PowerUp()
2080 iChannel->iPowerUpDfc.Enque();
2083 void DCommPowerHandler::PowerDown(TPowerState)
2085 iChannel->iPowerDownDfc.Enque();
2088 void DChannelComm::FinishBreak(TAny* aSelf)
2090 DChannelComm* self = (DChannelComm*)aSelf;
2091 self->QueueFinishBreakDfc();
2094 void DChannelComm::QueueFinishBreakDfc()
2100 void DChannelComm::FinishBreakDfc(TAny* aSelf)
2102 DChannelComm* self = (DChannelComm*)aSelf;
2103 self->FinishBreakImplementation(KErrNone);
2106 void DChannelComm::FinishBreakImplementation(TInt aError)
2108 if (iStatus==EClosed)
2110 Complete(EBreak, KErrNotReady);
2115 Complete(EBreak, aError);
2118 // re-setup transmission if needed, for writes after a break
2119 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
2120 if (iBreakDelayedTx)
2122 iBreakDelayedTx = EFalse; // protected -> prevent reentrant ISR
2123 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
2125 RestartDelayedTransmission();
2128 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
2130 void DChannelComm::RestartDelayedTransmission()
2132 LOG(("RestartDelayedTransmission()"));
2133 TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
2134 TBool completeTx=EFalse;
2136 iBreakDelayedTx = EFalse; // protected -> prevent reentrant ISR
2137 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
2139 if (iStatus==EClosed)
2141 irq = __SPIN_LOCK_IRQSAVE(iLock);
2142 iTxError = KErrNotReady; // protected -> changed in signals ISR
2146 else if(IsLineFail(iFailSignals)) // have signals changed in the meantime?
2148 irq = __SPIN_LOCK_IRQSAVE(iLock);
2149 iTxError = KErrCommsLineFail; // protected -> changed in signals ISR
2161 iTxError = KErrNone;
2162 __SPIN_UNLOCK_IRQRESTORE(iLock, irq);
2163 Complete(ETx, iTxError);