os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/specific/uart.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1998-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 the License "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
// template\template_variant\specific\uart.cpp
sl@0
    15
// pdd for serial ports
sl@0
    16
// assume Modem Control Signals change cause an interrupt
sl@0
    17
// 
sl@0
    18
//
sl@0
    19
sl@0
    20
sl@0
    21
#include <drivers/comm.h>
sl@0
    22
#include <template_assp.h>
sl@0
    23
#include "iolines.h"
sl@0
    24
#include <e32hal.h>
sl@0
    25
sl@0
    26
_LIT(KPddName,"Comm.Template");
sl@0
    27
sl@0
    28
// needs ldd version..
sl@0
    29
const TInt KMinimumLddMajorVersion=1;
sl@0
    30
const TInt KMinimumLddMinorVersion=1;
sl@0
    31
const TInt KMinimumLddBuild=122;
sl@0
    32
sl@0
    33
//
sl@0
    34
// TO DO: (mandatory)
sl@0
    35
//
sl@0
    36
// Define here the UART enumeration data for the serial ports.
sl@0
    37
// It is a good idea to define each enumerated value as a bit mask that can be written to (or OR-ed or AND-ed to)
sl@0
    38
// a hardware register to provide the configuration option desired (the following are EXAMPLES ONLY):
sl@0
    39
//
sl@0
    40
// EXAMPLE ONLY
sl@0
    41
enum TUartBaudRate
sl@0
    42
	{
sl@0
    43
	EUartBaudRate115200/* =bitmask for 115200 Baud */,
sl@0
    44
	EUartBaudRate76800/* =bitmask for 76800 Baud */,
sl@0
    45
	EUartBaudRate57600/* =bitmask for 57600 Baud */,
sl@0
    46
	EUartBaudRate38400/* =bitmask for 38400 Baud */,
sl@0
    47
	EUartBaudRate19200/* =bitmask for 19200 Baud */,
sl@0
    48
	EUartBaudRate14400/* =bitmask for 14400 Baud */,
sl@0
    49
	EUartBaudRate9600/* =bitmask for 9600 Baud */,
sl@0
    50
	EUartBaudRate4800/* =bitmask for 4800 Baud */,
sl@0
    51
	EUartBaudRate2400/* =bitmask for 2400 Baud */,
sl@0
    52
	EUartBaudRate1200/* =bitmask for 1200 Baud */,
sl@0
    53
	EUartBaudRate600/* =bitmask for 600 Baud */,
sl@0
    54
	EUartBaudRate300/* =bitmask for 300 Baud */,
sl@0
    55
	EUartBaudRate150/* =bitmask for 150 Baud */,
sl@0
    56
	EUartBaudRate110/* =bitmask for 110 Baud */
sl@0
    57
	};
sl@0
    58
// EXAMPLE ONLY
sl@0
    59
enum TUartBreak
sl@0
    60
	{
sl@0
    61
	EUartBreakOff/* =bitmask for turning Break Off */,
sl@0
    62
	EUartBreakOn/* =bitmask for turning Break On */
sl@0
    63
	};
sl@0
    64
// EXAMPLE ONLY
sl@0
    65
enum TUartParity
sl@0
    66
	{
sl@0
    67
	EUartParityNone/* =bitmask for no Parity */,
sl@0
    68
	EUartParityOdd/* =bitmask for odd Parity */,
sl@0
    69
	EUartParityEven/* =bitmask for even Parity */
sl@0
    70
	};
sl@0
    71
// EXAMPLE ONLY
sl@0
    72
enum TUartStopBit
sl@0
    73
	{
sl@0
    74
	EUartStopBitOne/* =bitmask for one stop bit */,
sl@0
    75
	EUartStopBitTwo/* =bitmask for two stop bits */
sl@0
    76
	};
sl@0
    77
enum TUartDataLength
sl@0
    78
	{
sl@0
    79
	EUartDataLength5/* =bitmask for five data bits */,
sl@0
    80
	EUartDataLength6/* =bitmask for six data bits */,
sl@0
    81
	EUartDataLength7/* =bitmask for seven data bits */,
sl@0
    82
	EUartDataLength8/* =bitmask for eight data bits */
sl@0
    83
	};
sl@0
    84
sl@0
    85
//
sl@0
    86
// TO DO: (mandatory)
sl@0
    87
//
sl@0
    88
// Lookup table to convert EPOC baud rates into hardware-specific baud rate values
sl@0
    89
// Unsupported baud rates select the nearest lower rate.
sl@0
    90
