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