1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/serialldd.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,871 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// wins/specific/serialldd.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "winscomm.h"
1.22 +#include <kernel/kern_priv.h>
1.23 +#include <e32hal.h>
1.24 +#include <e32uid.h>
1.25 +
1.26 +_LIT(KLddName,"Comm");
1.27 +
1.28 +const TUint KBreaking=0x02;
1.29 +const TUint KBreakPending=0x04;
1.30 +
1.31 +
1.32 +enum TPanic
1.33 + {
1.34 + ESetConfigWhileRequestPending,
1.35 + ESetSignalsSetAndClear,
1.36 + EResetBuffers,
1.37 + ESetReceiveBufferLength,
1.38 + };
1.39 +
1.40 +
1.41 +inline TUint32 SafeSwap(TUint32 aNewValue, TUint32& aWord)
1.42 + { return __e32_atomic_swp_ord32(&aWord, aNewValue); }
1.43 +
1.44 +DECLARE_STANDARD_LDD()
1.45 + {
1.46 + return new DDeviceComm;
1.47 + }
1.48 +
1.49 +
1.50 +DDeviceComm::DDeviceComm()
1.51 + {
1.52 + iParseMask = KDeviceAllowAll;
1.53 + iUnitsMask = 0xffffffff; // Leave units decision to the PDD
1.54 + iVersion = TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
1.55 + }
1.56 +
1.57 +TInt DDeviceComm::Install()
1.58 + {
1.59 + return(SetName(&KLddName));
1.60 + }
1.61 +
1.62 +void DDeviceComm::GetCaps(TDes8& aDes) const
1.63 + {
1.64 + TPckgBuf<TCapsDevCommV01> b;
1.65 + b().version = TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
1.66 + Kern::InfoCopy(aDes,b);
1.67 + }
1.68 +
1.69 +TInt DDeviceComm::Create(DLogicalChannelBase*& aChannel)
1.70 + {
1.71 + aChannel = new DChannelComm;
1.72 + return aChannel?KErrNone:KErrNoMemory;
1.73 + }
1.74 +
1.75 +
1.76 +DChannelComm::DChannelComm()
1.77 + :
1.78 + iRxCompleteDfc(DChannelComm::CompleteRxDfc,this,2),
1.79 + iTxCompleteDfc(DChannelComm::CompleteTxDfc,this,2),
1.80 + iRxDataAvailableDfc(DChannelComm::RxDataAvailableDfc,this,2),
1.81 + iSigNotifyDfc(DChannelComm::SignalNotifyDfc,this,2),
1.82 +// iBreakMinMilliSeconds(0),
1.83 +// iTurnaroundTimerRunning(EFalse),
1.84 +// iTurnaroundTransmitDelayed(EFalse),
1.85 + iTurnaroundTimer(DChannelComm::TurnaroundStartDfc, this),
1.86 + iTurnaroundDfc(DChannelComm::TurnaroundTimeout, this, 2),
1.87 +// iTurnaroundTxDesPtr(0),
1.88 +// iTurnaroundTxDesLength(0)
1.89 + iBreakDfc(DChannelComm::FinishBreakDfc, this, 2)
1.90 + {
1.91 + iConfig.iRate = EBps9600;
1.92 + iConfig.iDataBits = EData8;
1.93 + iConfig.iStopBits = EStop1;
1.94 + iConfig.iParity = EParityNone;
1.95 + iConfig.iHandshake = KConfigObeyCTS;
1.96 + iConfig.iParityError = KConfigParityErrorFail;
1.97 + iConfig.iFifo = EFifoEnable;
1.98 + iConfig.iTerminatorCount = 0;
1.99 + iConfig.iXonChar = 0x11;
1.100 + iConfig.iXoffChar = 0x13;
1.101 + iConfig.iSIREnable = ESIRDisable;
1.102 +
1.103 + iTxError = KErrNone;
1.104 + iRxError = KErrNone;
1.105 + iRxDAError = KErrNone;
1.106 + iSignalError = KErrNone;
1.107 + iClientDestPtr = 0;
1.108 + iClientSignalResultPtr = 0;
1.109 + iClient = &Kern::CurrentThread();
1.110 + iClient->Open();
1.111 + }
1.112 +
1.113 +
1.114 +DChannelComm::~DChannelComm()
1.115 + {
1.116 + Kern::SafeClose((DObject*&)iClient, NULL);
1.117 + }
1.118 +
1.119 +void DChannelComm::Shutdown()
1.120 + {
1.121 + // clean-up...
1.122 + if (iStatus == EActive)
1.123 + Stop(EStopPwrDown); // stop PDD
1.124 +
1.125 + Complete(EAll, KErrAbort);
1.126 +
1.127 + iRxCompleteDfc.Cancel();
1.128 + iTxCompleteDfc.Cancel();
1.129 + iTurnaroundTimer.Cancel();
1.130 + iTurnaroundDfc.Cancel();
1.131 + iSigNotifyDfc.Cancel();
1.132 + iRxDataAvailableDfc.Cancel();
1.133 + iBreakTimer.Cancel();
1.134 + iBreakDfc.Cancel();
1.135 + }
1.136 +
1.137 +TInt DChannelComm::TurnaroundSet(TUint aNewTurnaroundMilliSeconds)
1.138 + {
1.139 + TInt r = KErrNone;
1.140 + iTurnaroundMinMilliSeconds = aNewTurnaroundMilliSeconds;
1.141 + return r;
1.142 + }
1.143 +
1.144 +TBool DChannelComm::TurnaroundStopTimer()
1.145 +// Stop the timer and DFC
1.146 + {
1.147 + TInt irq = 0;
1.148 + irq = NKern::DisableInterrupts(1);
1.149 + TBool result = iTurnaroundTimerRunning;
1.150 + if(result)
1.151 + {
1.152 + iTurnaroundTimerRunning = EFalse;
1.153 + iTurnaroundTimer.Cancel();
1.154 + iTurnaroundDfc.Cancel();
1.155 + }
1.156 + NKern::RestoreInterrupts(irq);
1.157 + return result;
1.158 + }
1.159 +
1.160 +TInt DChannelComm::TurnaroundClear()
1.161 +// Clear any old timer and start timer based on new turnaround value.
1.162 +// Called for any change: from T > 0 to T == 0 or (T = t1 > 0) to (T = t2 > 0)
1.163 +// POLICY: If a write has already been delayed, it will be started immediately if the requested
1.164 +// turnaround time is elapsed else will only start after it is elapsed.
1.165 + {
1.166 + TInt r = KErrNone;
1.167 + TUint delta = 0;
1.168 +
1.169 + if(iTurnaroundTimerStartTimeValid == 1)
1.170 + {
1.171 + //Calculate the turnaround time elapsed so far
1.172 + delta = (NKern::TickCount() - iTurnaroundTimerStartTime) * NKern::TickPeriod();
1.173 + }
1.174 + if(delta < iTurnaroundMicroSeconds)
1.175 + {
1.176 + iTurnaroundMinMilliSeconds = (iTurnaroundMicroSeconds - delta) / 1000;
1.177 + TInt irq = NKern::DisableInterrupts(1);
1.178 + // POLICY: if timer is running from a previous read, stop it and re-start it
1.179 + if(iTurnaroundTimerRunning)
1.180 + {
1.181 + iTurnaroundTimer.Cancel();
1.182 + iTurnaroundDfc.Cancel();
1.183 + }
1.184 + iTurnaroundTimerRunning = ETrue;
1.185 + TInt timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
1.186 + iTurnaroundTimer.OneShot(timeout);
1.187 + NKern::RestoreInterrupts(irq);
1.188 + }
1.189 + else
1.190 + {
1.191 + if(TurnaroundStopTimer())
1.192 + {
1.193 + // if a write is waiting, start a DFC to run it
1.194 + TurnaroundStartDfcImplementation(EFalse);
1.195 + }
1.196 + }
1.197 + iTurnaroundMinMilliSeconds = 0;
1.198 + return r;
1.199 + }
1.200 +
1.201 +void DChannelComm::TurnaroundStartDfc(TAny* aSelf)
1.202 + {
1.203 + DChannelComm* self = (DChannelComm*)aSelf;
1.204 + self->TurnaroundStartDfcImplementation(ETrue);
1.205 + }
1.206 +
1.207 +void DChannelComm::TurnaroundStartDfcImplementation(TBool inIsr)
1.208 + {
1.209 + TInt irq = 0;
1.210 + if(!inIsr)
1.211 + {
1.212 + irq = NKern::DisableInterrupts(1);
1.213 + }
1.214 + iTurnaroundTimerRunning = EFalse;
1.215 + if(iTurnaroundTransmitDelayed || iTurnaroundBreakDelayed)
1.216 + {
1.217 + if(inIsr)
1.218 + iTurnaroundDfc.Add();
1.219 + else
1.220 + {
1.221 + NKern::RestoreInterrupts(irq);
1.222 + iTurnaroundDfc.Enque();
1.223 + }
1.224 + return;
1.225 + }
1.226 + if(!inIsr)
1.227 + {
1.228 + NKern::RestoreInterrupts(irq);
1.229 + }
1.230 + }
1.231 +
1.232 +void DChannelComm::TurnaroundTimeout(TAny* aSelf)
1.233 + {
1.234 + DChannelComm* self = (DChannelComm*)aSelf;
1.235 + self->TurnaroundTimeoutImplementation();
1.236 + }
1.237 +
1.238 +void DChannelComm::TurnaroundTimeoutImplementation(void)
1.239 + {
1.240 + TInt irq = NKern::DisableInterrupts(1);
1.241 + if (iTurnaroundBreakDelayed)
1.242 + {
1.243 + iTurnaroundBreakDelayed=EFalse;
1.244 + if (iStatus==EClosed)
1.245 + {
1.246 + NKern::RestoreInterrupts(irq);
1.247 + Complete(EBreak, KErrNotReady);
1.248 + return;
1.249 + }
1.250 +
1.251 + if (LineFail())
1.252 + {
1.253 + NKern::RestoreInterrupts(irq);
1.254 + Complete(EBreak, KErrCommsLineFail);
1.255 + return;
1.256 + }
1.257 +
1.258 + if (iTurnaroundTransmitDelayed)
1.259 + {
1.260 + //delay write by break instead of turnaround
1.261 + iBreakDelayedTx = ETrue;
1.262 + iBreakDelayedTxDesPtr = iTurnaroundTxDesPtr;
1.263 + iBreakDelayedTxDesLength = iTurnaroundTxDesLength;
1.264 + iTurnaroundTxDesPtr=0;
1.265 + iTurnaroundTxDesLength=0;
1.266 + iTurnaroundTransmitDelayed=EFalse;
1.267 + }
1.268 + NKern::RestoreInterrupts(irq);
1.269 + BreakOn();
1.270 + }
1.271 + else if(iTurnaroundTransmitDelayed)
1.272 + {
1.273 + iTurnaroundTransmitDelayed = EFalse; // protected -> prevent reentrant ISR
1.274 + NKern::RestoreInterrupts(irq);
1.275 + if (iStatus==EClosed)
1.276 + {
1.277 + iTurnaroundTxDesPtr = 0;
1.278 + iTurnaroundTxDesLength = 0;
1.279 + Complete(ETx,KErrNotReady);
1.280 + return;
1.281 + }
1.282 +
1.283 + // fail signals checked in the PDD
1.284 + InitiateWrite(iTurnaroundTxDesPtr, iTurnaroundTxDesLength);
1.285 + iTurnaroundTimerStartTime = 0;
1.286 + iTurnaroundTimerStartTimeValid = 2;
1.287 + iTurnaroundTxDesPtr = 0;
1.288 + iTurnaroundTxDesLength = 0;
1.289 + }
1.290 + else
1.291 + NKern::RestoreInterrupts(irq);
1.292 + }
1.293 +
1.294 +TInt DChannelComm::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion &aVer)
1.295 + {
1.296 + if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECOMM.LDD (Comm Driver)")))
1.297 + return KErrPermissionDenied;
1.298 + if (!Kern::QueryVersionSupported(TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber),aVer))
1.299 + return KErrNotSupported;
1.300 +
1.301 + // set up the correct DFC queue
1.302 + SetDfcQ(((DComm*)iPdd)->DfcQ(aUnit));
1.303 + iRxCompleteDfc.SetDfcQ(iDfcQ);
1.304 + iTxCompleteDfc.SetDfcQ(iDfcQ);
1.305 + iRxDataAvailableDfc.SetDfcQ(iDfcQ);
1.306 + iSigNotifyDfc.SetDfcQ(iDfcQ);
1.307 + iTurnaroundDfc.SetDfcQ(iDfcQ);
1.308 + iBreakDfc.SetDfcQ(iDfcQ);
1.309 + iMsgQ.Receive();
1.310 +
1.311 + ((DComm *)iPdd)->iLdd = this;
1.312 +
1.313 + //setup the initial port configuration
1.314 + PddConfigure(iConfig);
1.315 +
1.316 + return KErrNone;
1.317 + }
1.318 +
1.319 +
1.320 +
1.321 +
1.322 +void DChannelComm::Start()
1.323 + {
1.324 + if (iStatus != EClosed)
1.325 + {
1.326 + PddStart();
1.327 + iStatus = EActive;
1.328 + }
1.329 + }
1.330 +
1.331 +
1.332 +
1.333 +
1.334 +void DChannelComm::HandleMsg(TMessageBase* aMsg)
1.335 + {
1.336 + TThreadMessage& m = *(TThreadMessage*)aMsg;
1.337 + TInt id = m.iValue;
1.338 + if (id == (TInt)ECloseMsg)
1.339 + {
1.340 + Shutdown();
1.341 + iStatus = EClosed;
1.342 + m.Complete(KErrNone, EFalse);
1.343 + return;
1.344 + }
1.345 + else if (id == KMaxTInt)
1.346 + {
1.347 + // DoCancel
1.348 + DoCancel(m.Int0());
1.349 + m.Complete(KErrNone, ETrue);
1.350 + return;
1.351 + }
1.352 +
1.353 + if (id < 0)
1.354 + {
1.355 + // DoRequest
1.356 + TRequestStatus* pS = (TRequestStatus*)m.Ptr0();
1.357 + TInt r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
1.358 + if (r != KErrNone)
1.359 + Kern::RequestComplete(iClient, pS, r);
1.360 + m.Complete(KErrNone, ETrue);
1.361 + }
1.362 + else
1.363 + {
1.364 + // DoControl
1.365 + TInt r = DoControl(id, m.Ptr0(), m.Ptr1());
1.366 + m.Complete(r, ETrue);
1.367 + }
1.368 + }
1.369 +
1.370 +
1.371 +TInt DChannelComm::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1.372 + {
1.373 +
1.374 + //
1.375 + // First check if we have started
1.376 + //
1.377 + if (iStatus == EOpen)
1.378 + {
1.379 + Start();
1.380 + }
1.381 +
1.382 + // Now we can dispatch the request
1.383 + TInt r = KErrNone;
1.384 + TInt len = 0;
1.385 + switch (aReqNo)
1.386 + {
1.387 + case RBusDevComm::ERequestRead:
1.388 + if (a2)
1.389 + //get the size of the client data
1.390 + r = Kern::ThreadRawRead(iClient, a2, &len, sizeof(len));
1.391 + if (r == KErrNone)
1.392 + {
1.393 + if (a1) //doing a read
1.394 + {
1.395 + iRxStatus = aStatus;
1.396 + //start the read
1.397 + InitiateRead(a1,len);
1.398 + }
1.399 + else //notify read data availiable
1.400 + {
1.401 + iRxDAStatus = aStatus;
1.402 + NotifyReadDataAvailable();
1.403 + }
1.404 + }
1.405 + break;
1.406 +
1.407 + case RBusDevComm::ERequestWrite:
1.408 + {
1.409 + if (iStatus == EClosed)
1.410 + return KErrNotReady;
1.411 + if (!a1)
1.412 + a1 = (TAny*)1;
1.413 + r = Kern::ThreadRawRead(iClient, a2, &len, sizeof(len)); //get the length of the data to write
1.414 + if (r == KErrNone)
1.415 + {
1.416 + iTxStatus = aStatus;
1.417 + TInt irq = NKern::DisableInterrupts(1);
1.418 + if(iTurnaroundTimerRunning)
1.419 + {
1.420 + iTurnaroundTransmitDelayed = ETrue;
1.421 + iTurnaroundTxDesPtr = a1;
1.422 + iTurnaroundTxDesLength = len;
1.423 + NKern::RestoreInterrupts(irq);
1.424 + }
1.425 + else if (iFlags & KBreaking)
1.426 + {
1.427 + // currently breaking, delay the write
1.428 + iBreakDelayedTx = ETrue;
1.429 + iBreakDelayedTxDesPtr = a1; // save these as client could could start trashing them before the
1.430 + iBreakDelayedTxDesLength = len; // transmission effectively starts
1.431 + NKern::RestoreInterrupts(irq);
1.432 + }
1.433 + else
1.434 + {
1.435 + NKern::RestoreInterrupts(irq);
1.436 + InitiateWrite(a1, len); //a1 is ptr to data to write (on client side)
1.437 + iTurnaroundTimerStartTime = 0;
1.438 + iTurnaroundTimerStartTimeValid = 2;
1.439 + }
1.440 + }
1.441 + break;
1.442 + }
1.443 +
1.444 + case RBusDevComm::ERequestNotifySignalChange:
1.445 + {
1.446 + //a1 has place to put the result
1.447 + //a2 has the signal mask
1.448 + if (!a1)
1.449 + {
1.450 + r = KErrArgument;
1.451 + break;
1.452 + }
1.453 +
1.454 + //start the signal request
1.455 + TInt mask = 0;
1.456 + r = Kern::ThreadRawRead(iClient, a2, &mask, sizeof(mask)); //get the signal mask
1.457 + if (r == KErrNone)
1.458 + {
1.459 + iSignalStatus = aStatus;
1.460 + InitiateNotifySignals(a1, mask);
1.461 + }
1.462 + break;
1.463 + }
1.464 +
1.465 + case RBusDevComm::ERequestBreak:
1.466 + {
1.467 + r = Kern::ThreadRawRead(iClient, a1, &iBreakTimeMicroSeconds, sizeof(TInt)); //get the time to break for
1.468 + if (r == KErrNone)
1.469 + {
1.470 + iBreakStatus=aStatus;
1.471 +
1.472 + // check if turnaround timer running.
1.473 + TInt irq = NKern::DisableInterrupts(1);
1.474 + if(iTurnaroundTimerRunning)
1.475 + {
1.476 + iTurnaroundBreakDelayed = ETrue;
1.477 + NKern::RestoreInterrupts(irq);
1.478 + }
1.479 + else
1.480 + {
1.481 + NKern::RestoreInterrupts(irq);
1.482 + BreakOn();
1.483 + }
1.484 + }
1.485 + break;
1.486 + }
1.487 +
1.488 + default:
1.489 + r = KErrNotSupported;
1.490 + break;
1.491 +
1.492 + }
1.493 + return r;
1.494 + }
1.495 +
1.496 +TInt DChannelComm::SetConfig(TCommConfigV01& c)
1.497 + {
1.498 + iConfig = c;
1.499 + PddConfigure(iConfig);
1.500 + return KErrNone;
1.501 + }
1.502 +
1.503 +TInt DChannelComm::DoControl(TInt aFunction, TAny* a1, TAny* a2)
1.504 + {
1.505 +
1.506 + TCommConfigV01 c;
1.507 + TInt r = KErrNone;
1.508 +
1.509 + switch (aFunction)
1.510 + {
1.511 + case RBusDevComm::EControlConfig:
1.512 + {
1.513 + //get the current configuration
1.514 + TPtrC8 cfg((const TUint8*)&iConfig, sizeof(iConfig));
1.515 + r = Kern::ThreadDesWrite(iClient, a1, cfg, 0, KTruncateToMaxLength, iClient);
1.516 + break;
1.517 + }
1.518 +
1.519 + case RBusDevComm::EControlSetConfig:
1.520 + {
1.521 + if (AreAnyPending())
1.522 + Kern::PanicCurrentThread(_L("D32COMM"), ESetConfigWhileRequestPending);
1.523 + else
1.524 + {
1.525 + memclr(&c, sizeof(c));
1.526 + TPtr8 cfg((TUint8*)&c, 0, sizeof(c));
1.527 + r = Kern::ThreadDesRead(iClient, a1, cfg, 0, 0);
1.528 + if (r == KErrNone)
1.529 + r = SetConfig(c); //set the new configuration
1.530 + }
1.531 + break;
1.532 + }
1.533 +
1.534 + case RBusDevComm::EControlCaps:
1.535 + {
1.536 + //get capabilities
1.537 + TCommCaps2 caps;
1.538 + PddCaps(caps); //call ipdd->Caps
1.539 + r = Kern::ThreadDesWrite(iClient, a1, caps, 0, KTruncateToMaxLength, iClient);
1.540 + break;
1.541 + }
1.542 +
1.543 + case RBusDevComm::EControlSignals:
1.544 + {
1.545 + r = Signals();
1.546 + break;
1.547 + }
1.548 +
1.549 + case RBusDevComm::EControlSetSignals:
1.550 + {
1.551 +// if (((TUint)a1)&((TUint)a2)) //can't set and clear at same time
1.552 +// {
1.553 +// Kern::PanicCurrentThread(_L("D32COMM"), ESetSignalsSetAndClear);
1.554 +// }
1.555 +// else
1.556 + {
1.557 +
1.558 + SetSignals((TUint)a1, (TUint)a2);
1.559 + }
1.560 + break;
1.561 + }
1.562 +
1.563 + case RBusDevComm::EControlQueryReceiveBuffer:
1.564 + r = RxCount();
1.565 + break;
1.566 +
1.567 + case RBusDevComm::EControlResetBuffers:
1.568 + if (AreAnyPending())
1.569 + Kern::PanicCurrentThread(_L("D32COMM"), EResetBuffers);
1.570 + else
1.571 + ResetBuffers(ETrue);
1.572 + break;
1.573 +
1.574 + case RBusDevComm::EControlReceiveBufferLength:
1.575 + r = RxBufferSize();
1.576 + break;
1.577 +
1.578 + case RBusDevComm::EControlSetReceiveBufferLength:
1.579 + if (AreAnyPending())
1.580 + Kern::PanicCurrentThread(_L("D32COMM"), ESetReceiveBufferLength);
1.581 + else
1.582 + r = SetRxBufferSize((TInt)a1);
1.583 + break;
1.584 +
1.585 + case RBusDevComm::EControlMinTurnaroundTime:
1.586 + r = iTurnaroundMicroSeconds; // used saved value
1.587 + break;
1.588 +
1.589 + case RBusDevComm::EControlSetMinTurnaroundTime:
1.590 + {
1.591 + if ((TInt)a1<0)
1.592 + a1=(TAny*)0;
1.593 + iTurnaroundMicroSeconds = (TUint)a1; // save this
1.594 + TUint newTurnaroundMilliSeconds = (TUint)a1/1000; // convert to ms
1.595 + if(newTurnaroundMilliSeconds != iTurnaroundMinMilliSeconds)
1.596 + {
1.597 + // POLICY: if a new turnaround time is set before the previous running timer has expired
1.598 + // then the timer is adjusted depending on the new value and if any
1.599 + // write request has been queued, transmission will proceed after the timer has expired.
1.600 + if(iTurnaroundTimerStartTimeValid == 0)
1.601 + {
1.602 + iTurnaroundTimerStartTime = NKern::TickCount();
1.603 + iTurnaroundTimerStartTimeValid = 1;
1.604 + }
1.605 + if(iTurnaroundTimerStartTimeValid != 2)
1.606 + TurnaroundClear();
1.607 + if(newTurnaroundMilliSeconds > 0)
1.608 + {
1.609 + r = TurnaroundSet(newTurnaroundMilliSeconds);
1.610 + }
1.611 + }
1.612 + }
1.613 + break;
1.614 +
1.615 + default:
1.616 + r = KErrNotSupported;
1.617 + }
1.618 + return(r);
1.619 + }
1.620 +
1.621 +
1.622 +void DChannelComm::SignalNotifyDfc(TAny* aPtr)
1.623 + {
1.624 + DChannelComm* pC = (DChannelComm*)aPtr;
1.625 + pC->DoSignalNotify();
1.626 + }
1.627 +
1.628 +void DChannelComm::RxDataAvailableDfc(TAny* aPtr)
1.629 + {
1.630 + DChannelComm* pC = (DChannelComm*)aPtr;
1.631 + pC->DoRxDataAvailable();
1.632 + }
1.633 +
1.634 +void DChannelComm::DoRxDataAvailable()
1.635 + {
1.636 + Complete(ERxDA, iRxDAError);
1.637 + iRxDAError = KErrNone;
1.638 + }
1.639 +
1.640 +void DChannelComm::DoSignalNotify()
1.641 + {
1.642 + //copy the data back to the client
1.643 + if (iSignalError == KErrNone)
1.644 + iSignalError = Kern::ThreadRawWrite(iClient, iClientSignalResultPtr,&iSignalResult, sizeof(iSignalResult), iClient);
1.645 + Complete(ESigChg, iSignalError);
1.646 + iSignalError = KErrNone;
1.647 + }
1.648 +
1.649 +void DChannelComm::CompleteTxDfc(TAny* aPtr)
1.650 + {
1.651 + DChannelComm* pC = (DChannelComm*)aPtr;
1.652 + pC->DoCompleteTx();
1.653 + }
1.654 +
1.655 +void DChannelComm::DoCompleteTx()
1.656 + {
1.657 + Complete(ETx, iTxError);
1.658 + iTxError = KErrNone;
1.659 + }
1.660 +
1.661 +void DChannelComm::CompleteRxDfc(TAny* aPtr)
1.662 + {
1.663 + DChannelComm* pC = (DChannelComm*)aPtr;
1.664 + pC->DoCompleteRx();
1.665 + }
1.666 +
1.667 +void DChannelComm::DoCompleteRx()
1.668 + {
1.669 + if (iRxError == KErrNone)
1.670 + {
1.671 + //copy the data back to the client
1.672 + iRxError = Kern::ThreadDesWrite(iClient, (TDes8*)iClientDestPtr, *RxBuffer(), 0, KChunkShiftBy0, iClient);
1.673 + }
1.674 + Complete(ERx, iRxError);
1.675 + iRxError = KErrNone;
1.676 + TInt irq = NKern::DisableInterrupts(1);
1.677 + if(iTurnaroundMinMilliSeconds > 0)
1.678 + {
1.679 + // POLICY: if timer is running from a previous read, stop it and re-start it
1.680 + if(iTurnaroundTimerRunning)
1.681 + {
1.682 + iTurnaroundTimer.Cancel();
1.683 + iTurnaroundDfc.Cancel();
1.684 + }
1.685 + iTurnaroundTimerRunning = ETrue;
1.686 + TInt timeout = NKern::TimerTicks(iTurnaroundMinMilliSeconds);
1.687 + iTurnaroundTimer.OneShot(timeout);
1.688 + //Record the timestamp of turnaround timer start.
1.689 + iTurnaroundTimerStartTimeValid = 1;
1.690 + iTurnaroundTimerStartTime = NKern::TickCount();
1.691 + }
1.692 + NKern::RestoreInterrupts(irq);
1.693 + }
1.694 +
1.695 +void DChannelComm::DoCancel(TInt aMask)
1.696 + {
1.697 + if (aMask & RBusDevComm::ERequestReadCancel)
1.698 + {
1.699 + ReadCancel();
1.700 + }
1.701 +
1.702 + if (aMask & RBusDevComm::ERequestWriteCancel)
1.703 + {
1.704 + TInt irq = NKern::DisableInterrupts(1);
1.705 + if(iTurnaroundTransmitDelayed)
1.706 + {
1.707 + iTurnaroundTxDesPtr = 0;
1.708 + iTurnaroundTxDesLength = 0;
1.709 + iTurnaroundTransmitDelayed = EFalse;
1.710 + }
1.711 + NKern::RestoreInterrupts(irq);
1.712 +
1.713 + WriteCancel();
1.714 + }
1.715 +
1.716 + if (aMask & RBusDevComm::ERequestNotifySignalChangeCancel)
1.717 + {
1.718 + SignalChangeCancel();
1.719 + Complete(ESigChg,KErrCancel);
1.720 + }
1.721 +
1.722 + if (aMask & RBusDevComm::ERequestBreakCancel)
1.723 + {
1.724 + TInt irq = NKern::DisableInterrupts(1);
1.725 + if(iTurnaroundBreakDelayed)
1.726 + iTurnaroundBreakDelayed = EFalse;
1.727 + NKern::RestoreInterrupts(irq);
1.728 +
1.729 + iBreakDfc.Cancel();
1.730 + iBreakTimer.Cancel();
1.731 + FinishBreakImplementation(KErrCancel);
1.732 + }
1.733 + }
1.734 +
1.735 +
1.736 +void DChannelComm::InitiateWrite(TAny *aTxDes, TInt aLength)
1.737 + {
1.738 +//aTxDes has client side data
1.739 +//aLength has the len
1.740 +
1.741 + if (!aTxDes)
1.742 + {
1.743 + Complete(ETx, KErrArgument);
1.744 + return;
1.745 + }
1.746 + // call the pdd to fill its buffer and write the data
1.747 + Write(iClient, aTxDes, aLength);
1.748 + }
1.749 +
1.750 +void DChannelComm::InitiateRead(TAny *aRxDes, TInt aLength)
1.751 + {
1.752 +
1.753 + // Complete zero-length read immediately. maybe not
1.754 +
1.755 +// if (aLength == 0)
1.756 +// {
1.757 +// Complete(ERx, KErrNone);
1.758 +// return;
1.759 +// }
1.760 + TInt max=Kern::ThreadGetDesMaxLength(iClient,aRxDes);
1.761 +
1.762 + if (max < Abs(aLength) || max < 0)
1.763 + Complete(ERx, KErrGeneral);
1.764 + // do not start the Turnaround timer (invalid Descriptor this read never starts)
1.765 + else
1.766 + {
1.767 + iClientDestPtr = aRxDes;
1.768 + Read(iClient, aRxDes, aLength);
1.769 + }
1.770 + }
1.771 +
1.772 +void DChannelComm::InitiateNotifySignals(TAny *aSignalResultPtr, TInt aMask)
1.773 + {
1.774 + //aMask has the mask of signals we require
1.775 + //aSignalResultPtr is a pointer to the clients area for the result
1.776 + iClientSignalResultPtr = (TUint*)aSignalResultPtr;
1.777 + NotifySignals(iClient, aMask);
1.778 + }
1.779 +
1.780 +void DChannelComm::NotifyReadDataAvailable()
1.781 + {
1.782 + NotifyDataAvailable();
1.783 + }
1.784 +
1.785 +
1.786 +void DChannelComm::Complete(TInt aMask, TInt aReason)
1.787 + {
1.788 + if (aMask & ERx)
1.789 + Kern::RequestComplete(iClient, iRxStatus, aReason);
1.790 + if (aMask & ETx)
1.791 + Kern::RequestComplete(iClient, iTxStatus, aReason);
1.792 + if (aMask & ESigChg)
1.793 + Kern::RequestComplete(iClient, iSignalStatus, aReason);
1.794 + if (aMask & ERxDA)
1.795 + Kern::RequestComplete(iClient, iRxDAStatus, aReason);
1.796 + if (aMask & EBreak)
1.797 + Kern::RequestComplete(iClient, iBreakStatus, aReason);
1.798 + }
1.799 +
1.800 +void DChannelComm::BreakOn()
1.801 +//
1.802 +// Start the driver breaking.
1.803 +//
1.804 + {
1.805 + iFlags&=(~KBreakPending);
1.806 + iFlags|=KBreaking;
1.807 + PddBreak(ETrue);
1.808 + iBreakTimer.OneShot(iBreakTimeMicroSeconds, DChannelComm::FinishBreak, this);
1.809 + }
1.810 +
1.811 +void DChannelComm::BreakOff()
1.812 +//
1.813 +// Stop the driver breaking.
1.814 +//
1.815 + {
1.816 + PddBreak(EFalse);
1.817 + iFlags&=~KBreaking;
1.818 + }
1.819 +
1.820 +void DChannelComm::FinishBreak(TAny* aSelf)
1.821 + {
1.822 + DChannelComm* self = (DChannelComm*)aSelf;
1.823 + self->QueueFinishBreakDfc();
1.824 + }
1.825 +
1.826 +void DChannelComm::FinishBreakDfc(TAny* aSelf)
1.827 + {
1.828 + DChannelComm* self = (DChannelComm*)aSelf;
1.829 + self->FinishBreakImplementation(KErrNone);
1.830 + }
1.831 +
1.832 +void DChannelComm::QueueFinishBreakDfc()
1.833 + {
1.834 + iBreakDfc.Enque();
1.835 + }
1.836 +
1.837 +void DChannelComm::FinishBreakImplementation(TInt aBreakError)
1.838 + {
1.839 + if (iStatus==EClosed)
1.840 + {
1.841 + Complete(EBreak, KErrNotReady);
1.842 + }
1.843 + else if(LineFail()) // have signals changed in the meantime?
1.844 + {
1.845 + Complete(EBreak, KErrCommsLineFail);
1.846 + }
1.847 + else
1.848 + {
1.849 + BreakOff();
1.850 + Complete(EBreak, aBreakError);
1.851 +
1.852 + TInt irq = NKern::DisableInterrupts(1);
1.853 + if(iBreakDelayedTx)
1.854 + {
1.855 + iBreakDelayedTx = EFalse; // protected -> prevent reentrant ISR
1.856 + NKern::RestoreInterrupts(irq);
1.857 + if (iStatus==EClosed)
1.858 + {
1.859 + iBreakDelayedTxDesPtr = 0;
1.860 + iBreakDelayedTxDesLength = 0;
1.861 + Complete(ETx,KErrNotReady);
1.862 + return;
1.863 + }
1.864 +
1.865 + // fail signals checked in the PDD
1.866 + InitiateWrite(iBreakDelayedTxDesPtr, iBreakDelayedTxDesLength);
1.867 + iBreakDelayedTxDesPtr = 0;
1.868 + iBreakDelayedTxDesLength = 0;
1.869 + }
1.870 + else
1.871 + NKern::RestoreInterrupts(irq);
1.872 +
1.873 + }
1.874 + }