//
sl@0
    91
// EXAMPLE ONLY
sl@0
    92
static const TUartBaudRate BaudRate[19] =
sl@0
    93
	{
sl@0
    94
	EUartBaudRate110,EUartBaudRate110,EUartBaudRate110,
sl@0
    95
	EUartBaudRate110,EUartBaudRate150,EUartBaudRate300,
sl@0
    96
	EUartBaudRate600,EUartBaudRate1200,EUartBaudRate110,
sl@0
    97
	EUartBaudRate110,EUartBaudRate2400,EUartBaudRate110,
sl@0
    98
	EUartBaudRate4800,EUartBaudRate110,EUartBaudRate9600,
sl@0
    99
	EUartBaudRate19200,EUartBaudRate38400,EUartBaudRate57600,
sl@0
   100
	EUartBaudRate115200
sl@0
   101
	};
sl@0
   102
sl@0
   103
//
sl@0
   104
// TO DO: (mandatory)
sl@0
   105
//
sl@0
   106
// Lookup table to convert EPOC parity settings into hardware-specific values
sl@0
   107
//
sl@0
   108
// EXAMPLE ONLY
sl@0
   109
static const TUartParity Parity[3] =
sl@0
   110
	{
sl@0
   111
	EUartParityNone,EUartParityEven,EUartParityOdd
sl@0
   112
	};
sl@0
   113
sl@0
   114
//
sl@0
   115
// TO DO: (mandatory)
sl@0
   116
//
sl@0
   117
// Lookup table to convert EPOC stop bit values into hardware-specific values
sl@0
   118
//
sl@0
   119
// EXAMPLE ONLY
sl@0
   120
static const TUartStopBit StopBit[2] =
sl@0
   121
	{
sl@0
   122
	EUartStopBitOne,EUartStopBitTwo
sl@0
   123
	};
sl@0
   124
sl@0
   125
//
sl@0
   126
// TO DO: (mandatory)
sl@0
   127
//
sl@0
   128
// Lookup table to convert EPOC data bit settings into hardware-specific values
sl@0
   129
//
sl@0
   130
// EXAMPLE ONLY
sl@0
   131
static const TUartDataLength DataLength[4] =
sl@0
   132
	{
sl@0
   133
	EUartDataLength5,EUartDataLength6,	
sl@0
   134
	EUartDataLength7,EUartDataLength8
sl@0
   135
	};
sl@0
   136
sl@0
   137
sl@0
   138
sl@0
   139
class DDriverComm : public DPhysicalDevice
sl@0
   140
	{
sl@0
   141
public:
sl@0
   142
	DDriverComm();
sl@0
   143
	virtual TInt Install();
sl@0
   144
	virtual void GetCaps(TDes8 &aDes) const;
sl@0
   145
	virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
sl@0
   146
	virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
sl@0
   147
	};
sl@0
   148
sl@0
   149
class DCommTemplate : public DComm
sl@0
   150
	{
sl@0
   151
public:
sl@0
   152
	DCommTemplate();
sl@0
   153
	~DCommTemplate();
sl@0
   154
	TInt DoCreate(TInt aUnit, const TDesC8* anInfo);
sl@0
   155
public:
sl@0
   156
	virtual TInt Start();
sl@0
   157
	virtual void Stop(TStopMode aMode);
sl@0
   158
	virtual void Break(TBool aState);
sl@0
   159
	virtual void EnableTransmit();
sl@0
   160
	virtual TUint Signals() const;
sl@0
   161
	virtual void SetSignals(TUint aSetMask,TUint aClearMask);
sl@0
   162
	virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const;
sl@0
   163
	virtual void Configure(TCommConfigV01 &aConfig);
sl@0
   164
	virtual void Caps(TDes8 &aCaps) const;
sl@0
   165
	virtual TInt DisableIrqs();
sl@0
   166
	virtual void RestoreIrqs(TInt aIrq);
sl@0
   167
	virtual TDfcQue* DfcQ(TInt aUnit);
sl@0
   168
	virtual void CheckConfig(TCommConfigV01& aConfig);
sl@0
   169
public:
sl@0
   170
	static void Isr(TAny* aPtr);
sl@0
   171
public:
sl@0
   172
	TInt iInterruptId;
sl@0
   173
	TInt iUnit;
sl@0
   174
	TLinAddr iPortAddr;
sl@0
   175
	TInt iInInterrupt;
sl@0
   176
	TUint iSignals;
sl@0
   177
	TDynamicDfcQue*	iDfcQ;
sl@0
   178
	};
