emulator/emulatorbsp/specific/serialldd.cpp
changeset 0 cec860690d41
equal deleted inserted replaced
-1:000000000000 0:cec860690d41
       
     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 	}