os/boardsupport/emulator/emulatorbsp/specific/serialldd.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-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 "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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // wins/specific/serialldd.cpp
    15 // 
    16 //
    17 
    18 #include "winscomm.h"
    19 #include <kernel/kern_priv.h>
    20 #include <e32hal.h>
    21 #include <e32uid.h>
    22 
    23 _LIT(KLddName,"Comm");
    24 
    25 const TUint KBreaking=0x02;
    26 const TUint KBreakPending=0x04;
    27 
    28 
    29 enum TPanic
    30 	{
    31 	ESetConfigWhileRequestPending,
    32 	ESetSignalsSetAndClear,
    33 	EResetBuffers,
    34 	ESetReceiveBufferLength,
    35 	};
    36 
    37 
    38 inline TUint32 SafeSwap(TUint32 aNewValue, TUint32& aWord)
    39 	{ return __e32_atomic_swp_ord32(&aWord, aNewValue); }
    40 
    41 DECLARE_STANDARD_LDD()
    42 	{
    43 	return new DDeviceComm;
    44 	}
    45 
    46 
    47 DDeviceComm::DDeviceComm()
    48 	{
    49 	iParseMask = KDeviceAllowAll;
    50 	iUnitsMask = 0xffffffff; // Leave units decision to the PDD
    51 	iVersion = TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
    52 	}
    53 
    54 TInt DDeviceComm::Install()
    55 	{
    56 	return(SetName(&KLddName));
    57 	}
    58 
    59 void DDeviceComm::GetCaps(TDes8& aDes) const
    60 	{
    61 	TPckgBuf<TCapsDevCommV01> b;
    62 	b().version = TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
    63 	Kern::InfoCopy(aDes,b);
    64 	}
    65 
    66 TInt DDeviceComm::Create(DLogicalChannelBase*& aChannel)
    67 	{
    68 	aChannel = new DChannelComm;
    69 	return aChannel?KErrNone:KErrNoMemory;
    70 	}
    71 
    72 
    73 DChannelComm::DChannelComm()
    74 	:
    75 		iRxCompleteDfc(DChannelComm::CompleteRxDfc,this,2),
    76 		iTxCompleteDfc(DChannelComm::CompleteTxDfc,this,2),
    77 		iRxDataAvailableDfc(DChannelComm::RxDataAvailableDfc,this,2),
    78 		iSigNotifyDfc(DChannelComm::SignalNotifyDfc,this,2),
    79 //		iBreakMinMilliSeconds(0),
    80 //		iTurnaroundTimerRunning(EFalse),
    81 //		iTurnaroundTransmitDelayed(EFalse),
    82 		iTurnaroundTimer(DChannelComm::TurnaroundStartDfc, this),
    83 		iTurnaroundDfc(DChannelComm::TurnaroundTimeout, this, 2),
    84 //		iTurnaroundTxDesPtr(0),
    85 //		iTurnaroundTxDesLength(0)
    86 		iBreakDfc(DChannelComm::FinishBreakDfc, this, 2)
    87 	{
    88 	iConfig.iRate = EBps9600;
    89 	iConfig.iDataBits = EData8;
    90 	iConfig.iStopBits = EStop1;
    91 	iConfig.iParity = EParityNone;
    92 	iConfig.iHandshake = KConfigObeyCTS;
    93 	iConfig.iParityError = KConfigParityErrorFail;
    94 	iConfig.iFifo = EFifoEnable;
    95 	iConfig.iTerminatorCount = 0;
    96 	iConfig.iXonChar = 0x11;
    97 	iConfig.iXoffChar = 0x13;
    98 	iConfig.iSIREnable = ESIRDisable;
    99 
   100 	iTxError = KErrNone;
   101 	iRxError = KErrNone;
   102 	iRxDAError = KErrNone;
   103 	iSignalError = KErrNone;
   104 	iClientDestPtr = 0;
   105 	iClientSignalResultPtr = 0;
   106 	iClient = &Kern::CurrentThread();
   107 	iClient->Open();
   108 	}
   109 
   110 
   111 DChannelComm::~DChannelComm()
   112 	{
   113 	Kern::SafeClose((DObject*&)iClient, NULL);
   114 	}
   115 
   116 void DChannelComm::Shutdown()
   117 	{
   118 	// clean-up...
   119 	if (iStatus == EActive)
   120 		Stop(EStopPwrDown);			// stop PDD
   121 
   122 	Complete(EAll, KErrAbort);
   123 
   124 	iRxCompleteDfc.Cancel();
   125 	iTxCompleteDfc.Cancel();
   126 	iTurnaroundTimer.Cancel();
   127 	iTurnaroundDfc.Cancel();
   128 	iSigNotifyDfc.Cancel();
   129 	iRxDataAvailableDfc.Cancel();
   130 	iBreakTimer.Cancel();
   131 	iBreakDfc.Cancel();
   132 	}
   133 
   134 TInt DChannelComm::TurnaroundSet(TUint aNewTurnaroundMilliSeconds)
   135 	{
   136 	TInt r = KErrNone;
   137 	iTurnaroundMinMilliSeconds = aNewTurnaroundMilliSeconds;
   138 	return r;
   139 	}
   140 
   141 TBool DChannelComm::TurnaroundStopTimer()
   142 // Stop the timer and DFC
   143 	{
   144 	TInt irq = 0;
   145 	irq = NKern::DisableInterrupts(1);
   146 	TBool result = iTurnaroundTimerRunning;
   147 	if(result)
   148 		{
   149 		iTurnaroundTimerRunning = EFalse;
   150 		iTurnaroundTimer.Cancel();
   151 		iTurnaroundDfc.Cancel();
   152 		}
   153 	NKern::RestoreInterrupts(irq);
   154 	return result;
   155 	}
   156 
   157 TInt DChannelComm::TurnaroundClear()
   158 // Clear any old timer and start timer based on new turnaround value.
   159 // Called for any change: from T > 0 to T == 0 or (T = t1 > 0) to (T = t2 > 0)
   160 // POLICY: If a write has already been delayed, it will be started immediately if the requested 
   161 //  turnaround time is elapsed else will only start after it is elapsed.
   162 	{
   163 	TInt r = KErrNone;
   164 	TUint delta = 0;
   165 
   166     if(iTurnaroundTimerStartTimeValid == 1)
   167 		{
   168 		//Calculate the turnaround time elapsed so far
   169 		delta = (NKern::TickCount() - iTurnaroundTimerStartTime) * NKern::TickPeriod();
   170 		}
   171 	if(delta < iTurnaroundMicroSeconds)
   172 		{
   173         iTurnaroundMinMilliSeconds = (iTurnaroundMicroSeconds - delta) / 1000;
   174       	TInt irq = NKern::DisableInterrupts(1);
   175 		// POLICY: if timer is running from a previous read, stop it and re-start it
   176 		if(iTurnaroundTimerRunning)
   177 			{
   178 			iTurnaroundTimer.Cancel();
   179 			iTurnaroundDfc.Cancel();
   180 			}
   181 		iTurnaroundTimerRunning = ETrue;
   182 		TInt timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
   183 		iTurnaroundTimer.OneShot(timeout);
   184     	NKern::RestoreInterrupts(irq);
   185 	    }
   186     else
   187 		{
   188 		if(TurnaroundStopTimer())
   189 			{
   190 			// if a write is waiting, start a DFC to run it
   191 			TurnaroundStartDfcImplementation(EFalse);
   192 			}
   193 		}
   194 	iTurnaroundMinMilliSeconds = 0;
   195 	return r;
   196 	}
   197 
   198 void DChannelComm::TurnaroundStartDfc(TAny* aSelf)
   199 	{
   200 	DChannelComm* self = (DChannelComm*)aSelf;
   201 	self->TurnaroundStartDfcImplementation(ETrue);
   202 	}
   203 
   204 void DChannelComm::TurnaroundStartDfcImplementation(TBool inIsr)
   205 	{
   206 	TInt irq = 0;
   207 	if(!inIsr)
   208 		{
   209 		irq = NKern::DisableInterrupts(1);
   210 		}
   211 	iTurnaroundTimerRunning = EFalse;
   212 	if(iTurnaroundTransmitDelayed || iTurnaroundBreakDelayed)
   213 		{
   214 		if(inIsr)
   215 			iTurnaroundDfc.Add();
   216 		else
   217 			{
   218 			NKern::RestoreInterrupts(irq);
   219 			iTurnaroundDfc.Enque();
   220 			}
   221 		return;
   222 		}
   223 	if(!inIsr)
   224 		{
   225 		NKern::RestoreInterrupts(irq);
   226 		}
   227 	}
   228 
   229 void DChannelComm::TurnaroundTimeout(TAny* aSelf)
   230 	{
   231 	DChannelComm* self = (DChannelComm*)aSelf;
   232 	self->TurnaroundTimeoutImplementation();
   233 	}
   234 
   235 void DChannelComm::TurnaroundTimeoutImplementation(void)
   236 	{
   237 	TInt irq = NKern::DisableInterrupts(1);
   238 	if (iTurnaroundBreakDelayed)
   239 		{
   240 		iTurnaroundBreakDelayed=EFalse;
   241 		if (iStatus==EClosed)
   242 			{
   243             NKern::RestoreInterrupts(irq);
   244 			Complete(EBreak, KErrNotReady);
   245 			return;
   246 			}
   247 
   248 		if (LineFail())
   249 			{
   250             NKern::RestoreInterrupts(irq);
   251 			Complete(EBreak, KErrCommsLineFail);
   252 			return;
   253 			}
   254 
   255 		if (iTurnaroundTransmitDelayed)
   256 			{
   257 			//delay write by break instead of turnaround
   258 			iBreakDelayedTx = ETrue;
   259 			iBreakDelayedTxDesPtr = iTurnaroundTxDesPtr;
   260 			iBreakDelayedTxDesLength = iTurnaroundTxDesLength;
   261 			iTurnaroundTxDesPtr=0;
   262 			iTurnaroundTxDesLength=0;
   263 			iTurnaroundTransmitDelayed=EFalse;
   264 			}
   265         NKern::RestoreInterrupts(irq);
   266 		BreakOn();
   267 		}
   268 	else if(iTurnaroundTransmitDelayed)
   269 		{
   270 		iTurnaroundTransmitDelayed = EFalse;	// protected -> prevent reentrant ISR
   271 		NKern::RestoreInterrupts(irq);
   272 		if (iStatus==EClosed)
   273 			{
   274 			iTurnaroundTxDesPtr = 0;
   275 			iTurnaroundTxDesLength = 0;
   276 			Complete(ETx,KErrNotReady);
   277 			return;
   278 			}
   279 
   280 		// fail signals checked in the PDD
   281 		InitiateWrite(iTurnaroundTxDesPtr, iTurnaroundTxDesLength);
   282 		iTurnaroundTimerStartTime = 0;
   283 		iTurnaroundTimerStartTimeValid = 2;
   284 		iTurnaroundTxDesPtr = 0;
   285 		iTurnaroundTxDesLength = 0;
   286 		}
   287 	else 
   288 		NKern::RestoreInterrupts(irq);
   289 	}
   290 
   291 TInt DChannelComm::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion &aVer)
   292 	{
   293 	if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECOMM.LDD (Comm Driver)")))
   294 		return KErrPermissionDenied;
   295 	if (!Kern::QueryVersionSupported(TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber),aVer))
   296 		return KErrNotSupported;
   297 
   298 	// set up the correct DFC queue
   299 	SetDfcQ(((DComm*)iPdd)->DfcQ(aUnit));
   300 	iRxCompleteDfc.SetDfcQ(iDfcQ);
   301 	iTxCompleteDfc.SetDfcQ(iDfcQ);
   302 	iRxDataAvailableDfc.SetDfcQ(iDfcQ);
   303 	iSigNotifyDfc.SetDfcQ(iDfcQ);
   304 	iTurnaroundDfc.SetDfcQ(iDfcQ);
   305 	iBreakDfc.SetDfcQ(iDfcQ);
   306 	iMsgQ.Receive();
   307 
   308 	((DComm *)iPdd)->iLdd = this;
   309 
   310 	//setup the initial port configuration
   311 	PddConfigure(iConfig);
   312 	
   313 	return KErrNone;
   314 	}
   315 
   316 
   317 
   318 
   319 void DChannelComm::Start()
   320 	{
   321 	if (iStatus != EClosed)
   322 		{
   323 		PddStart();
   324 		iStatus = EActive;
   325 		}
   326 	}
   327 
   328 
   329 
   330 
   331 void DChannelComm::HandleMsg(TMessageBase* aMsg)
   332 	{
   333 	TThreadMessage& m = *(TThreadMessage*)aMsg;
   334 	TInt id = m.iValue;
   335 	if (id == (TInt)ECloseMsg)
   336 		{
   337 		Shutdown();
   338 		iStatus = EClosed;
   339 		m.Complete(KErrNone, EFalse);
   340 		return;
   341 		}
   342 	else if (id == KMaxTInt)
   343 		{
   344 		// DoCancel
   345 		DoCancel(m.Int0());
   346 		m.Complete(KErrNone, ETrue);
   347 		return;
   348 		}
   349 
   350 	if (id < 0)
   351 		{
   352 		// DoRequest
   353 		TRequestStatus* pS = (TRequestStatus*)m.Ptr0();
   354 		TInt r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
   355 		if (r != KErrNone)
   356 			Kern::RequestComplete(iClient, pS, r);
   357 		m.Complete(KErrNone, ETrue);
   358 		}
   359 	else
   360 		{
   361 		// DoControl
   362 		TInt r = DoControl(id, m.Ptr0(), m.Ptr1());
   363 		m.Complete(r, ETrue);
   364 		}
   365 	}
   366 
   367 
   368 TInt DChannelComm::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   369 	{
   370 
   371 	//
   372 	// First check if we have started
   373 	//
   374 	if (iStatus == EOpen)
   375 		{
   376 		Start();
   377 		}
   378 
   379 	// Now we can dispatch the request
   380 	TInt r = KErrNone;
   381 	TInt len = 0;
   382 	switch (aReqNo)
   383 		{
   384 		case RBusDevComm::ERequestRead:
   385 			if (a2)
   386 				//get the size of the client data 
   387 				r = Kern::ThreadRawRead(iClient, a2, &len, sizeof(len));
   388 			if (r == KErrNone)
   389 				{
   390 				if (a1)	//doing a read
   391 					{
   392 					iRxStatus = aStatus;
   393 					//start the read
   394 					InitiateRead(a1,len);
   395 					}
   396 				else	//notify read data availiable
   397 					{
   398 					iRxDAStatus = aStatus;
   399 					NotifyReadDataAvailable();
   400 					}
   401 				}
   402 			break;
   403 		
   404 		case RBusDevComm::ERequestWrite:
   405 			{
   406 			if (iStatus == EClosed)
   407 				return KErrNotReady;
   408 			if (!a1)
   409 				a1 = (TAny*)1;
   410 			r = Kern::ThreadRawRead(iClient, a2, &len, sizeof(len));	//get the length of the data to write
   411 			if (r == KErrNone)
   412 				{
   413 				iTxStatus = aStatus;
   414 				TInt irq = NKern::DisableInterrupts(1);
   415 				if(iTurnaroundTimerRunning)
   416 					{
   417 					iTurnaroundTransmitDelayed = ETrue;
   418 					iTurnaroundTxDesPtr = a1;
   419 					iTurnaroundTxDesLength = len;
   420 					NKern::RestoreInterrupts(irq);
   421 					}
   422 				else if (iFlags & KBreaking)
   423 					{
   424 					// currently breaking, delay the write
   425 					iBreakDelayedTx = ETrue;
   426 					iBreakDelayedTxDesPtr = a1;		// save these as client could could start trashing them before the
   427 					iBreakDelayedTxDesLength = len;	// transmission effectively starts
   428 					NKern::RestoreInterrupts(irq);
   429 					}
   430 				else
   431 					{
   432 					NKern::RestoreInterrupts(irq);
   433 					InitiateWrite(a1, len); //a1 is ptr to data to write (on client side)
   434 					iTurnaroundTimerStartTime = 0;
   435 					iTurnaroundTimerStartTimeValid = 2;
   436 					}
   437 				}
   438 			break;
   439 			}
   440 
   441 		case RBusDevComm::ERequestNotifySignalChange:
   442 			{
   443 			//a1 has place to put the result
   444 			//a2 has the signal mask
   445 			if (!a1)
   446 				{
   447 				r = KErrArgument;
   448 				break;
   449 				}
   450 			
   451 			//start the signal request
   452 			TInt mask = 0;
   453 			r = Kern::ThreadRawRead(iClient, a2, &mask, sizeof(mask));	//get the signal mask
   454 			if (r == KErrNone)
   455 				{
   456 				iSignalStatus = aStatus;
   457 				InitiateNotifySignals(a1, mask);
   458 				}
   459 			break;
   460 			}
   461 		
   462 		case RBusDevComm::ERequestBreak:
   463 			{
   464 			r = Kern::ThreadRawRead(iClient, a1, &iBreakTimeMicroSeconds, sizeof(TInt));	//get the time to break for
   465 			if (r == KErrNone)
   466 				{
   467 				iBreakStatus=aStatus;
   468 				
   469 				// check if turnaround timer running.
   470 				TInt irq = NKern::DisableInterrupts(1);
   471 				if(iTurnaroundTimerRunning)
   472 					{
   473 					iTurnaroundBreakDelayed = ETrue;
   474 					NKern::RestoreInterrupts(irq);
   475 					}
   476 				else
   477 					{
   478 					NKern::RestoreInterrupts(irq);
   479 					BreakOn();
   480 					}
   481 				}
   482 			break;
   483 			}
   484 				
   485 		default:
   486 			r = KErrNotSupported;
   487 			break;
   488 
   489 		}
   490 	return r;
   491 	}
   492 
   493 TInt DChannelComm::SetConfig(TCommConfigV01& c)
   494 	{
   495 	iConfig = c;
   496 	PddConfigure(iConfig);
   497 	return KErrNone;
   498 	}
   499 
   500 TInt DChannelComm::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   501 	{
   502 
   503 	TCommConfigV01 c;
   504 	TInt r = KErrNone;
   505 
   506 	switch (aFunction)
   507 		{
   508 		case RBusDevComm::EControlConfig:
   509 			{
   510 			//get the current configuration
   511 			TPtrC8 cfg((const TUint8*)&iConfig, sizeof(iConfig));
   512 			r = Kern::ThreadDesWrite(iClient, a1, cfg, 0, KTruncateToMaxLength, iClient);
   513 			break;
   514 			}
   515 
   516 		case RBusDevComm::EControlSetConfig:
   517 			{
   518 			if (AreAnyPending())	
   519 				Kern::PanicCurrentThread(_L("D32COMM"), ESetConfigWhileRequestPending);
   520 			else
   521 				{
   522 				memclr(&c, sizeof(c));
   523 				TPtr8 cfg((TUint8*)&c, 0, sizeof(c));
   524 				r = Kern::ThreadDesRead(iClient, a1, cfg, 0, 0);
   525 				if (r == KErrNone)
   526 					r = SetConfig(c);	//set the new configuration
   527 				}
   528 			break;
   529 			}
   530 
   531 		case RBusDevComm::EControlCaps:
   532 			{
   533 			//get capabilities
   534 			TCommCaps2 caps;
   535 			PddCaps(caps);	//call ipdd->Caps
   536 			r = Kern::ThreadDesWrite(iClient, a1, caps, 0, KTruncateToMaxLength, iClient);
   537 			break;
   538 			}
   539 
   540 		case RBusDevComm::EControlSignals:
   541 			{
   542 			r = Signals();
   543 			break;
   544 			}
   545 
   546 		case RBusDevComm::EControlSetSignals:
   547 			{
   548 //			if (((TUint)a1)&((TUint)a2))	//can't set and clear at same time
   549 //				{
   550 //				Kern::PanicCurrentThread(_L("D32COMM"), ESetSignalsSetAndClear);
   551 //				}
   552 //			else
   553 				{
   554 
   555 				SetSignals((TUint)a1, (TUint)a2);
   556 				}
   557 			break;
   558 			}
   559 
   560 		case RBusDevComm::EControlQueryReceiveBuffer:
   561 			r = RxCount();
   562 			break;
   563 
   564 		case RBusDevComm::EControlResetBuffers:
   565 			if (AreAnyPending())
   566 				Kern::PanicCurrentThread(_L("D32COMM"), EResetBuffers);
   567 			else
   568 				ResetBuffers(ETrue);
   569 			break;
   570 
   571 		case RBusDevComm::EControlReceiveBufferLength:
   572 			r = RxBufferSize();
   573 			break;
   574 
   575 		case RBusDevComm::EControlSetReceiveBufferLength:
   576 			if (AreAnyPending())
   577 				Kern::PanicCurrentThread(_L("D32COMM"), ESetReceiveBufferLength);
   578 			else
   579 				r = SetRxBufferSize((TInt)a1);
   580 			break;
   581 
   582 		case RBusDevComm::EControlMinTurnaroundTime:
   583 			r = iTurnaroundMicroSeconds;			// used saved value
   584 			break;
   585 
   586 		case RBusDevComm::EControlSetMinTurnaroundTime:
   587 				{
   588 				if ((TInt)a1<0)
   589 					a1=(TAny*)0;
   590 				iTurnaroundMicroSeconds = (TUint)a1;			// save this
   591 				TUint newTurnaroundMilliSeconds = (TUint)a1/1000;	// convert to ms
   592 				if(newTurnaroundMilliSeconds != iTurnaroundMinMilliSeconds)
   593 					{
   594 					// POLICY: if a new turnaround time is set before the previous running timer has expired 
   595   					// then the timer is adjusted depending on the new value and if any
   596                     // write request has been queued, transmission will proceed after the timer has expired.
   597 					if(iTurnaroundTimerStartTimeValid == 0)
   598 						{
   599 						iTurnaroundTimerStartTime = NKern::TickCount();
   600 						iTurnaroundTimerStartTimeValid = 1;
   601 						}
   602 					if(iTurnaroundTimerStartTimeValid != 2)
   603 						TurnaroundClear();
   604 					if(newTurnaroundMilliSeconds > 0)
   605 						{
   606 						r = TurnaroundSet(newTurnaroundMilliSeconds);
   607 						}
   608 					}
   609 				}
   610 			break;
   611 
   612 		default:
   613 			r = KErrNotSupported;
   614 			}
   615 		return(r);
   616 		}
   617 
   618 
   619 void DChannelComm::SignalNotifyDfc(TAny* aPtr)
   620 	{
   621 	DChannelComm* pC = (DChannelComm*)aPtr;
   622 	pC->DoSignalNotify();
   623 	}
   624 
   625 void DChannelComm::RxDataAvailableDfc(TAny* aPtr)
   626 	{
   627 	DChannelComm* pC = (DChannelComm*)aPtr;
   628 	pC->DoRxDataAvailable();
   629 	}
   630 
   631 void DChannelComm::DoRxDataAvailable()
   632 	{
   633 	Complete(ERxDA, iRxDAError);
   634 	iRxDAError = KErrNone;
   635 	}
   636 
   637 void DChannelComm::DoSignalNotify()
   638 	{
   639 	//copy the data back to the client
   640 	if (iSignalError == KErrNone)
   641 		iSignalError = Kern::ThreadRawWrite(iClient, iClientSignalResultPtr,&iSignalResult, sizeof(iSignalResult), iClient);
   642 	Complete(ESigChg, iSignalError);
   643 	iSignalError = KErrNone;
   644 	}
   645 
   646 void DChannelComm::CompleteTxDfc(TAny* aPtr)
   647 	{
   648 	DChannelComm* pC = (DChannelComm*)aPtr;
   649 	pC->DoCompleteTx();
   650 	}
   651 
   652 void DChannelComm::DoCompleteTx()
   653 	{
   654 	Complete(ETx, iTxError);
   655 	iTxError = KErrNone;
   656 	}
   657 
   658 void DChannelComm::CompleteRxDfc(TAny* aPtr)
   659 	{
   660 	DChannelComm* pC = (DChannelComm*)aPtr;
   661 	pC->DoCompleteRx();
   662 	}
   663 
   664 void DChannelComm::DoCompleteRx()
   665 	{
   666 	if (iRxError == KErrNone)
   667 		{
   668 		//copy the data back to the client
   669 		iRxError = Kern::ThreadDesWrite(iClient, (TDes8*)iClientDestPtr, *RxBuffer(), 0, KChunkShiftBy0, iClient);
   670 		}
   671 	Complete(ERx, iRxError);
   672 	iRxError = KErrNone;
   673 	TInt irq = NKern::DisableInterrupts(1);
   674 	if(iTurnaroundMinMilliSeconds > 0)
   675 		{
   676 		// POLICY: if timer is running from a previous read, stop it and re-start it
   677 		if(iTurnaroundTimerRunning)
   678 			{
   679 			iTurnaroundTimer.Cancel();
   680 			iTurnaroundDfc.Cancel();
   681 			}
   682 		iTurnaroundTimerRunning = ETrue;
   683 		TInt timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
   684 		iTurnaroundTimer.OneShot(timeout);
   685 		//Record the timestamp of turnaround timer start.
   686 		iTurnaroundTimerStartTimeValid = 1;
   687 		iTurnaroundTimerStartTime = NKern::TickCount();
   688 		}
   689 	NKern::RestoreInterrupts(irq);
   690 	}
   691 
   692 void DChannelComm::DoCancel(TInt aMask)
   693 	{
   694 	if (aMask & RBusDevComm::ERequestReadCancel)
   695 		{
   696 		ReadCancel();
   697 		}
   698 
   699 	if (aMask & RBusDevComm::ERequestWriteCancel)
   700 		{
   701 		TInt irq = NKern::DisableInterrupts(1);
   702 		if(iTurnaroundTransmitDelayed)
   703 			{
   704 			iTurnaroundTxDesPtr = 0;
   705 			iTurnaroundTxDesLength = 0;
   706 			iTurnaroundTransmitDelayed = EFalse;
   707 			}
   708 		NKern::RestoreInterrupts(irq);
   709 
   710 		WriteCancel();
   711 		}
   712 
   713 	if (aMask & RBusDevComm::ERequestNotifySignalChangeCancel)
   714 		{
   715 		SignalChangeCancel();
   716 		Complete(ESigChg,KErrCancel);
   717 		}
   718 
   719 	if (aMask & RBusDevComm::ERequestBreakCancel)
   720 		{
   721 		TInt irq = NKern::DisableInterrupts(1);
   722 		if(iTurnaroundBreakDelayed)
   723 			iTurnaroundBreakDelayed = EFalse;
   724 		NKern::RestoreInterrupts(irq);
   725 		
   726 		iBreakDfc.Cancel();
   727 		iBreakTimer.Cancel();
   728 		FinishBreakImplementation(KErrCancel);
   729 		}
   730 	}
   731 
   732 
   733 void DChannelComm::InitiateWrite(TAny *aTxDes, TInt aLength)
   734 	{
   735 //aTxDes has client side data
   736 //aLength has the len
   737 	
   738 	if (!aTxDes)
   739 		{
   740 		Complete(ETx, KErrArgument);
   741 		return;
   742 		}
   743 	// call the pdd to fill its buffer and write the data
   744 	Write(iClient, aTxDes, aLength);
   745 	}
   746 
   747 void DChannelComm::InitiateRead(TAny *aRxDes, TInt aLength)
   748 	{
   749 
   750 	// Complete zero-length read immediately.  maybe not
   751 
   752 //	if (aLength == 0)
   753 //		{
   754 //		Complete(ERx, KErrNone);
   755 //		return;
   756 //		}
   757 	TInt max=Kern::ThreadGetDesMaxLength(iClient,aRxDes);
   758 
   759 	if (max < Abs(aLength) || max < 0)
   760 		Complete(ERx, KErrGeneral);
   761 		// do not start the Turnaround timer (invalid Descriptor this read never starts)
   762 	else
   763 		{
   764 		iClientDestPtr = aRxDes;
   765 		Read(iClient, aRxDes, aLength);
   766 		}
   767 	}
   768 
   769 void DChannelComm::InitiateNotifySignals(TAny *aSignalResultPtr, TInt aMask)
   770 	{
   771 	//aMask has the mask of signals we require
   772 	//aSignalResultPtr is a pointer to the clients area for the result
   773 	iClientSignalResultPtr = (TUint*)aSignalResultPtr;
   774 	NotifySignals(iClient, aMask);
   775 	}
   776 
   777 void DChannelComm::NotifyReadDataAvailable()
   778 	{
   779 	NotifyDataAvailable();
   780 	}
   781 
   782 
   783 void DChannelComm::Complete(TInt aMask, TInt aReason)
   784 	{
   785 	if (aMask & ERx)
   786 		Kern::RequestComplete(iClient, iRxStatus, aReason);
   787 	if (aMask & ETx)
   788 		Kern::RequestComplete(iClient, iTxStatus, aReason);
   789 	if (aMask & ESigChg)
   790 		Kern::RequestComplete(iClient, iSignalStatus, aReason);
   791 	if (aMask & ERxDA)
   792 		Kern::RequestComplete(iClient, iRxDAStatus, aReason);
   793 	if (aMask & EBreak)
   794 		Kern::RequestComplete(iClient, iBreakStatus, aReason);
   795 	}
   796 
   797 void DChannelComm::BreakOn()
   798 //
   799 // Start the driver breaking.
   800 //
   801 	{
   802 	iFlags&=(~KBreakPending);
   803 	iFlags|=KBreaking;
   804 	PddBreak(ETrue);
   805 	iBreakTimer.OneShot(iBreakTimeMicroSeconds, DChannelComm::FinishBreak, this);
   806 	}
   807 
   808 void DChannelComm::BreakOff()
   809 //
   810 // Stop the driver breaking.
   811 //
   812 	{
   813 	PddBreak(EFalse);
   814 	iFlags&=~KBreaking;
   815 	}
   816 
   817 void DChannelComm::FinishBreak(TAny* aSelf)
   818 	{
   819 	DChannelComm* self = (DChannelComm*)aSelf;
   820 	self->QueueFinishBreakDfc();
   821 	}
   822 
   823 void DChannelComm::FinishBreakDfc(TAny* aSelf)
   824 	{
   825 	DChannelComm* self = (DChannelComm*)aSelf;
   826 	self->FinishBreakImplementation(KErrNone);
   827 	}
   828 
   829 void DChannelComm::QueueFinishBreakDfc()
   830 	{
   831 	iBreakDfc.Enque();
   832 	}
   833 
   834 void DChannelComm::FinishBreakImplementation(TInt aBreakError)
   835 	{
   836 	if (iStatus==EClosed)
   837 		{
   838 		Complete(EBreak, KErrNotReady);
   839 		}
   840 	else if(LineFail())	// have signals changed in the meantime?
   841 		{
   842 		Complete(EBreak, KErrCommsLineFail);
   843 		}
   844 	else
   845 		{
   846 		BreakOff();
   847 		Complete(EBreak, aBreakError);
   848 
   849 		TInt irq = NKern::DisableInterrupts(1);
   850 		if(iBreakDelayedTx)
   851 			{
   852 			iBreakDelayedTx = EFalse;	// protected -> prevent reentrant ISR
   853 			NKern::RestoreInterrupts(irq);
   854 			if (iStatus==EClosed)
   855 				{
   856 				iBreakDelayedTxDesPtr = 0;
   857 				iBreakDelayedTxDesLength = 0;
   858 				Complete(ETx,KErrNotReady);
   859 				return;
   860 				}
   861 
   862 			// fail signals checked in the PDD
   863 			InitiateWrite(iBreakDelayedTxDesPtr, iBreakDelayedTxDesLength);
   864 			iBreakDelayedTxDesPtr = 0;
   865 			iBreakDelayedTxDesLength = 0;
   866 			}
   867 		else 
   868 			NKern::RestoreInterrupts(irq);
   869 
   870 		}
   871 	}