sl@0
   179
sl@0
   180
sl@0
   181
DDriverComm::DDriverComm()
sl@0
   182
//
sl@0
   183
// Constructor
sl@0
   184
//
sl@0
   185
	{
sl@0
   186
	//
sl@0
   187
	// TO DO: (mandatory)
sl@0
   188
	//
sl@0
   189
	// Set up iUnitMask with the number of Units (Serial Ports) supported by this PDD,
sl@0
   190
	// 1 bit set per Unit supported e.g.:
sl@0
   191
	// iUnitsMask=0x7;	->  supports units 0, 1, 2
sl@0
   192
	//
sl@0
   193
	iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
sl@0
   194
	}
sl@0
   195
sl@0
   196
TInt DDriverComm::Install()
sl@0
   197
//
sl@0
   198
// Install the driver
sl@0
   199
//
sl@0
   200
	{
sl@0
   201
sl@0
   202
	return SetName(&KPddName);
sl@0
   203
	}
sl@0
   204
sl@0
   205
void GetTemplateCommsCaps(TDes8 &aCaps, TInt aUnit)
sl@0
   206
	{
sl@0
   207
	TCommCaps2 capsBuf;
sl@0
   208
	//
sl@0
   209
	// TO DO: (mandatory)
sl@0
   210
	//
sl@0
   211
	// Fill in the Caps structure with the relevant information for this Unit, e.g
sl@0
   212
	//  TCommCapsV02 &c=capsBuf();
sl@0
   213
	//	c.iRate=(OR in as many KCapsBpsXXX as bit rates supported);
sl@0
   214
	//	c.iDataBits=(OR in as many KCapsDataXXX as data length configuration supported);
sl@0
   215
	//	c.iStopBits=(OR in as many KCapsStopXXX as the number of stop bits configurations supported);
sl@0
   216
	//	c.iParity=(OR in as many KCapsParityXXX as parity configuration supported);
sl@0
   217
	//	c.iHandshake=(OR in all KCapsObeyXXXSupported, KCapsSendXXXSupported, KCapsFailXXXSupported, KCapsFreeXXXSupported
sl@0
   218
	//				  as required for this Unit's configuration);.
sl@0
   219
	//	c.iSignals=(OR in as many KCapsSignalXXXSupported as Modem control signals controllable by this Unit);
sl@0
   220
	//	c.iSIR=(0 or OR in as many KCapsSIRXXX as IR bit rates supported);
sl@0
   221
	//	c.iNotificationCaps=(OR in as many KNotifyXXXSupported as notifications supported by this Unit);
sl@0
   222
	//	c.iFifo=(0 or KCapsHasFifo);
sl@0
   223
	//	c.iRoleCaps=(0 or KCapsRoleSwitchSupported);
sl@0
   224
	//	c.iFlowControlCaps=(0 or KCapsFlowControlStatusSupported);
sl@0
   225
	/** @see TCommCapsV02 */
sl@0
   226
	//
sl@0
   227
	aCaps.FillZ(aCaps.MaxLength());
sl@0
   228
	aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
sl@0
   229
	}
sl@0
   230
sl@0
   231
void DDriverComm::GetCaps(TDes8 &aDes) const
sl@0
   232
//
sl@0
   233
// Return the drivers capabilities
sl@0
   234
//
sl@0
   235
	{
sl@0
   236
	GetTemplateCommsCaps(aDes, 0);
sl@0
   237
	}
sl@0
   238
sl@0
   239
TInt DDriverComm::Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer)
sl@0
   240
//
sl@0
   241
// Create a driver
sl@0
   242
//
sl@0
   243
	{
sl@0
   244
	DCommTemplate* pD=new DCommTemplate;
sl@0
   245
	aChannel=pD;
sl@0
   246
	TInt r=KErrNoMemory;
sl@0
   247
	if (pD)
sl@0
   248
		r=pD->DoCreate(aUnit,anInfo);
sl@0
   249
	return r;
sl@0
   250
	}
sl@0
   251
sl@0
   252
TInt DDriverComm::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer)
sl@0
   253
//
sl@0
   254
//	Validate the requested configuration (Version and Unit)
sl@0
   255
//
sl@0
   256
	{
sl@0
   257
	if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,KMinimumLddMinorVersion,KMinimumLddBuild))))
sl@0
   258
		return KErrNotSupported;
sl@0
   259
	//
sl@0
   260
	// TO DO: (mandatory)
sl@0
   261
	//
sl@0
   262
	// Return KErrNotSupported if aUnit is not in the supported range for this driver, KErrNone if it is
sl@0
   263
	//
sl@0
   264
	return KErrNone;
sl@0
   265
	}
sl@0
   266
sl@0
   267
DCommTemplate::DCommTemplate()
sl@0
   268
//
sl@0
   269
// Constructor
sl@0
   270
//
sl@0
   271
	{
sl@0
   272
	iInterruptId=-1;		// -1 means not bound
sl@0
   273
	}
sl@0
   274
sl@0
   275
DCommTemplate::~DCommTemplate()
sl@0
   276
//
sl@0
   277
// Destructor
sl@0
   278
//
sl@0
   279
	{
sl@0
   280
	if (iInterruptId>=0)
sl@0
   281
		Interrupt::Unbind(iInterruptId);
sl@0
   282
	
sl@0
   283
	if (iDfcQ)
sl@0
   284
		{
sl@0
   285
		iDfcQ->Destroy();
sl@0
   286
		}
sl@0
   287
	}
sl@0
   288
sl@0
   289
const TInt KDCommTemplDfcThreadPriority = 24;
sl@0
   290
_LIT(KDCommTemplDfcThread,"DCommTemplDfcThread");
sl@0
   291
sl@0
   292
TInt DCommTemplate::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/)
sl@0
   293
//
sl@0
   294
// Sets up the PDD
sl@0
   295
//
sl@0
   296
	{
sl@0
   297
	iUnit=aUnit;
sl@0
   298
	TInt irq=-1;
sl@0
   299
	//
sl@0
   300
	// TO DO: (mandatory)
sl@0
   301
	//
sl@0
   302
	//  Create own DFC queue
sl@0
   303
	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KDCommTemplDfcThreadPriority, KDCommTemplDfcThread);
sl@0
   304
sl@0
   305
	if (r != KErrNone)
sl@0
   306
		return r; 	
sl@0
   307
sl@0
   308
	// Set iPortAddr and irq with the Linear Base address of the UART and the Interrupt ID coresponding to aUnit
sl@0
   309
	//
sl@0
   310
sl@0
   311
	// bind to UART interrupt
sl@0
   312
	r=Interrupt::Bind(irq,Isr,this);
sl@0
   313
	if (r==KErrNone)
sl@0
   314
		iInterruptId=irq;
sl@0
   315
sl@0
   316
	//
sl@0
   317
	// TO DO: (optional)
sl@0
   318
	//
sl@0
   319
	// Any other setting up of UART hardware registers, required for:
sl@0
   320
	//  - Disabling the UART operation
sl@0
   321
	//  - disabling all UART Interrupts
sl@0
   322
	//  - clearing all Rx errors
sl@0
   323
	//  - clearing all UART interrupts
sl@0
   324
	//  - de-activating output Modem Control signals
sl@0
   325
	//
sl@0
   326
sl@0
   327
	Variant::MarkDebugPortOff();
sl@0
   328
	return r;
sl@0
   329
	}
sl@0
   330
sl@0
   331
TDfcQue* DCommTemplate::DfcQ(TInt aUnit)
sl@0
   332
//
sl@0
   333
// Return the DFC queue to be used for this device
sl@0
   334
// For UARTs just use the standard low priority DFC queue
sl@0
   335
// For Serial PC cards, use the PC card controller thread for the socket in question.
sl@0
   336
//
sl@0
   337
	{
sl@0
   338
	return aUnit==iUnit ? iDfcQ : NULL;
sl@0
   339
	}
sl@0
   340
sl@0
   341
TInt DCommTemplate::Start()
sl@0
   342
//
sl@0
   343
// Start receiving characters
sl@0
   344
//
sl@0
   345
	{
sl@0
   346
	iTransmitting=EFalse;			// if EnableTransmit() called before Start()
sl@0
   347
sl@0
   348
	//
sl@0
   349
	// TO DO: (mandatory)
sl@0
   350
	//
sl@0
   351
	// Set up hardware registers to enable the UART and switch receive mode on
sl@0
   352
	//
sl@0
   353
sl@0
   354
	// if (iUnit!=IR Port)											TO DO: (mandatory): Implement
sl@0
   355
		{
sl@0
   356
		iSignals=Signals();
sl@0
   357
		iLdd->UpdateSignals(iSignals);
sl@0
   358
		}
sl@0
   359
sl@0
   360
	//
sl@0
   361
	// TO DO: (optional)
sl@0
   362
	//
sl@0
   363
	// If Unit is IR Port may need to start the IR port
sl@0
   364
	//
sl@0
   365
	Interrupt::Enable(iInterruptId);
sl@0
   366
	return KErrNone;
sl@0
   367
	}
sl@0
   368
sl@0
   369
TBool FinishedTransmitting(TAny* aPtr)
sl@0
   370
	{
sl@0
   371
	//
sl@0
   372
	// TO DO: (mandatory)
sl@0
   373
	//
sl@0
   374
	// Return ETrue if UART is still transmitting, EFalse Otherwise
sl@0
   375
	//
sl@0
   376
	return EFalse;		// EXAMPLE ONLY
sl@0
   377
	}
sl@0
   378
sl@0
   379
void DCommTemplate::Stop(TStopMode aMode)
sl@0
   380
//
sl@0
   381
// Stop receiving characters
sl@0
   382
//
sl@0
   383
	{
sl@0
   384
	switch (aMode)
sl@0
   385
		{
sl@0
   386
		case EStopNormal:
sl@0
   387
		case EStopPwrDown:
sl@0
   388
			Interrupt::Disable(iInterruptId);
sl@0
   389
			iTransmitting=EFalse;
sl@0
   390
sl@0
   391
			// wait for uart to stop tranmitting
sl@0
   392
			Kern::PollingWait(FinishedTransmitting,this,3,100);
sl@0
   393
sl@0
   394
			//
sl@0
   395
			// TO DO: (optional)
sl@0
   396
			//
sl@0
   397
			// Any other setting up of UART hardware registers, required for:
sl@0
   398
			//  - Disabling the UART operation
sl@0
   399
			//  - disabling all UART Interrupts
sl@0
   400
			//  - disabling Transmit and Receive pathes
sl@0
   401
			//  - clearing all UART interrupts
sl@0
   402
			//
sl@0
   403
			break;
sl@0
   404
		case  EStopEmergency:
sl@0
   405
			Interrupt::Disable(iInterruptId);
sl@0
   406
			iTransmitting=EFalse;
sl@0
   407
			break;
sl@0
   408
		}
sl@0
   409
	//
sl@0
   410
	// TO DO: (optional)
sl@0
   411
	//
sl@0
   412
	// If Unit is IR Port may need to stop the IR port
sl@0
   413
	//
sl@0
   414
	Variant::MarkDebugPortOff();
sl@0
   415
	}
sl@0
   416
sl@0
   417
void DCommTemplate::Break(TBool aState)
sl@0
   418
//
sl@0
   419
// Start or stop the uart breaking
sl@0
   420
//
sl@0
   421
	{
sl@0
   422
	if (aState)
sl@0
   423
		{
sl@0
   424
		//
sl@0
   425
		// TO DO: (mandatory)
sl@0
   426
		//
sl@0
   427
		// Enable sending a Break (space) condition
sl@0
   428
		//
sl@0
   429
		}
sl@0
   430
	else
sl@0
   431
		{
sl@0
   432
		//
sl@0
   433
		// TO DO: (mandatory)
sl@0
   434
		//
sl@0
   435
		// Stop sending a Break (space) condition
sl@0
   436
		//
sl@0
   437
		}
sl@0
   438
	}
sl@0
   439
sl@0
   440
void DCommTemplate::EnableTransmit()
sl@0
   441
//
sl@0
   442
// Start sending characters.
sl@0
   443
//
sl@0
   444
	{
sl@0
   445
	TBool tx = (TBool)__e32_atomic_swp_ord32(&iTransmitting, 1);
sl@0
   446
	if (tx)
sl@0
   447
		return;
sl@0
   448
		TInt r = 0;
sl@0
   449
	while (/* (Transmit FIFO Not full) && */ Kern::PowerGood())				// TO DO: (mandatory): Implement
sl@0
   450
		{
sl@0
   451
		TInt r=TransmitIsr();
sl@0
   452
		if(r<0)
sl@0
   453
			{
sl@0
   454
			//no more to send
sl@0
   455
			iTransmitting=EFalse;
sl@0
   456
			break;
sl@0
   457
			}
sl@0
   458
		//
sl@0
   459
		// TO DO: (mandatory)
sl@0
   460
		//
sl@0
   461
		// Write transmit character into transmit FIFO or output register
sl@0
   462
		//
sl@0
   463
		}
sl@0
   464
	TInt irq=0;
sl@0
   465
	if (!iInInterrupt)					// CheckTxBuffer adds a Dfc: can only run from ISR or with NKernel locked
sl@0
   466
		{
sl@0
   467
		NKern::Lock();
sl@0
   468
		irq=NKern::DisableAllInterrupts();
sl@0
   469
		}
sl@0
   470
	CheckTxBuffer();
sl@0
   471
	if (!iInInterrupt)
sl@0
   472
		{
sl@0
   473
		NKern::RestoreInterrupts(irq);
sl@0
   474
		NKern::Unlock();
sl@0
   475
		}
sl@0
   476
	//
sl@0
   477
	// TO DO: (mandatory)
sl@0
   478
	//
sl@0
   479
	// Enable transmission of data
sl@0
   480
	//
sl@0
   481
	if (r>=0)											// only enable interrupt if there's more data to send
sl@0
   482
		{
sl@0
   483
		//
sl@0
   484
		// TO DO: (mandatory)
sl@0
   485
		//
sl@0
   486
		// Enable transmit interrupt in the Hardware (Interrupt::Enable() has already been called in Start())
sl@0
   487
		//
sl@0
   488
		}
sl@0
   489
	}
sl@0
   490
sl@0
   491
TUint DCommTemplate::Signals() const
sl@0
   492
//
sl@0
   493
// Read and translate the modem lines
sl@0
   494
//
sl@0
   495
	{
sl@0
   496
	TUint signals=0;
sl@0
   497
	//
sl@0
   498
	// TO DO: (mandatory)
sl@0
   499
	//
sl@0
   500
	// If the UART corresponding to iUnit supports Modem Control Signals, read them and return a bitmask with one or 
sl@0
   501
	// more of the following OR-ed in:
sl@0
   502
	// - KSignalDTR,
sl@0
   503
	// - KSignalRTS,
sl@0
   504
	// - KSignalDSR,
sl@0
   505
	// - KSignalCTS,
sl@0
   506
	// - KSignalDCD.
sl@0
   507
	// 
sl@0
   508
	return signals;
sl@0
   509
	}
sl@0
   510
sl@0
   511
void DCommTemplate::SetSignals(TUint aSetMask, TUint aClearMask)
sl@0
   512
//
sl@0
   513
// Set signals.
sl@0
   514
//
sl@0
   515
	{
sl@0
   516
	//
sl@0
   517
	// TO DO: (mandatory)
sl@0
   518
	//
sl@0
   519
	// If the UART corresponding to iUnit supports Modem Control Signals, converts the flags in aSetMask and aClearMask 
sl@0
   520
	// into hardware-specific bitmasks to write to the UART modem/handshake output register(s). 
sl@0
   521
	// aSetMask, aClearMask will have one or more of the following OR-ed in:
sl@0
   522
	// - KSignalDTR,
sl@0
   523
	// - KSignalRTS,
sl@0
   524
	//
sl@0
   525
	}
sl@0
   526
sl@0
   527
TInt DCommTemplate::ValidateConfig(const TCommConfigV01 &aConfig) const
sl@0
   528
//
sl@0
   529
// Check a config structure.
sl@0
   530
//
sl@0
   531
	{
sl@0
   532
	//
sl@0
   533
	// TO DO: (mandatory)
sl@0
   534
	//
sl@0
   535
	// Checks the the options in aConfig are supported by the UART corresponding to iUnit
sl@0
   536
	// May need to check:
sl@0
   537
	//  - aConfig.iParity (contains one of EParityXXX)
sl@0
   538
	/** @see TParity */
sl@0
   539
	//  - aConfig.iRate (contains one of EBpsXXX)
sl@0
   540
	/** @see TBps */
sl@0
   541
	//  - aConfig.iDataBits (contains one of EDataXXX)
sl@0
   542
	/** @see TDataBits */
sl@0
   543
	//  - aConfig.iStopBits (contains one of EStopXXX)
sl@0
   544
	/** @see TDataBits */
sl@0
   545
	//  - aConfig.iHandshake (contains one of KConfigObeyXXX or KConfigSendXXX or KConfigFailXXX or KConfigFreeXXX)
sl@0
   546
	//  - aConfig.iParityError (contains KConfigParityErrorFail or KConfigParityErrorIgnore or KConfigParityErrorReplaceChar)
sl@0
   547
	//  - aConfig.iFifo (contains ether EFifoEnable or EFifoDisable)
sl@0
   548
	/** @see TFifo */
sl@0
   549
	//  - aConfig.iSpecialRate (may contain a rate not listed under TBps)
sl@0
   550
	//  - aConfig.iTerminatorCount (conatains number of special characters used as terminators)
sl@0
   551
	//  - aConfig.iTerminator[] (contains a list of special characters which can be used as terminators)
sl@0
   552
	//  - aConfig.iXonChar (contains the character used as XON - software flow control)
sl@0
   553
	//  - aConfig.iXoffChar (contains the character used as XOFF - software flow control)
sl@0
   554
	//  - aConfig.iParityErrorChar (contains the character used to replace bytes received with a parity error)
sl@0
   555
	//  - aConfig.iSIREnable (contains either ESIREnable or ESIRDisable)
sl@0
   556
	/** @see TSir */
sl@0
   557
	//  - aConfig.iSIRSettings (contains one of KConfigSIRXXX)
sl@0
   558
	// and returns KErrNotSupported if the UART corresponding to iUnit does not support this configuration
sl@0
   559
	//
sl@0
   560
	return KErrNone;
sl@0
   561
	}
sl@0
   562
sl@0
   563
void DCommTemplate::CheckConfig(TCommConfigV01& aConfig)
sl@0
   564
	{
sl@0
   565
	//
sl@0
   566
	// TO DO: (optional)
sl@0
   567
	//
sl@0
   568
	// Validates the default configuration that is defined when a channel is first opened
sl@0
   569
	//
sl@0
   570
	}
sl@0
   571
sl@0
   572
TInt DCommTemplate::DisableIrqs()
sl@0
   573
//
sl@0
   574
// Disable normal interrupts
sl@0
   575
//
sl@0
   576
	{
sl@0
   577
	
sl@0
   578
	return NKern::DisableInterrupts(1);
sl@0
   579
	}
sl@0
   580
sl@0
   581
void DCommTemplate::RestoreIrqs(TInt aLevel)
sl@0
   582
//
sl@0
   583
// Restore normal interrupts
sl@0
   584
//
sl@0
   585
	{
sl@0
   586
	
sl@0
   587
	NKern::RestoreInterrupts(aLevel);
sl@0
   588
	}
sl@0
   589
sl@0
   590
void DCommTemplate::Configure(TCommConfigV01 &aConfig)
sl@0
   591
//
sl@0
   592
// Configure the UART from aConfig
sl@0
   593
//
sl@0
   594
	{
sl@0
   595
	Kern::PollingWait(FinishedTransmitting,this,3,100);	// wait for uart to stop tranmitting
sl@0
   596
sl@0
   597
	//
sl@0
   598
	// TO DO: (optional)
sl@0
   599
	//
sl@0
   600
	// Ensure Tx, Rx and the UART are disabled and disable sending Break (space) condition.
sl@0
   601
	// May need to modify clocks settings, pin functions etc.
sl@0
   602
	//
sl@0
   603
sl@0
   604
	//
sl@0
   605
	// TO DO: (mandatory)
sl@0
   606
	//
sl@0
   607
	// Set communications parameters such as:
sl@0
   608
	//  - Baud rate
sl@0
   609
	//  - Parity
sl@0
   610
	//  - Stop bits
sl@0
   611
	//  - Data bits
sl@0
   612
	// These can be obtained from aConfig using the look-up tables above, e.g.
sl@0
   613
	// TUint baudRate=BaudRate[aConfig.iRate];
sl@0
   614
	// TUint parity=Parity[aConfig.iParity];
sl@0
   615
	// TUint stopBits=StopBit[aConfig.iStopBits];
sl@0
   616
	// TUint dataBits=DataLength[aConfig.iDataBits];
sl@0
   617
	// Write these to the appropriate hardware registers using iPortAddr to identify which ste of register to modify
sl@0
   618
	//
sl@0
   619
sl@0
   620
	//
sl@0
   621
	// TO DO: (optional)
sl@0
   622
	//
sl@0
   623
	// If the UART corresponding to iUnit supports IR may need to set up IR transceiver
sl@0
   624
	//
sl@0
   625
	}
sl@0
   626
sl@0
   627
void DCommTemplate::Caps(TDes8 &aCaps) const
sl@0
   628
//
sl@0
   629
// return our caps
sl@0
   630
//
sl@0
   631
	{
sl@0
   632
	GetTemplateCommsCaps(aCaps,iUnit);
sl@0
   633
	}
sl@0
   634
sl@0
   635
void DCommTemplate::Isr(TAny* aPtr)
sl@0
   636
//
sl@0
   637
// Service the UART interrupt
sl@0
   638
//
sl@0
   639
	{
sl@0
   640
	DCommTemplate& d=*(DCommTemplate*)aPtr;
sl@0
   641
	d.iInInterrupt=1;										// going in...
sl@0
   642
	// TUint portAddr=d.iPortAddr;										TO DO: (mandatory): Uncomment this
sl@0
   643
sl@0
   644
	//
sl@0
   645
	// TO DO: (mandatory)
sl@0
   646
	//
sl@0
   647
	// Read the interrupt source register to determine if it is a Receive, Transmit or Modem Signals change interrupt.
sl@0
   648
	// If required also, clear interrupts at the source.
sl@0
   649
	// Then process the interrupt condition as in the following pseudo-code extract:
sl@0
   650
	//
sl@0
   651
	// if((Received character Interrupts) || (Error in received character Interupt))		TO DO: (mandatory): Implement
sl@0
   652
		{
sl@0
   653
		TUint rx[32];
sl@0
   654
		TUint xon=d.iLdd->iRxXonChar;
sl@0
   655
		TUint xoff=d.iLdd->iRxXoffChar;
sl@0
   656
		TInt rxi=0;
sl@0
   657
		TInt x=0;
sl@0
   658
		TUint ch=0;
sl@0
   659
	//	while((Receive FIFO not empty) && Kern::PowerGood())								TO DO: (mandatory): Implement
sl@0
   660
			{
sl@0
   661
			TUint regStatus1=0;
sl@0
   662
				// NOTE: for some hardware the order the following 2 operations is performed may have to be reversed
sl@0
   663
	//		if(Error in received character interrupt)										TO DO: (mandatory): Implement
sl@0
   664
	//			regStatus1=(Read receive error bitmask off appropriate register);
sl@0
   665
	//		ch=(Read received character);
sl@0
   666
			
sl@0
   667
			// coverity[dead_error_condition]
sl@0
   668
			// The next line should be reachable when this template file is edited for use
sl@0
   669
			if(regStatus1!=0)						// if error in this character
sl@0
   670
				{
sl@0
   671
	//			if (ch & (Parity Error))													TO DO: (mandatory): Implement
sl@0
   672
					ch|=KReceiveIsrParityError;
sl@0
   673
	//			if (ch & (Framing Error))													TO DO: (mandatory): Implement
sl@0
   674
					ch|=KReceiveIsrFrameError;
sl@0
   675
	//			if (ch & (Overrun))															TO DO: (mandatory): Implement
sl@0
   676
					ch|=KReceiveIsrOverrunError;
sl@0
   677
				}
sl@0
   678
			if (ch==xon)
sl@0
   679
				x=1;
sl@0
   680
			else if (ch==xoff)
sl@0
   681
				x=-1;
sl@0
   682
			else
sl@0
   683
				rx[rxi++]=ch;
sl@0
   684
			}
sl@0
   685
		d.ReceiveIsr(rx,rxi,x);
sl@0
   686
		}
sl@0
   687
	// if((Transmitted character Interrupt))												TO DO: (mandatory): Implement
sl@0
   688
		{
sl@0
   689
		while(/* (Transmit FIFO Not full) && */ Kern::PowerGood())							// TO DO: (mandatory): Implement
sl@0
   690
			{
sl@0
   691
			TInt r=d.TransmitIsr();
sl@0
   692
			if(r<0)
sl@0
   693
				{
sl@0
   694
				//no more to send
sl@0
   695
				//
sl@0
   696
				// TO DO: (mandatory)
sl@0
   697
				//
sl@0
   698
				// Disable the Transmit Interrupt in Hardware
sl@0
   699
				d.iTransmitting=EFalse;
sl@0
   700
				break;
sl@0
   701
				}
sl@0
   702
			// (write transmit character to output FIFO or Data register)					TO DO: (mandatory): Implement
sl@0
   703
			}
sl@0
   704
		d.CheckTxBuffer();
sl@0
   705
		}
sl@0
   706
	// if((Modem Signals changed Interrupt))												TO DO: (mandatory): Implement
sl@0
   707
		{
sl@0
   708
		TUint signals=d.Signals()&KDTEInputSignals;
sl@0
   709
		if (signals != d.iSignals)
sl@0
   710
			{
sl@0
   711
			d.iSignals=signals;
sl@0
   712
			d.iLdd->StateIsr(signals);
sl@0
   713
			}
sl@0
   714
		}
sl@0
   715
	d.iInInterrupt=0;										// going out...
sl@0
   716
	}
sl@0
   717
sl@0
   718
DECLARE_STANDARD_PDD()
sl@0
   719
	{
sl@0
   720
	return new DDriverComm;
sl@0
   721
	}
sl@0
   722