os/boardsupport/emulator/emulatorbsp/specific/serialpdd.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/serialpdd.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "winscomm.h"
sl@0
    19
#include "nk_priv.h"
sl@0
    20
#include "nk_plat.h"
sl@0
    21
#include <emulator.h>
sl@0
    22
sl@0
    23
#define WIN32_LEAN_AND_MEAN
sl@0
    24
#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
sl@0
    25
#include <windows.h>
sl@0
    26
#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
sl@0
    27
sl@0
    28
#ifdef FAULT
sl@0
    29
#undef FAULT
sl@0
    30
#endif
sl@0
    31
#define FAULT() Kern::Fault(__FILE__,__LINE__)
sl@0
    32
sl@0
    33
_LIT(KComName, "\\\\.\\com");
sl@0
    34
sl@0
    35
// needs ldd version..
sl@0
    36
const TInt KMinimumLddMajorVersion=1;
sl@0
    37
const TInt KMinimumLddMinorVersion=1;
sl@0
    38
const TInt KMinimumLddBuild=1;		
sl@0
    39
sl@0
    40
//used for the read and write buffers in the driver.
sl@0
    41
//large buffer reserved so any transfer to/from the client can fit into a driver buffer
sl@0
    42
const TInt KSerialBufferMaxSize = 0x800000;
sl@0
    43
const TInt KSerialBufferInitialSize = 0x10000;
sl@0
    44
const TInt KSerialBufferIncrementSize = 0x1000;	//granularity.  must be power of 2	
sl@0
    45
sl@0
    46
sl@0
    47
const DWORD KReadOneOrMoreTimeout = MAXDWORD-1;	//milliseconds
sl@0
    48
sl@0
    49
sl@0
    50
//buffer sizes passed to NT for setting its own driver buffer sizes
sl@0
    51
const TInt KDefaultWinNTReadBufSize = 1024;
sl@0
    52
const TInt KDefaultWinNTWriteBufSize = 1024;
sl@0
    53
sl@0
    54
static DWORD dummyLen=0;
sl@0
    55
sl@0
    56
enum TDCommWinsFault 
sl@0
    57
	{
sl@0
    58
	EWindowsUnexpectedError,
sl@0
    59
	EUnknownCommand,
sl@0
    60
	EBadIOLen,
sl@0
    61
	EEofOnSerial,
sl@0
    62
	EWriteEarlyCompletion,
sl@0
    63
	ELineErrorNotReported,
sl@0
    64
	ESerialBufferTooBig,
sl@0
    65
	EReadLength,
sl@0
    66
	};
sl@0
    67
sl@0
    68
sl@0
    69
class DDriverComm : public DPhysicalDevice
sl@0
    70
	{
sl@0
    71
public:
sl@0
    72
	DDriverComm();
sl@0
    73
	virtual TInt Install();
sl@0
    74
	virtual TInt Remove();
sl@0
    75
	virtual void GetCaps(TDes8 &aDes) const;
sl@0
    76
	virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
sl@0
    77
	virtual TInt Validate(TInt aUnit, const TDesC8* aInfo, const TVersion &aVer);
sl@0
    78
	};
sl@0
    79
sl@0
    80
sl@0
    81
class DCommWins : public DComm
sl@0
    82
	{
sl@0
    83
public:
sl@0
    84
	enum TDriverCommand {ESetBreak=1,EClearBreak,ETransmit,ETransmit0,
sl@0
    85
						EGetSignals,ESetSignals,EConfigure,
sl@0
    86
						EStop,EStopNoDrain,EStart,EDie,	ETransmitCancel,
sl@0
    87
						EReceive, EReceiveOneOrMore, EReceiveCancel,ENotifyDataAvailable,
sl@0
    88
						ENotifySignals, EInvalidCommand};
sl@0
    89
public:
sl@0
    90
	DCommWins();
sl@0
    91
	~DCommWins();
sl@0
    92
	virtual TInt Start();
sl@0
    93
	virtual void Stop(TStopMode aMode);
sl@0
    94
	virtual void Break(TBool aState);
sl@0
    95
	virtual void Write(DThread* aThread, TAny *aTxDes, TInt aLength);
sl@0
    96
	virtual void Read(DThread* aThread, TAny *aTxDes, TInt aLength);
sl@0
    97
	virtual void NotifySignals(DThread* aThread, TInt aMask);
sl@0
    98
	virtual void NotifyDataAvailable();
sl@0
    99
	virtual TUint Signals() const;
sl@0
   100
	virtual void SetSignals(TUint aSetMask,TUint aClearMask);
sl@0
   101
	virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const;
sl@0
   102
	virtual void Configure(TCommConfigV01 &aConfig);
sl@0
   103
	virtual void Caps(TDes8 &aCaps) const;
sl@0
   104
	virtual void CheckConfig(TCommConfigV01& aConfig);
sl@0
   105
	virtual TDfcQue* DfcQ(TInt aUnit);
sl@0
   106
sl@0
   107
	inline void CheckTxBuffer();
sl@0
   108
	inline TBool Transmitting();
sl@0
   109
	virtual TInt RxCount();
sl@0
   110
	virtual void ResetBuffers(TBool);
sl@0
   111
	virtual TInt SetRxBufferSize(TInt aSize);
sl@0
   112
	virtual TInt RxBufferSize();
sl@0
   113
	virtual TDes8* RxBuffer();
sl@0
   114
	virtual void DoConfigure();
sl@0
   115
	virtual TBool AreAnyPending();
sl@0
   116
	virtual void ReadCancel();
sl@0
   117
	virtual void WriteCancel();
sl@0
   118
	virtual void SignalChangeCancel();
sl@0
   119
	TInt DoCreate(TInt aUnit,const TDesC8 *aInfo);
sl@0
   120
	void WaitForEvent();
sl@0
   121
	void DriverCommand(TDriverCommand aCommand);
sl@0
   122
	void DoWriteComplete(TInt aErr);
sl@0
   123
	void DoReadComplete(TInt aErr, TInt aBytes);
sl@0
   124
	void DoSignalCompletion(TInt aError, TUint changed, TUint aValues);
sl@0
   125
	void DoDataAvailableCompletion();
sl@0
   126
	void RunCommThread(TDriverCommand aCommand);
sl@0
   127
	inline void SignalDriverThread();
sl@0
   128
	inline TBool LineFail();
sl@0
   129
	
sl@0
   130
private:
sl@0
   131
	void ReleaseBuffers();
sl@0
   132
	void ReSizeBuffer(TUint8*& aBuf, TInt& iBufLen, TPtr8& aDes, const TInt aNewLen);
sl@0
   133
	TBool IsATerminator(TText8 aChar);
sl@0
   134
	void CompleteRead(TInt aLength);
sl@0
   135
	void DataAvailableNotificationCancel();
sl@0
   136
sl@0
   137
sl@0
   138
private:
sl@0
   139
	TInt iWritePending;
sl@0
   140
	TInt iReadPending;
sl@0
   141
	TBool iStopping;
sl@0
   142
	TBool iRunning;
sl@0
   143
	TDriverCommand iCommand;
sl@0
   144
	TCommConfigV01 *iConfig;
sl@0
   145
	TUint iSignals;
sl@0
   146
	TUint iFailSignals;
sl@0
   147
	TUint iSavedSignals;
sl@0
   148
	TBool iLineFail;
sl@0
   149
	TBool iRXLineFail;
sl@0
   150
	TBool iTXLineFail;
sl@0
   151
sl@0
   152
	TUint8 * iInBufPtr;		//input buffer used by driver.
sl@0
   153
	TInt iInBufLength;
sl@0
   154
	TPtr8 iInDes;
sl@0
   155
sl@0
   156
	TInt iReadSoFar;
sl@0
   157
	TBool iTerminatedRead;	//true if we are reading with 1 or more terminating characters
sl@0
   158
sl@0
   159
	TUint8 * iOutBufPtr;
sl@0
   160
	TInt iOutBufLength;
sl@0
   161
	TPtr8 iOutDes;
sl@0
   162
sl@0
   163
	TInt iRxBufferSize;		//size of receivebuffer passed to windows & set by calls to SetReceiveBufferSize 
sl@0
   164
							//used to determine xon and xoff levels
sl@0
   165
	TUint iSignalsRequested;  //mask of signals we are waiting for
sl@0
   166
	TUint iSignalsWanted;		//mask we are asked to check 
sl@0
   167
	TBool iDataAvailableNotification;
sl@0
   168
	HANDLE iThread;
sl@0
   169
	HANDLE iCommThreadSem;
sl@0
   170
	HANDLE iDriverThreadSem;
sl@0
   171
	HANDLE iCommPort;
sl@0
   172
	DWORD iThreadID;
sl@0
   173
	DWORD iSignalStatus;
sl@0
   174
	OVERLAPPED iReadOverLapped;
sl@0
   175
	OVERLAPPED iWriteOverLapped;
sl@0
   176
	OVERLAPPED iSignalOverLapped;
sl@0
   177
sl@0
   178
	TInt iClientReadLength;		//how much data the client has requested in a read
sl@0
   179
	TBool		iBreakDetected;
sl@0
   180
	};
sl@0
   181
sl@0
   182
void Panic(TDCommWinsFault aFault)
sl@0
   183
//
sl@0
   184
// Panic the driver 
sl@0
   185
//
sl@0
   186
	{
sl@0
   187
	Kern::PanicCurrentThread(_L("DCommWins"), aFault);
sl@0
   188
	}
sl@0
   189
sl@0
   190
sl@0
   191
TUint commThread(DCommWins *comm)
sl@0
   192
//
sl@0
   193
// Comm thread entry point
sl@0
   194
//
sl@0
   195
	{
sl@0
   196
sl@0
   197
	comm->WaitForEvent();
sl@0
   198
	return 0;
sl@0
   199
	}
sl@0
   200
sl@0
   201
VOID WINAPI WriteCompletion(DCommWins *aDrv, DWORD aErr,DWORD /*numBytes*/)
sl@0
   202
	{
sl@0
   203
sl@0
   204
	aDrv->DoWriteComplete(aErr);
sl@0
   205
	}
sl@0
   206
sl@0
   207
sl@0
   208
VOID WINAPI ReadCompletion(DCommWins *aDrv, DWORD aErr,DWORD numBytes)
sl@0
   209
	{
sl@0
   210
sl@0
   211
	aDrv->DoReadComplete(aErr, numBytes);
sl@0
   212
	}
sl@0
   213
sl@0
   214
VOID WINAPI SignalCompletion(DCommWins *aDrv, TInt aError, TUint aChanged, TUint aValues)
sl@0
   215
	{
sl@0
   216
	aDrv->DoSignalCompletion(aError, aChanged, aValues);
sl@0
   217
	}
sl@0
   218
sl@0
   219
VOID WINAPI DataAvailableCompletion(DCommWins *aDrv)
sl@0
   220
	{
sl@0
   221
	aDrv->DoDataAvailableCompletion();
sl@0
   222
	}
sl@0
   223
sl@0
   224
sl@0
   225
sl@0
   226
BOOL WINAPI EscapeCommFunctionP(HANDLE hFile,DWORD dwFunc)
sl@0
   227
	{
sl@0
   228
	DWORD err;
sl@0
   229
	DWORD lastError = 0;
sl@0
   230
	BOOL res;
sl@0
   231
	COMSTAT s;
sl@0
   232
	
sl@0
   233
	do
sl@0
   234
		{
sl@0
   235
		ClearCommError(hFile, &err, &s);
sl@0
   236
		res = EscapeCommFunction(hFile,dwFunc);
sl@0
   237
		if(!res)
sl@0
   238
			lastError = GetLastError();
sl@0
   239
		}
sl@0
   240
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   241
sl@0
   242
	return(res);
sl@0
   243
	}
sl@0
   244
sl@0
   245
sl@0
   246
BOOL WINAPI GetCommModemStatusP(HANDLE hFile,LPDWORD lpModemStat)
sl@0
   247
	{
sl@0
   248
	DWORD err;
sl@0
   249
	DWORD lastError = 0;
sl@0
   250
	BOOL res;
sl@0
   251
	COMSTAT s;
sl@0
   252
	
sl@0
   253
	do
sl@0
   254
		{
sl@0
   255
		ClearCommError(hFile, &err, &s);
sl@0
   256
		res = GetCommModemStatus(hFile,lpModemStat);
sl@0
   257
		if(!res)
sl@0
   258
			lastError  = GetLastError();
sl@0
   259
		}
sl@0
   260
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   261
sl@0
   262
	return(res);
sl@0
   263
	}
sl@0
   264
sl@0
   265
sl@0
   266
BOOL WINAPI GetCommStateP(HANDLE hFile,LPDCB lpDCB)
sl@0
   267
	{
sl@0
   268
	DWORD err;
sl@0
   269
	DWORD lastError = 0;
sl@0
   270
	BOOL res;
sl@0
   271
	COMSTAT s;
sl@0
   272
	
sl@0
   273
	do
sl@0
   274
		{
sl@0
   275
		ClearCommError(hFile,&err,&s);
sl@0
   276
		res = GetCommState(hFile,lpDCB);
sl@0
   277
		if (!res)
sl@0
   278
			lastError = GetLastError();
sl@0
   279
		}
sl@0
   280
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   281
sl@0
   282
	return(res);
sl@0
   283
	}
sl@0
   284
sl@0
   285
BOOL WINAPI SetCommStateP(HANDLE hFile,LPDCB lpDCB)
sl@0
   286
	{
sl@0
   287
	DWORD err;
sl@0
   288
	DWORD lastError = 0;
sl@0
   289
	BOOL res;
sl@0
   290
	COMSTAT s;
sl@0
   291
	
sl@0
   292
	do
sl@0
   293
		{
sl@0
   294
		ClearCommError(hFile, &err, &s);
sl@0
   295
		res = SetCommState(hFile, lpDCB);
sl@0
   296
		if (!res)
sl@0
   297
			lastError = GetLastError();
sl@0
   298
		}
sl@0
   299
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   300
sl@0
   301
	return(res);
sl@0
   302
	}
sl@0
   303
sl@0
   304
BOOL WINAPI SetCommMaskP(HANDLE hFile,DWORD dwEvtMask)
sl@0
   305
	{
sl@0
   306
	DWORD err;
sl@0
   307
	DWORD lastError = 0;
sl@0
   308
	BOOL res;
sl@0
   309
	COMSTAT s;
sl@0
   310
	
sl@0
   311
	do
sl@0
   312
		{
sl@0
   313
		ClearCommError(hFile, &err, &s);
sl@0
   314
		res = SetCommMask(hFile, dwEvtMask);
sl@0
   315
		if (!res)
sl@0
   316
			lastError = GetLastError();
sl@0
   317
		}
sl@0
   318
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   319
sl@0
   320
	return(res);
sl@0
   321
	}
sl@0
   322
sl@0
   323
BOOL WINAPI WriteFileP(HANDLE hFile,LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped)
sl@0
   324
	{
sl@0
   325
	DWORD err;
sl@0
   326
	DWORD lastError = 0;
sl@0
   327
	BOOL res;
sl@0
   328
	COMSTAT s;
sl@0
   329
	
sl@0
   330
	do
sl@0
   331
		{
sl@0
   332
		ClearCommError(hFile, &err, &s);
sl@0
   333
		res = WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
sl@0
   334
		if (!res)
sl@0
   335
			lastError = GetLastError();
sl@0
   336
		}
sl@0
   337
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   338
sl@0
   339
	return(res);
sl@0
   340
	}
sl@0
   341
sl@0
   342
BOOL WINAPI ReadFileP(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped)
sl@0
   343
	{
sl@0
   344
	DWORD err;
sl@0
   345
	DWORD lastError = 0;
sl@0
   346
	BOOL res;
sl@0
   347
	COMSTAT s;
sl@0
   348
	
sl@0
   349
	do
sl@0
   350
		{
sl@0
   351
		ClearCommError(hFile, &err, &s);
sl@0
   352
		res = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
sl@0
   353
		if (!res)
sl@0
   354
			lastError = GetLastError();
sl@0
   355
		}
sl@0
   356
	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
sl@0
   357
sl@0
   358
	return(res);
sl@0
   359
	}
sl@0
   360
sl@0
   361
sl@0
   362
sl@0
   363
sl@0
   364
DDriverComm::DDriverComm()
sl@0
   365
	{
sl@0
   366
#if defined (__COM_ONE_ONLY__)
sl@0
   367
	iUnitsMask=0x1; // Support units 0
sl@0
   368
#elif defined (__COM_TWO_ONLY__)
sl@0
   369
	iUnitsMask=0x2; // Support units 1
sl@0
   370
#else
sl@0
   371
	iUnitsMask=0x3ff; // Support units 0 to 9
sl@0
   372
#endif
sl@0
   373
sl@0
   374
	iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
sl@0
   375
	}
sl@0
   376
sl@0
   377
TInt DDriverComm::Install()
sl@0
   378
	{
sl@0
   379
#if defined (__COM_ONE_ONLY__)
sl@0
   380
	TPtrC buf=_L("Comm.Wins1");
sl@0
   381
	return(SetName(&buf));
sl@0
   382
#elif defined (__COM_TWO_ONLY__)
sl@0
   383
	TPtrC buf=_L("Comm.Wins2");
sl@0
   384
	return(SetName(&buf));
sl@0
   385
#else
sl@0
   386
	TPtrC buf=_L("Comm.Wins");
sl@0
   387
	return(SetName(&buf));
sl@0
   388
#endif
sl@0
   389
	}
sl@0
   390
sl@0
   391
TInt DDriverComm::Remove()
sl@0
   392
	{
sl@0
   393
	return(KErrNone);
sl@0
   394
	}
sl@0
   395
sl@0
   396
sl@0
   397
TInt DDriverComm::Validate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
sl@0
   398
//
sl@0
   399
//	Validate the requested configuration
sl@0
   400
//
sl@0
   401
	{
sl@0
   402
	if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,KMinimumLddMinorVersion,KMinimumLddBuild))))
sl@0
   403
		return KErrNotSupported;
sl@0
   404
#if defined (__COM_ONE_ONLY__)
sl@0
   405
	if (aUnit!=0)
sl@0
   406
		return KErrNotSupported;
sl@0
   407
#elif defined (__COM_TWO_ONLY__)
sl@0
   408
	if (aUnit!=1)
sl@0
   409
		return KErrNotSupported;
sl@0
   410
#endif
sl@0
   411
	// leave Unit check to CreateFile
sl@0
   412
	return KErrNone;
sl@0
   413
	}
sl@0
   414
sl@0
   415
sl@0
   416
void GetWinsCommsCaps(TDes8 &aCaps)
sl@0
   417
	{
sl@0
   418
	TCommCaps3 capsBuf;
sl@0
   419
	TCommCapsV03 &c=capsBuf();
sl@0
   420
//
sl@0
   421
// All rates except 50,2000, 3600 and special
sl@0
   422
//
sl@0
   423
	c.iRate=KCapsBps75|KCapsBps110|KCapsBps134|KCapsBps150|KCapsBps300|KCapsBps600|KCapsBps1200|KCapsBps1800|KCapsBps2400|KCapsBps4800|KCapsBps7200|KCapsBps9600|KCapsBps19200|KCapsBps38400|KCapsBps57600|KCapsBps115200;
sl@0
   424
sl@0
   425
	c.iDataBits=0xf; // All data sizes
sl@0
   426
	c.iStopBits=0x3; // 1 and 2 stop bits
sl@0
   427
	c.iParity=0x7; // None, Even and Odd
sl@0
   428
	c.iHandshake = 0x3BF;	//all except KConfigObeyDCD
sl@0
   429
	c.iSignals=0x3f; // All signals
sl@0
   430
	c.iSIR=0;//No Ir
sl@0
   431
	c.iNotificationCaps=KNotifySignalsChangeSupported|KNotifyDataAvailableSupported;
sl@0
   432
	c.iRoleCaps=0;
sl@0
   433
	c.iFlowControlCaps=0;
sl@0
   434
	c.iBreakSupported=ETrue;
sl@0
   435
	aCaps.FillZ(aCaps.MaxLength());
sl@0
   436
	aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
sl@0
   437
	}
sl@0
   438
sl@0
   439
void DDriverComm::GetCaps(TDes8 &aDes) const
sl@0
   440
	{
sl@0
   441
	GetWinsCommsCaps(aDes);
sl@0
   442
	}
sl@0
   443
sl@0
   444
TInt DDriverComm::Create(DBase*& aChannel, TInt aUnit,const TDesC8* aInfo,const TVersion& aVer)
sl@0
   445
	{
sl@0
   446
sl@0
   447
	if (!Kern::QueryVersionSupported(iVersion,aVer))
sl@0
   448
		return KErrNotSupported;
sl@0
   449
sl@0
   450
	DCommWins *pD= new DCommWins;
sl@0
   451
	if (!pD) return KErrNoMemory;
sl@0
   452
sl@0
   453
	TInt ret=pD->DoCreate(aUnit,aInfo);
sl@0
   454
sl@0
   455
	if (ret!=KErrNone)
sl@0
   456
	{
sl@0
   457
		delete pD;
sl@0
   458
		return ret;
sl@0
   459
	}
sl@0
   460
	
sl@0
   461
	aChannel = pD;
sl@0
   462
sl@0
   463
	return KErrNone;
sl@0
   464
	}
sl@0
   465
sl@0
   466
void DCommWins::DoWriteComplete(TInt aErr)
sl@0
   467
	{
sl@0
   468
	iWritePending = 0;
sl@0
   469
	iTransmitting = EFalse;
sl@0
   470
	StartOfInterrupt();
sl@0
   471
	iLdd->iTxError = aErr;
sl@0
   472
	iLdd->iTxCompleteDfc.Add();
sl@0
   473
	EndOfInterrupt();
sl@0
   474
	}
sl@0
   475
sl@0
   476
sl@0
   477
sl@0
   478
void DCommWins::DoSignalCompletion(TInt aError, TUint aChanged, TUint aValues)
sl@0
   479
	{
sl@0
   480
	//aValues contains the signal values.  EPOC constants
sl@0
   481
	//aChanged contains the signals which have changed
sl@0
   482
	//we return the signal values
sl@0
   483
	TUint res = aValues & iSignalsWanted;
sl@0
   484
	res |= (aChanged << 12);
sl@0
   485
	
sl@0
   486
	iLdd->iSignalResult = res;
sl@0
   487
	iLdd->iSignalError = aError;
sl@0
   488
	StartOfInterrupt();
sl@0
   489
	iLdd->iSigNotifyDfc.Add();
sl@0
   490
	EndOfInterrupt();
sl@0
   491
	}
sl@0
   492
sl@0
   493
void DCommWins::DoDataAvailableCompletion()
sl@0
   494
	{
sl@0
   495
	StartOfInterrupt();
sl@0
   496
	iLdd->iRxDataAvailableDfc.Add();
sl@0
   497
	EndOfInterrupt();
sl@0
   498
	}
sl@0
   499
sl@0
   500
sl@0
   501
sl@0
   502
void DCommWins::CompleteRead(TInt aLength)
sl@0
   503
	{
sl@0
   504
	iReadPending = 0;
sl@0
   505
	iInDes.SetLength(aLength);
sl@0
   506
	StartOfInterrupt();
sl@0
   507
	iLdd->iRxCompleteDfc.Add();
sl@0
   508
	EndOfInterrupt();
sl@0
   509
	}
sl@0
   510
sl@0
   511
sl@0
   512
sl@0
   513
void DCommWins::DoReadComplete(TInt aErr, TInt aBytes)
sl@0
   514
	{
sl@0
   515
	iLdd->iRxError = aErr;
sl@0
   516
	//write back the length and the data
sl@0
   517
	//process for any terminating characters.
sl@0
   518
	//win32 only does binary reads and ignores the eofchar, so terminated reads
sl@0
   519
	//require reading one char at a time
sl@0
   520
	if (iTerminatedRead && !aErr)
sl@0
   521
		{
sl@0
   522
		__NK_ASSERT_ALWAYS(aBytes <= 1);
sl@0
   523
		if (aBytes == 0)
sl@0
   524
			{
sl@0
   525
			// not sure why we get this somtimes, but handle it anyway : read another character
sl@0
   526
			ReadFileP(iCommPort,(void*)(iInBufPtr+iReadSoFar), 1, &dummyLen, &iReadOverLapped);
sl@0
   527
			}
sl@0
   528
		else if (++iReadSoFar == iClientReadLength)	//see if we have read enough characters into the buffer
sl@0
   529
			{
sl@0
   530
			//got them all so complete it
sl@0
   531
			CompleteRead(iReadSoFar);
sl@0
   532
			}
sl@0
   533
		else if (IsATerminator(iInBufPtr[iReadSoFar-1]))	//see if the char just read was the terminator
sl@0
   534
			{
sl@0
   535
			//it's a terminated read and we've found one of the terminbators
sl@0
   536
			CompleteRead(iReadSoFar);
sl@0
   537
			}
sl@0
   538
		else if (iReadPending == EReceive)
sl@0
   539
			{
sl@0
   540
			//read another character
sl@0
   541
			ReadFileP(iCommPort,(void*)(iInBufPtr+iReadSoFar), 1, &dummyLen, &iReadOverLapped);
sl@0
   542
			}
sl@0
   543
		else
sl@0
   544
			{
sl@0
   545
			//it's a receive 1 or more with terminators, we've got 1 so that'll do
sl@0
   546
			CompleteRead(iReadSoFar);
sl@0
   547
			}
sl@0
   548
		}
sl@0
   549
	else
sl@0
   550
		{
sl@0
   551
		CompleteRead(aBytes);
sl@0
   552
		}
sl@0
   553
	}
sl@0
   554
sl@0
   555
sl@0
   556
sl@0
   557
sl@0
   558
void DCommWins::RunCommThread(TDriverCommand aCommand)
sl@0
   559
//
sl@0
   560
// Wake up the comms thread
sl@0
   561
//
sl@0
   562
	{
sl@0
   563
sl@0
   564
	__ASSERT_DEBUG(aCommand!=EInvalidCommand,Panic(EUnknownCommand));
sl@0
   565
	iCommand=aCommand;
sl@0
   566
//
sl@0
   567
// Are we about to go re-entrant?
sl@0
   568
//
sl@0
   569
	if(GetCurrentThreadId()==iThreadID)
sl@0
   570
		{
sl@0
   571
		DriverCommand(aCommand);
sl@0
   572
		WaitForSingleObject(iDriverThreadSem,INFINITE);
sl@0
   573
		}
sl@0
   574
	else
sl@0
   575
		{
sl@0
   576
		Sleep(0); // Possible deadlock solution - see MSDN Knowledge Base Article Q173260
sl@0
   577
		if (ReleaseSemaphore(iCommThreadSem,1,NULL)==FALSE)
sl@0
   578
			{
sl@0
   579
			DWORD ret=GetLastError();
sl@0
   580
			ret=ret;
sl@0
   581
			Panic(EWindowsUnexpectedError);
sl@0
   582
			}
sl@0
   583
		WaitForSingleObject(iDriverThreadSem,INFINITE);
sl@0
   584
		}
sl@0
   585
	}
sl@0
   586
sl@0
   587
inline void DCommWins::SignalDriverThread()
sl@0
   588
//
sl@0
   589
// Wake up the comms thread
sl@0
   590
//
sl@0
   591
	{
sl@0
   592
	Sleep(0); // Possible deadlock solution - see MSDN Knowledge Base Article Q173260
sl@0
   593
	if (ReleaseSemaphore(iDriverThreadSem,1,NULL)==FALSE)
sl@0
   594
		{
sl@0
   595
		DWORD ret=GetLastError();
sl@0
   596
		ret=ret;
sl@0
   597
		Panic(EWindowsUnexpectedError);
sl@0
   598
		}
sl@0
   599
	}
sl@0
   600
sl@0
   601
sl@0
   602
sl@0
   603
//
sl@0
   604
#pragma warning( disable : 4705 )	// statement has no effect
sl@0
   605
DCommWins::DCommWins() :  iOutDes(0,0), iInDes(0,0), iRxBufferSize(KDefaultWinNTReadBufSize), iSignalsRequested(0)
sl@0
   606
	{
sl@0
   607
	__DECLARE_NAME(_S("DCommWins"));
sl@0
   608
	}
sl@0
   609
#pragma warning( default : 4705 )
sl@0
   610
sl@0
   611
TInt DCommWins::DoCreate(TInt aUnit,const TDesC8 * /*aInfo*/)
sl@0
   612
//
sl@0
   613
// Create the comms driver.
sl@0
   614
//
sl@0
   615
	{
sl@0
   616
sl@0
   617
#if defined (__COM_ONE_ONLY__)
sl@0
   618
	if (aUnit!=0)
sl@0
   619
		return KErrNotSupported;
sl@0
   620
#elif defined (__COM_TWO_ONLY__)
sl@0
   621
	if (aUnit!=1)
sl@0
   622
		return KErrNotSupported;
sl@0
   623
#endif
sl@0
   624
sl@0
   625
	TBuf8<0x10> n;
sl@0
   626
	n.Append(KComName);
sl@0
   627
	n.AppendNum(aUnit+1);
sl@0
   628
	n.Append('\0');
sl@0
   629
sl@0
   630
	iCommPort=CreateFileA((LPCSTR)n.Ptr(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
sl@0
   631
	if (iCommPort==INVALID_HANDLE_VALUE)	
sl@0
   632
		{	
sl@0
   633
	//	Reused code from Emulator::LastError() rather than adding an extra case 
sl@0
   634
	//	to Emulator::LastError() because mapping KErrNotSupported to the returned
sl@0
   635
	//	FILE_NOT_FOUND is non-intuitive and special to this case only
sl@0
   636
		DWORD winErr=GetLastError();
sl@0
   637
		switch (winErr)
sl@0
   638
			{
sl@0
   639
			case ERROR_INVALID_USER_BUFFER:
sl@0
   640
			case ERROR_NOT_ENOUGH_MEMORY:
sl@0
   641
			case ERROR_INSUFFICIENT_BUFFER:
sl@0
   642
				return(KErrNoMemory);
sl@0
   643
			case ERROR_ACCESS_DENIED:
sl@0
   644
				return(KErrAccessDenied);
sl@0
   645
			case ERROR_FILE_NOT_FOUND:		//	Reflects value returned by
sl@0
   646
				return(KErrNotSupported);	//	corresponding MARM Pdd  
sl@0
   647
			case ERROR_NOT_SUPPORTED:
sl@0
   648
				return(KErrNotSupported);
sl@0
   649
			default:
sl@0
   650
				return(KErrGeneral);
sl@0
   651
			}
sl@0
   652
		}
sl@0
   653
	
sl@0
   654
sl@0
   655
	//create the buffers.
sl@0
   656
	//the buffers need to be as big as the client will ever use.  8mb reserved, but commit less
sl@0
   657
	iInBufPtr = (TUint8*)VirtualAlloc(NULL, KSerialBufferMaxSize,MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
sl@0
   658
	if (!iInBufPtr)
sl@0
   659
		return(Emulator::LastError());
sl@0
   660
sl@0
   661
	//commit the first bit of the buffer
sl@0
   662
	if (!VirtualAlloc(iInBufPtr, KSerialBufferInitialSize, MEM_COMMIT,PAGE_READWRITE))
sl@0
   663
		return(Emulator::LastError());
sl@0
   664
sl@0
   665
	iInBufLength = KSerialBufferInitialSize;
sl@0
   666
	iInDes.Set(iInBufPtr, 0, iInBufLength);
sl@0
   667
sl@0
   668
	//reserve address space for the output buffer
sl@0
   669
	iOutBufPtr = (TUint8*)VirtualAlloc(NULL, KSerialBufferMaxSize,MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
sl@0
   670
	if (!iOutBufPtr)
sl@0
   671
		return(Emulator::LastError());
sl@0
   672
sl@0
   673
	//commit a smaller region of it
sl@0
   674
	if (!VirtualAlloc(iOutBufPtr, KSerialBufferInitialSize, MEM_COMMIT,PAGE_READWRITE))
sl@0
   675
		return(Emulator::LastError());
sl@0
   676
sl@0
   677
	iOutBufLength = KSerialBufferInitialSize;
sl@0
   678
	iOutDes.Set(iOutBufPtr, 0, iOutBufLength);
sl@0
   679
	
sl@0
   680
	DCB dcb;
sl@0
   681
	//set the dcb size
sl@0
   682
	dcb.DCBlength = sizeof(dcb);
sl@0
   683
	if (!GetCommStateP(iCommPort,&dcb))
sl@0
   684
		return(Emulator::LastError());
sl@0
   685
sl@0
   686
	EscapeCommFunctionP(iCommPort,0);
sl@0
   687
sl@0
   688
//
sl@0
   689
	if (!SetCommMaskP(iCommPort,EV_BREAK|EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR|EV_RING))
sl@0
   690
		return(Emulator::LastError());
sl@0
   691
sl@0
   692
	if(!SetupComm(iCommPort,KDefaultWinNTReadBufSize,KDefaultWinNTWriteBufSize))
sl@0
   693
		return(Emulator::LastError());
sl@0
   694
sl@0
   695
	if ((iCommThreadSem=CreateSemaphoreA(NULL,0,0x7fffffff,NULL))==NULL)
sl@0
   696
		return(Emulator::LastError());
sl@0
   697
sl@0
   698
	if ((iDriverThreadSem=CreateSemaphoreA(NULL,0,0x7fffffff,NULL))==NULL)
sl@0
   699
		return(Emulator::LastError());
sl@0
   700
sl@0
   701
//
sl@0
   702
// The serial port seems to open with the error condition set
sl@0
   703
//
sl@0
   704
sl@0
   705
	DWORD err,res;
sl@0
   706
	COMSTAT s;
sl@0
   707
	if (ClearCommError(iCommPort,&err,&s)==FALSE)
sl@0
   708
		res=GetLastError();
sl@0
   709
sl@0
   710
	if ((iThread=CreateWin32Thread(EThreadEvent,(LPTHREAD_START_ROUTINE)commThread,(void *)this, FALSE))==NULL)
sl@0
   711
		return(Emulator::LastError());
sl@0
   712
sl@0
   713
	SetThreadPriority(iThread,THREAD_PRIORITY_HIGHEST);
sl@0
   714
	return(KErrNone);
sl@0
   715
	}
sl@0
   716
sl@0
   717
sl@0
   718
	
sl@0
   719
void DCommWins::ReleaseBuffers()
sl@0
   720
	{
sl@0
   721
	if (iInBufPtr)
sl@0
   722
		{
sl@0
   723
		//decommit the buffer
sl@0
   724
		VirtualFree(iInBufPtr,KSerialBufferMaxSize, MEM_DECOMMIT);
sl@0
   725
		//and release the region
sl@0
   726
		VirtualFree(iInBufPtr, NULL, MEM_RELEASE);
sl@0
   727
		iInBufPtr = NULL;
sl@0
   728
		}
sl@0
   729
	if (iOutBufPtr)
sl@0
   730
		{
sl@0
   731
		VirtualFree(iOutBufPtr,KSerialBufferMaxSize, MEM_DECOMMIT);
sl@0
   732
		VirtualFree(iOutBufPtr, NULL, MEM_RELEASE);
sl@0
   733
		iOutBufPtr = NULL;
sl@0
   734
		}
sl@0
   735
	}
sl@0
   736
	
sl@0
   737
sl@0
   738
DCommWins::~DCommWins()
sl@0
   739
	{
sl@0
   740
	if (iThread)
sl@0
   741
		{
sl@0
   742
		if (! iRunning)
sl@0
   743
			{
sl@0
   744
			__ASSERT_ALWAYS(
sl@0
   745
				ResumeThread(iThread) != 0xffffffff,
sl@0
   746
				Panic(EWindowsUnexpectedError)); 
sl@0
   747
			}
sl@0
   748
sl@0
   749
		iRunning=ETrue;
sl@0
   750
		RunCommThread(EDie);
sl@0
   751
		}
sl@0
   752
sl@0
   753
	if (iCommPort)
sl@0
   754
		CloseHandle(iCommPort);
sl@0
   755
sl@0
   756
	if (iDriverThreadSem)
sl@0
   757
		CloseHandle(iDriverThreadSem);
sl@0
   758
sl@0
   759
	if (iCommThreadSem)
sl@0
   760
		CloseHandle(iCommThreadSem);
sl@0
   761
sl@0
   762
	if (iReadOverLapped.hEvent)
sl@0
   763
		CloseHandle(iReadOverLapped.hEvent);
sl@0
   764
sl@0
   765
	if (iWriteOverLapped.hEvent)
sl@0
   766
		CloseHandle(iWriteOverLapped.hEvent);
sl@0
   767
sl@0
   768
	if (iSignalOverLapped.hEvent)
sl@0
   769
		CloseHandle(iSignalOverLapped.hEvent);
sl@0
   770
sl@0
   771
	if (iThread)
sl@0
   772
		CloseHandle(iThread);
sl@0
   773
sl@0
   774
	//free up the memory
sl@0
   775
	ReleaseBuffers();
sl@0
   776
	}
sl@0
   777
sl@0
   778
TInt DCommWins::Start()
sl@0
   779
	{
sl@0
   780
sl@0
   781
	__ASSERT_ALWAYS(ResumeThread(iThread)!=0xffffffff,Panic(EWindowsUnexpectedError));
sl@0
   782
	iRunning=ETrue;
sl@0
   783
	RunCommThread(EStart);
sl@0
   784
	return(KErrNone);
sl@0
   785
	}
sl@0
   786
sl@0
   787
void DCommWins::Stop(TStopMode aMode)
sl@0
   788
	{
sl@0
   789
sl@0
   790
	RunCommThread((aMode==EStopEmergency) ? EStopNoDrain : EStop);
sl@0
   791
	SuspendThread(iThread);
sl@0
   792
	iRunning=EFalse;
sl@0
   793
	}
sl@0
   794
sl@0
   795
void DCommWins::Break(TBool aState)
sl@0
   796
//
sl@0
   797
// Assert a break signal
sl@0
   798
//
sl@0
   799
	{
sl@0
   800
	if (aState)
sl@0
   801
		RunCommThread(ESetBreak);
sl@0
   802
	else
sl@0
   803
		RunCommThread(EClearBreak);
sl@0
   804
	}
sl@0
   805
sl@0
   806
sl@0
   807
sl@0
   808
TInt DCommWins::RxCount()
sl@0
   809
	{
sl@0
   810
	DWORD err =0;
sl@0
   811
	COMSTAT stat;
sl@0
   812
	if (ClearCommError(iCommPort,&err, &stat))
sl@0
   813
		return stat.cbInQue;
sl@0
   814
	else
sl@0
   815
		return Emulator::LastError();
sl@0
   816
	}
sl@0
   817
sl@0
   818
sl@0
   819
void DCommWins::ResetBuffers(TBool aTx)
sl@0
   820
	{
sl@0
   821
	PurgeComm(iCommPort, PURGE_RXCLEAR | (aTx ? PURGE_TXCLEAR : 0));
sl@0
   822
	}
sl@0
   823
sl@0
   824
sl@0
   825
TBool DCommWins::AreAnyPending()
sl@0
   826
	{
sl@0
   827
	return (iReadPending != 0) || (iWritePending != 0);
sl@0
   828
	}
sl@0
   829
sl@0
   830
sl@0
   831
void DCommWins::WriteCancel()
sl@0
   832
	{
sl@0
   833
	DriverCommand(ETransmitCancel);
sl@0
   834
	}
sl@0
   835
sl@0
   836
sl@0
   837
void DCommWins::ReadCancel()
sl@0
   838
	{
sl@0
   839
	DriverCommand(EReceiveCancel);
sl@0
   840
	}
sl@0
   841
sl@0
   842
void DCommWins::SignalChangeCancel()
sl@0
   843
	{
sl@0
   844
	if (iSignalsRequested)
sl@0
   845
		{
sl@0
   846
		iSignalsRequested = 0;
sl@0
   847
		}
sl@0
   848
sl@0
   849
	}
sl@0
   850
sl@0
   851
void DCommWins::DataAvailableNotificationCancel()
sl@0
   852
	{
sl@0
   853
	if (iDataAvailableNotification)
sl@0
   854
		{
sl@0
   855
		iDataAvailableNotification = EFalse;
sl@0
   856
		iLdd->iRxDAError = KErrCancel;
sl@0
   857
		iLdd->iRxDataAvailableDfc.Enque();
sl@0
   858
		}
sl@0
   859
	}
sl@0
   860
sl@0
   861
TDes8* DCommWins::RxBuffer()
sl@0
   862
	{
sl@0
   863
	return &iInDes;
sl@0
   864
	}
sl@0
   865
sl@0
   866
TInt DCommWins::SetRxBufferSize(TInt aSize)
sl@0
   867
	{
sl@0
   868
	aSize += aSize&1;	//round up to multiple of 2 bytes as windows complains if odd
sl@0
   869
	TInt ret = SetupComm(iCommPort, aSize, KDefaultWinNTWriteBufSize);
sl@0
   870
	if (ret)
sl@0
   871
		{
sl@0
   872
		iRxBufferSize = aSize;
sl@0
   873
		
sl@0
   874
		DCB dcb = {0};
sl@0
   875
		dcb.DCBlength = sizeof(dcb);
sl@0
   876
		
sl@0
   877
		if (!GetCommStateP(iCommPort,&dcb))
sl@0
   878
			return Emulator::LastError();
sl@0
   879
sl@0
   880
		//use rx buffer size to configure xon/xoff limits
sl@0
   881
		dcb.XoffLim = (WORD)(iRxBufferSize / 4);		//25%
sl@0
   882
		if (iConfig->iParityError & KConfigXonXoffDebug)
sl@0
   883
			dcb.XonLim = (WORD)((iRxBufferSize / 2) -5);	//50%-5
sl@0
   884
		else
sl@0
   885
			dcb.XonLim = (WORD)((iRxBufferSize / 4) * 3);	//75%
sl@0
   886
sl@0
   887
		if (!SetCommStateP(iCommPort,&dcb))
sl@0
   888
			return Emulator::LastError();
sl@0
   889
sl@0
   890
		return KErrNone;
sl@0
   891
		}
sl@0
   892
	return Emulator::LastError();
sl@0
   893
	}
sl@0
   894
sl@0
   895
sl@0
   896
TInt DCommWins::RxBufferSize()
sl@0
   897
	{
sl@0
   898
	return iRxBufferSize;
sl@0
   899
	}
sl@0
   900
sl@0
   901
sl@0
   902
TBool DCommWins::IsATerminator(TText8 aChar)
sl@0
   903
	{
sl@0
   904
	TInt x;
sl@0
   905
	for (x=0; x < iConfig->iTerminatorCount; x++)
sl@0
   906
		if (aChar == iConfig->iTerminator[x])
sl@0
   907
			return ETrue;
sl@0
   908
	return EFalse;
sl@0
   909
	}
sl@0
   910
sl@0
   911
sl@0
   912
void DCommWins::ReSizeBuffer(TUint8*& aBuf, TInt& aBufLen, TPtr8& aDes, const TInt aNewLen)
sl@0
   913
	{
sl@0
   914
sl@0
   915
	if (aNewLen > KSerialBufferMaxSize)
sl@0
   916
		Panic(ESerialBufferTooBig);
sl@0
   917
sl@0
   918
	aBufLen = ((aNewLen + KSerialBufferIncrementSize-1) / KSerialBufferIncrementSize) * KSerialBufferIncrementSize;
sl@0
   919
sl@0
   920
	if (aBufLen > KSerialBufferMaxSize)
sl@0
   921
		aBufLen = KSerialBufferMaxSize;
sl@0
   922
sl@0
   923
	if (!VirtualAlloc(aBuf, aBufLen, MEM_COMMIT,PAGE_READWRITE))
sl@0
   924
		{
sl@0
   925
		ReleaseBuffers();
sl@0
   926
		Panic(ESerialBufferTooBig);
sl@0
   927
		}
sl@0
   928
	aDes.Set(aBuf, 0, aBufLen);
sl@0
   929
	}
sl@0
   930
sl@0
   931
sl@0
   932
void DCommWins::Write(DThread* aThread, TAny* aSrc, TInt aLength)
sl@0
   933
sl@0
   934
	{
sl@0
   935
	if (aLength==0)
sl@0
   936
		{
sl@0
   937
		RunCommThread(ETransmit0);
sl@0
   938
		}
sl@0
   939
	else
sl@0
   940
		{
sl@0
   941
		if (aLength > iOutBufLength)
sl@0
   942
			ReSizeBuffer(iOutBufPtr, iOutBufLength, iOutDes, aLength);
sl@0
   943
sl@0
   944
		//copy the data from the client
sl@0
   945
		Kern::ThreadDesRead(aThread, aSrc, iOutDes, 0,0);
sl@0
   946
		iOutDes.SetLength(aLength);
sl@0
   947
		//tell the comms thread to write the data
sl@0
   948
		RunCommThread(ETransmit);
sl@0
   949
		}
sl@0
   950
	}
sl@0
   951
sl@0
   952
void DCommWins::NotifySignals(DThread* /*aThread*/, TInt aMask)
sl@0
   953
	{
sl@0
   954
	iSignalsWanted = aMask;
sl@0
   955
	RunCommThread(ENotifySignals);
sl@0
   956
	}
sl@0
   957
sl@0
   958
sl@0
   959
void DCommWins::NotifyDataAvailable()
sl@0
   960
	{
sl@0
   961
	RunCommThread(ENotifyDataAvailable);
sl@0
   962
	}
sl@0
   963
sl@0
   964
sl@0
   965
void DCommWins::Read(DThread* /*aThread*/, TAny* /*aDest*/, TInt aLength)
sl@0
   966
sl@0
   967
	{
sl@0
   968
	TDriverCommand command;
sl@0
   969
sl@0
   970
	if (aLength < 0)
sl@0
   971
		{
sl@0
   972
		iClientReadLength = Abs(aLength);
sl@0
   973
		command = EReceiveOneOrMore;
sl@0
   974
		}
sl@0
   975
	else
sl@0
   976
		{
sl@0
   977
		iClientReadLength = aLength;
sl@0
   978
		command = EReceive;
sl@0
   979
		}
sl@0
   980
sl@0
   981
	if (iClientReadLength > iInBufLength)
sl@0
   982
		ReSizeBuffer(iInBufPtr, iInBufLength, iInDes, iClientReadLength);
sl@0
   983
	
sl@0
   984
	//tell the comms thread to read the data
sl@0
   985
	RunCommThread(command);
sl@0
   986
	}
sl@0
   987
sl@0
   988
sl@0
   989
sl@0
   990
sl@0
   991
sl@0
   992
TUint DCommWins::Signals() const
sl@0
   993
	{
sl@0
   994
sl@0
   995
	ULONG signals=0;
sl@0
   996
	GetCommModemStatusP(iCommPort,&signals);
sl@0
   997
	TUint status=0;
sl@0
   998
	if (signals&MS_CTS_ON)
sl@0
   999
		status|=KSignalCTS;
sl@0
  1000
	if (signals&MS_DSR_ON)
sl@0
  1001
		status|=KSignalDSR;
sl@0
  1002
	if (signals&MS_RING_ON)
sl@0
  1003
		status|=KSignalRNG;
sl@0
  1004
	if (signals&MS_RLSD_ON)
sl@0
  1005
		status|=KSignalDCD;
sl@0
  1006
	return(status|iSignals);
sl@0
  1007
	}
sl@0
  1008
sl@0
  1009
sl@0
  1010
void DCommWins::SetSignals(TUint aSetMask,TUint aClearMask)
sl@0
  1011
	{
sl@0
  1012
	if (aSetMask&KSignalRTS)
sl@0
  1013
		{
sl@0
  1014
		iSignals|=KSignalRTS;
sl@0
  1015
		EscapeCommFunctionP(iCommPort,SETRTS);
sl@0
  1016
		}
sl@0
  1017
	if (aSetMask&KSignalDTR)
sl@0
  1018
		{
sl@0
  1019
		iSignals|=KSignalDTR;
sl@0
  1020
		EscapeCommFunctionP(iCommPort,SETDTR);
sl@0
  1021
		}
sl@0
  1022
	if (aClearMask&KSignalRTS)
sl@0
  1023
		{
sl@0
  1024
		iSignals&=(~KSignalRTS);
sl@0
  1025
		EscapeCommFunctionP(iCommPort,CLRRTS);
sl@0
  1026
		}
sl@0
  1027
	if (aClearMask&KSignalDTR)
sl@0
  1028
		{
sl@0
  1029
		iSignals&=(~KSignalDTR);
sl@0
  1030
		EscapeCommFunctionP(iCommPort,CLRDTR);
sl@0
  1031
		}
sl@0
  1032
	}
sl@0
  1033
sl@0
  1034
sl@0
  1035
sl@0
  1036
void DCommWins::CheckConfig(TCommConfigV01& /*aConfig*/)
sl@0
  1037
	{
sl@0
  1038
	// Do nothing
sl@0
  1039
	}
sl@0
  1040
sl@0
  1041
sl@0
  1042
sl@0
  1043
void DCommWins::Configure(TCommConfigV01 &aConfig)
sl@0
  1044
//
sl@0
  1045
// Ask comm thread to set up the serial port
sl@0
  1046
//
sl@0
  1047
	{
sl@0
  1048
sl@0
  1049
	iConfig=&aConfig;
sl@0
  1050
	if (iRunning)
sl@0
  1051
		{
sl@0
  1052
		RunCommThread(EConfigure);
sl@0
  1053
		}
sl@0
  1054
	else
sl@0
  1055
		{
sl@0
  1056
//		iCommand=EConfigure;
sl@0
  1057
		DoConfigure();
sl@0
  1058
		}
sl@0
  1059
	}
sl@0
  1060
sl@0
  1061
void DCommWins::DoConfigure()
sl@0
  1062
//
sl@0
  1063
// Set up the serial port
sl@0
  1064
//
sl@0
  1065
	{
sl@0
  1066
sl@0
  1067
	DCB dcb = {0};
sl@0
  1068
	//set the dcb size
sl@0
  1069
	dcb.DCBlength = sizeof(dcb);
sl@0
  1070
	if (!GetCommStateP(iCommPort,&dcb))
sl@0
  1071
		return;
sl@0
  1072
sl@0
  1073
			
sl@0
  1074
	//stop if an error happens
sl@0
  1075
	dcb.fAbortOnError = TRUE;
sl@0
  1076
	
sl@0
  1077
	//baud rate
sl@0
  1078
	switch (iConfig->iRate)
sl@0
  1079
		{
sl@0
  1080
	case EBps75:
sl@0
  1081
		dcb.BaudRate=75;
sl@0
  1082
		break;
sl@0
  1083
	case EBps110:
sl@0
  1084
		dcb.BaudRate=110;
sl@0
  1085
		break;
sl@0
  1086
	case EBps134:
sl@0
  1087
		dcb.BaudRate=134;
sl@0
  1088
		break;
sl@0
  1089
	case EBps150:
sl@0
  1090
		dcb.BaudRate=150;
sl@0
  1091
		break;
sl@0
  1092
	case EBps300:
sl@0
  1093
		dcb.BaudRate=300;
sl@0
  1094
		break;
sl@0
  1095
	case EBps600:
sl@0
  1096
		dcb.BaudRate=600;
sl@0
  1097
		break;
sl@0
  1098
	case EBps1200:
sl@0
  1099
		dcb.BaudRate=1200;
sl@0
  1100
		break;
sl@0
  1101
	case EBps1800:
sl@0
  1102
		dcb.BaudRate=1800;
sl@0
  1103
		break;
sl@0
  1104
	case EBps2400:
sl@0
  1105
		dcb.BaudRate=2400;
sl@0
  1106
		break;
sl@0
  1107
	case EBps4800:
sl@0
  1108
		dcb.BaudRate=4800;
sl@0
  1109
		break;
sl@0
  1110
	case EBps7200:
sl@0
  1111
		dcb.BaudRate=7200;
sl@0
  1112
		break;
sl@0
  1113
	case EBps9600:
sl@0
  1114
		dcb.BaudRate=9600;
sl@0
  1115
		break;
sl@0
  1116
	case EBps19200:
sl@0
  1117
		dcb.BaudRate=19200;
sl@0
  1118
		break;
sl@0
  1119
	case EBps38400:
sl@0
  1120
		dcb.BaudRate=38400;
sl@0
  1121
		break;
sl@0
  1122
	case EBps57600:
sl@0
  1123
		dcb.BaudRate=57600;
sl@0
  1124
		break;
sl@0
  1125
	case EBps115200:
sl@0
  1126
		dcb.BaudRate=115200;
sl@0
  1127
		break;
sl@0
  1128
		}
sl@0
  1129
   
sl@0
  1130
	switch (iConfig->iParity)
sl@0
  1131
		{
sl@0
  1132
	case EParityNone:
sl@0
  1133
		dcb.Parity=NOPARITY;
sl@0
  1134
		dcb.fParity = FALSE;
sl@0
  1135
		break;
sl@0
  1136
	case EParityEven:
sl@0
  1137
		dcb.Parity=EVENPARITY;
sl@0
  1138
		dcb.fParity = TRUE;
sl@0
  1139
		break;
sl@0
  1140
	case EParityOdd:
sl@0
  1141
		dcb.Parity=ODDPARITY;
sl@0
  1142
		dcb.fParity = TRUE;
sl@0
  1143
		break;
sl@0
  1144
	case EParityMark:
sl@0
  1145
		dcb.Parity = MARKPARITY;
sl@0
  1146
		dcb.fParity = TRUE;
sl@0
  1147
		break;
sl@0
  1148
	case EParitySpace:
sl@0
  1149
		dcb.Parity = SPACEPARITY;
sl@0
  1150
		dcb.fParity = TRUE;
sl@0
  1151
		break;
sl@0
  1152
		}
sl@0
  1153
sl@0
  1154
	switch (iConfig->iParityError)
sl@0
  1155
		{
sl@0
  1156
	case KConfigParityErrorFail:
sl@0
  1157
		dcb.fErrorChar = FALSE;
sl@0
  1158
		break;
sl@0
  1159
sl@0
  1160
	case KConfigParityErrorIgnore:
sl@0
  1161
		dcb.fErrorChar = FALSE;
sl@0
  1162
		dcb.fAbortOnError = FALSE;
sl@0
  1163
		break;
sl@0
  1164
sl@0
  1165
	case KConfigParityErrorReplaceChar:
sl@0
  1166
		dcb.fErrorChar = TRUE;
sl@0
  1167
		dcb.ErrorChar = iConfig->iParityErrorChar;
sl@0
  1168
		break;
sl@0
  1169
		}
sl@0
  1170
sl@0
  1171
sl@0
  1172
	TUint& hs = iConfig->iHandshake;
sl@0
  1173
sl@0
  1174
sl@0
  1175
	//SOFTWARE FLOW CONTROL
sl@0
  1176
	dcb.fInX  = (hs & KConfigObeyXoff) ? TRUE : FALSE;
sl@0
  1177
	dcb.fOutX = (hs & KConfigSendXoff) ? TRUE : FALSE;
sl@0
  1178
sl@0
  1179
	dcb.XonChar = iConfig->iXonChar;
sl@0
  1180
	dcb.XoffChar = iConfig->iXoffChar;
sl@0
  1181
	dcb.ErrorChar = iConfig->iParityErrorChar;
sl@0
  1182
sl@0
  1183
	//use rx buffer size to configure xon/xoff limits
sl@0
  1184
	dcb.XoffLim = (WORD)(iRxBufferSize / 4);		//25%
sl@0
  1185
	if (iConfig->iParityError & KConfigXonXoffDebug)
sl@0
  1186
		dcb.XonLim = (WORD)((iRxBufferSize / 2) -5);	//50%-5
sl@0
  1187
	else
sl@0
  1188
		dcb.XonLim = (WORD)((iRxBufferSize / 4) * 3);	//75%
sl@0
  1189
sl@0
  1190
sl@0
  1191
sl@0
  1192
	//OUTPUT HARDWARE FLOW CONTROL
sl@0
  1193
	//set out DSR control to be off
sl@0
  1194
	dcb.fOutxDsrFlow = FALSE;
sl@0
  1195
	dcb.fOutxCtsFlow = (hs & KConfigObeyCTS) ? TRUE : FALSE;
sl@0
  1196
	dcb.fDsrSensitivity =  (hs & KConfigObeyDSR) ? TRUE : FALSE;
sl@0
  1197
sl@0
  1198
sl@0
  1199
	if (hs & KConfigObeyDCD)
sl@0
  1200
		{
sl@0
  1201
		}
sl@0
  1202
sl@0
  1203
	
sl@0
  1204
	//INPUT HARDWARE FLOW CONTROL
sl@0
  1205
	dcb.fRtsControl = (hs & KConfigFreeRTS) ? RTS_CONTROL_DISABLE : RTS_CONTROL_HANDSHAKE;
sl@0
  1206
	dcb.fDtrControl = (hs & KConfigFreeDTR) ? DTR_CONTROL_DISABLE : DTR_CONTROL_ENABLE;
sl@0
  1207
sl@0
  1208
sl@0
  1209
	//complete with KErrCommsLineFail if these are set and the line goes low
sl@0
  1210
	iFailSignals = 0;
sl@0
  1211
	if (hs & KConfigFailDSR)
sl@0
  1212
		iFailSignals |= KSignalDSR;
sl@0
  1213
	
sl@0
  1214
	if (hs & KConfigFailCTS)
sl@0
  1215
		iFailSignals |= KSignalCTS;
sl@0
  1216
sl@0
  1217
	if (hs & KConfigFailDCD)
sl@0
  1218
		iFailSignals |= KSignalDCD;
sl@0
  1219
	
sl@0
  1220
	
sl@0
  1221
	iTerminatedRead = iConfig->iTerminatorCount > 0;
sl@0
  1222
sl@0
  1223
   	switch(iConfig->iDataBits)
sl@0
  1224
		{
sl@0
  1225
	case EData5:
sl@0
  1226
		dcb.ByteSize=5;	
sl@0
  1227
		break;
sl@0
  1228
	case EData6:
sl@0
  1229
		dcb.ByteSize=6;
sl@0
  1230
		break;
sl@0
  1231
	case EData7:
sl@0
  1232
		dcb.ByteSize=7;
sl@0
  1233
		break;
sl@0
  1234
	case EData8:
sl@0
  1235
		dcb.ByteSize=8;
sl@0
  1236
		break;
sl@0
  1237
		}
sl@0
  1238
sl@0
  1239
	switch(iConfig->iStopBits)
sl@0
  1240
		{
sl@0
  1241
	case EStop1:
sl@0
  1242
		dcb.StopBits=ONESTOPBIT;
sl@0
  1243
		break;
sl@0
  1244
	case EStop2:
sl@0
  1245
		dcb.StopBits=TWOSTOPBITS;
sl@0
  1246
		break;
sl@0
  1247
		}
sl@0
  1248
sl@0
  1249
sl@0
  1250
sl@0
  1251
	TInt error_r=KErrNone;
sl@0
  1252
	if(!SetCommStateP(iCommPort,&dcb))
sl@0
  1253
		error_r=GetLastError();
sl@0
  1254
sl@0
  1255
// Clear any error we may have caused
sl@0
  1256
//
sl@0
  1257
	DWORD err,res;
sl@0
  1258
	COMSTAT s;
sl@0
  1259
	if (ClearCommError(iCommPort,&err,&s)==FALSE)
sl@0
  1260
		res=GetLastError();
sl@0
  1261
sl@0
  1262
	}
sl@0
  1263
sl@0
  1264
void DCommWins::Caps(TDes8 &aCaps) const
sl@0
  1265
//
sl@0
  1266
// Return the current capabilities
sl@0
  1267
//
sl@0
  1268
	{
sl@0
  1269
sl@0
  1270
	GetWinsCommsCaps(aCaps);
sl@0
  1271
	}
sl@0
  1272
sl@0
  1273
sl@0
  1274
void DCommWins::WaitForEvent()
sl@0
  1275
	{
sl@0
  1276
sl@0
  1277
	HANDLE objects[4];
sl@0
  1278
sl@0
  1279
sl@0
  1280
	iReadOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL); 
sl@0
  1281
	iWriteOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL);
sl@0
  1282
	iSignalOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL);
sl@0
  1283
	objects[0]=iSignalOverLapped.hEvent; // iCommPort;
sl@0
  1284
	objects[1]=iCommThreadSem;
sl@0
  1285
	objects[2]=iWriteOverLapped.hEvent;
sl@0
  1286
	objects[3]=iReadOverLapped.hEvent;
sl@0
  1287
sl@0
  1288
	FOREVER
sl@0
  1289
		{
sl@0
  1290
		DWORD ret=WaitForMultipleObjectsEx(4,objects,FALSE,INFINITE,TRUE);
sl@0
  1291
		switch (ret)
sl@0
  1292
			{
sl@0
  1293
		case WAIT_OBJECT_0:
sl@0
  1294
			{
sl@0
  1295
			//			EnterCritical();
sl@0
  1296
sl@0
  1297
			if (iDataAvailableNotification)
sl@0
  1298
				{
sl@0
  1299
				DataAvailableCompletion(this);
sl@0
  1300
				iDataAvailableNotification = EFalse;	//stop us repeatedly reporting it
sl@0
  1301
				}
sl@0
  1302
sl@0
  1303
			// Detect breaks
sl@0
  1304
			if (iSignalStatus & EV_BREAK)
sl@0
  1305
				{
sl@0
  1306
				iBreakDetected=ETrue; // the read will complete with an error
sl@0
  1307
				}
sl@0
  1308
				
sl@0
  1309
			TUint currentSignals = Signals();
sl@0
  1310
sl@0
  1311
			//mask out all the signals but the ones we are interested in
sl@0
  1312
			iLineFail = (iFailSignals & currentSignals) != iFailSignals;
sl@0
  1313
			if (iLineFail)
sl@0
  1314
				{
sl@0
  1315
				//if we have the handshake options of
sl@0
  1316
				//KConfigFailDSR, KConfigFailDCD KFailConfigCTS set
sl@0
  1317
				//we need to do something if any of them are low so
sl@0
  1318
				//complete any outstanding ops with failure
sl@0
  1319
				if (iReadPending)
sl@0
  1320
					{
sl@0
  1321
					//we have a read to complete
sl@0
  1322
					iRXLineFail = ETrue;
sl@0
  1323
					PurgeComm(iCommPort, PURGE_RXABORT);
sl@0
  1324
					}
sl@0
  1325
sl@0
  1326
				if (iWritePending)
sl@0
  1327
					{
sl@0
  1328
					//we have a write to complete
sl@0
  1329
					iTXLineFail = ETrue;
sl@0
  1330
					PurgeComm(iCommPort, PURGE_TXABORT);
sl@0
  1331
					}
sl@0
  1332
				}
sl@0
  1333
sl@0
  1334
sl@0
  1335
			//iSignalsRequested will only have bits set if outstanding request
sl@0
  1336
			TUint changed = (currentSignals ^ iSavedSignals) & iSignalsRequested;
sl@0
  1337
			if (changed) 
sl@0
  1338
				{
sl@0
  1339
				SignalCompletion(this, KErrNone, changed, currentSignals);
sl@0
  1340
				iSavedSignals = currentSignals;
sl@0
  1341
				iSignalsRequested = 0;				//stop us repeatedly reporting it.
sl@0
  1342
												//iSignalsRequested is setup in the call to notify
sl@0
  1343
				}
sl@0
  1344
			
sl@0
  1345
			if (iWritePending == ETransmit0 && (currentSignals & KSignalCTS) != 0)
sl@0
  1346
				WriteCompletion(this, KErrNone, 0);
sl@0
  1347
sl@0
  1348
			//request another notification event.  All events are requested.
sl@0
  1349
			iSignalStatus=0;
sl@0
  1350
			DWORD commErrors;
sl@0
  1351
			BOOL res;
sl@0
  1352
			DWORD lastError = 0;
sl@0
  1353
			COMSTAT cstat;
sl@0
  1354
sl@0
  1355
			do
sl@0
  1356
				{
sl@0
  1357
				ClearCommError(iCommPort,&commErrors,&cstat);
sl@0
  1358
				res = WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped);
sl@0
  1359
				if (!res)
sl@0
  1360
					lastError = GetLastError();
sl@0
  1361
				}
sl@0
  1362
			while((!res) && (lastError != ERROR_IO_PENDING));
sl@0
  1363
sl@0
  1364
			break;
sl@0
  1365
			}
sl@0
  1366
sl@0
  1367
		case WAIT_OBJECT_0+1:
sl@0
  1368
//
sl@0
  1369
// iCommThreadSemaphore has been signalled
sl@0
  1370
//
sl@0
  1371
			DriverCommand(iCommand);
sl@0
  1372
			break;
sl@0
  1373
		case WAIT_OBJECT_0+2:
sl@0
  1374
			//
sl@0
  1375
			//	Write completion
sl@0
  1376
			//
sl@0
  1377
			{
sl@0
  1378
sl@0
  1379
			DWORD len = 0;
sl@0
  1380
			TInt error = KErrNone;
sl@0
  1381
			if (!GetOverlappedResult(iCommPort, &iWriteOverLapped, &len, FALSE))
sl@0
  1382
				error = Emulator::LastError();
sl@0
  1383
			
sl@0
  1384
			COMSTAT s;
sl@0
  1385
			DWORD err = 0;
sl@0
  1386
			ClearCommError(iCommPort,&err,&s);
sl@0
  1387
sl@0
  1388
			//if we are failing if one or more of CTS, DSR, DCD go low
sl@0
  1389
			if (iTXLineFail)
sl@0
  1390
				{
sl@0
  1391
				error = KErrCommsLineFail;
sl@0
  1392
				iTXLineFail = EFalse;
sl@0
  1393
				}
sl@0
  1394
			else if (err)
sl@0
  1395
				{
sl@0
  1396
				if (err & CE_FRAME)
sl@0
  1397
					error = KErrCommsFrame;
sl@0
  1398
				else if (err & CE_OVERRUN)
sl@0
  1399
					error = KErrCommsOverrun;
sl@0
  1400
				else if (err & CE_RXPARITY)
sl@0
  1401
					error = KErrCommsParity;
sl@0
  1402
				}
sl@0
  1403
sl@0
  1404
			WriteCompletion(this, error, len);
sl@0
  1405
			break;
sl@0
  1406
			}
sl@0
  1407
sl@0
  1408
		case WAIT_OBJECT_0+3:
sl@0
  1409
			//
sl@0
  1410
			//	Read completion
sl@0
  1411
			//
sl@0
  1412
			{
sl@0
  1413
			DWORD len = 0;
sl@0
  1414
			TInt error = KErrNone;
sl@0
  1415
			if (!GetOverlappedResult(iCommPort, &iReadOverLapped, &len, FALSE))
sl@0
  1416
				{
sl@0
  1417
				// May have a break already detected to report
sl@0
  1418
				if (iBreakDetected)
sl@0
  1419
					{
sl@0
  1420
					error=KErrCommsBreak;
sl@0
  1421
					iBreakDetected=EFalse;
sl@0
  1422
					}
sl@0
  1423
				else
sl@0
  1424
					error = Emulator::LastError();
sl@0
  1425
				}
sl@0
  1426
			else
sl@0
  1427
				iBreakDetected=EFalse; // No error, so any breaks have finished
sl@0
  1428
			
sl@0
  1429
			COMSTAT s;
sl@0
  1430
			DWORD err = 0;
sl@0
  1431
			ClearCommError(iCommPort,&err,&s);
sl@0
  1432
sl@0
  1433
			//if we are failing if one or more of CTS, DSR, DCD go low
sl@0
  1434
			if (iRXLineFail)
sl@0
  1435
				{
sl@0
  1436
				error = KErrCommsLineFail;
sl@0
  1437
				iRXLineFail = EFalse;
sl@0
  1438
				}
sl@0
  1439
			else if (err)
sl@0
  1440
				{
sl@0
  1441
				if (err & CE_FRAME)
sl@0
  1442
					error = KErrCommsFrame;
sl@0
  1443
				else if (err & CE_OVERRUN)
sl@0
  1444
					error = KErrCommsOverrun;
sl@0
  1445
				else if (err & CE_RXPARITY)
sl@0
  1446
					error = KErrCommsParity;
sl@0
  1447
				}
sl@0
  1448
sl@0
  1449
			ReadCompletion(this, error, len);
sl@0
  1450
			break;
sl@0
  1451
			}
sl@0
  1452
sl@0
  1453
		case WAIT_IO_COMPLETION:
sl@0
  1454
			break;
sl@0
  1455
sl@0
  1456
		default:
sl@0
  1457
			Emulator::LastError();
sl@0
  1458
			FAULT();
sl@0
  1459
			}
sl@0
  1460
		}
sl@0
  1461
	}
sl@0
  1462
sl@0
  1463
void DCommWins::DriverCommand(TDriverCommand aCommand)
sl@0
  1464
//
sl@0
  1465
// Do a driver command - executed when the semaphore has been signalled in the comm port thread
sl@0
  1466
//
sl@0
  1467
	{
sl@0
  1468
	switch (aCommand)
sl@0
  1469
		{
sl@0
  1470
	case ESetBreak:
sl@0
  1471
		FlushFileBuffers(iCommPort);
sl@0
  1472
		SetCommBreak(iCommPort);
sl@0
  1473
		break;
sl@0
  1474
sl@0
  1475
	case EClearBreak:
sl@0
  1476
		ClearCommBreak(iCommPort);
sl@0
  1477
		break;
sl@0
  1478
sl@0
  1479
	case ETransmit0:
sl@0
  1480
		
sl@0
  1481
		if (!iWritePending)
sl@0
  1482
			{
sl@0
  1483
			if ((iConfig->iHandshake & KConfigObeyCTS) != 0 && (Signals() & KSignalCTS) == 0)
sl@0
  1484
				iWritePending = ETransmit0;
sl@0
  1485
			else
sl@0
  1486
				DoWriteComplete(KErrNone);
sl@0
  1487
			}
sl@0
  1488
		break;
sl@0
  1489
sl@0
  1490
	case ETransmit:
sl@0
  1491
		
sl@0
  1492
		if (!iWritePending)
sl@0
  1493
			{
sl@0
  1494
			COMMTIMEOUTS ct;
sl@0
  1495
			int r = GetCommTimeouts(iCommPort, &ct);
sl@0
  1496
			ct.WriteTotalTimeoutConstant = 0;
sl@0
  1497
			ct.WriteTotalTimeoutMultiplier = 0;
sl@0
  1498
			r = SetCommTimeouts(iCommPort, &ct);
sl@0
  1499
sl@0
  1500
			WriteFileP(iCommPort,iOutDes.Ptr(), iOutDes.Length(), &dummyLen, &iWriteOverLapped);
sl@0
  1501
			iWritePending = ETransmit;
sl@0
  1502
			iTransmitting= ETrue;
sl@0
  1503
			}
sl@0
  1504
		break;
sl@0
  1505
sl@0
  1506
	case EStart:
sl@0
  1507
		{
sl@0
  1508
		iSignalStatus=0;
sl@0
  1509
		iSignalStatus=0;
sl@0
  1510
		DWORD commErrors;
sl@0
  1511
		BOOL res;
sl@0
  1512
		DWORD lastError = 0;
sl@0
  1513
		COMSTAT cstat;
sl@0
  1514
sl@0
  1515
		do
sl@0
  1516
			{
sl@0
  1517
			ClearCommError(iCommPort,&commErrors,&cstat);
sl@0
  1518
			res = WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped);
sl@0
  1519
			if (!res)
sl@0
  1520
				lastError = GetLastError();
sl@0
  1521
			}
sl@0
  1522
		while((!res) && (lastError != ERROR_IO_PENDING));
sl@0
  1523
		}
sl@0
  1524
		break;
sl@0
  1525
	
sl@0
  1526
	case EStop:
sl@0
  1527
        // Flush last write
sl@0
  1528
		if(iWritePending == ETransmit)
sl@0
  1529
			{
sl@0
  1530
			WaitForSingleObject(iWriteOverLapped.hEvent, INFINITE);
sl@0
  1531
			FlushFileBuffers(iCommPort);
sl@0
  1532
			}
sl@0
  1533
        iWritePending=0;
sl@0
  1534
        iTransmitting=EFalse;
sl@0
  1535
		// Fall through
sl@0
  1536
	case EStopNoDrain:
sl@0
  1537
		// Cancel any pending writes
sl@0
  1538
        if(iWritePending == ETransmit)
sl@0
  1539
		    {
sl@0
  1540
			PurgeComm(iCommPort, PURGE_TXABORT|PURGE_TXCLEAR);
sl@0
  1541
            WaitForSingleObject(iWriteOverLapped.hEvent, INFINITE);
sl@0
  1542
		    }   
sl@0
  1543
        iWritePending=0;
sl@0
  1544
		iTransmitting=EFalse;
sl@0
  1545
		iStopping=ETrue;
sl@0
  1546
        if(iRunning)
sl@0
  1547
            {
sl@0
  1548
            SetCommMaskP(iCommPort,EV_BREAK|EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR);
sl@0
  1549
            WaitForSingleObject(iSignalOverLapped.hEvent, INFINITE);
sl@0
  1550
            }
sl@0
  1551
		break;
sl@0
  1552
sl@0
  1553
	case EDie:	
sl@0
  1554
		SignalDriverThread();
sl@0
  1555
		ExitThread(1);
sl@0
  1556
		break;
sl@0
  1557
	
sl@0
  1558
	case EConfigure:
sl@0
  1559
		DoConfigure();
sl@0
  1560
		break;
sl@0
  1561
	
sl@0
  1562
	case ETransmitCancel:
sl@0
  1563
		if (iWritePending == ETransmit)
sl@0
  1564
			PurgeComm(iCommPort, PURGE_TXABORT);
sl@0
  1565
//		else if (iWritePending == ETransmit0)
sl@0
  1566
//			{
sl@0
  1567
			// careful - this runs in the context of the kernel thread, not the event thread
sl@0
  1568
		iLdd->iTxError = KErrCancel;
sl@0
  1569
		iLdd->iTxCompleteDfc.Enque();
sl@0
  1570
//			}
sl@0
  1571
		break;
sl@0
  1572
sl@0
  1573
	case EReceive:
sl@0
  1574
		if (!iReadPending)
sl@0
  1575
			{
sl@0
  1576
			COMMTIMEOUTS ct;
sl@0
  1577
			int r = GetCommTimeouts(iCommPort, &ct);
sl@0
  1578
			ct.ReadIntervalTimeout = 0;
sl@0
  1579
			ct.ReadTotalTimeoutMultiplier = 0;
sl@0
  1580
			ct.ReadTotalTimeoutConstant = 0;
sl@0
  1581
			r = SetCommTimeouts(iCommPort, &ct);
sl@0
  1582
sl@0
  1583
			//if we are doing a terminated read.... we need to do it a byte at a time!
sl@0
  1584
			if (iTerminatedRead)
sl@0
  1585
				{
sl@0
  1586
				iReadSoFar = 0;
sl@0
  1587
				ReadFileP(iCommPort,(void*)iInDes.Ptr(), 1, &dummyLen, &iReadOverLapped);
sl@0
  1588
				}
sl@0
  1589
			else
sl@0
  1590
				{
sl@0
  1591
				ReadFileP(iCommPort,(void*)iInDes.Ptr(), iClientReadLength, &dummyLen, &iReadOverLapped);
sl@0
  1592
				}
sl@0
  1593
sl@0
  1594
			iReadPending = EReceive;
sl@0
  1595
			}
sl@0
  1596
		break;
sl@0
  1597
sl@0
  1598
	case EReceiveOneOrMore:
sl@0
  1599
		if (!iReadPending)
sl@0
  1600
			{
sl@0
  1601
			COMMTIMEOUTS ct;
sl@0
  1602
			int r = GetCommTimeouts(iCommPort, &ct);
sl@0
  1603
			ct.ReadIntervalTimeout = MAXDWORD;
sl@0
  1604
			ct.ReadTotalTimeoutMultiplier = MAXDWORD;
sl@0
  1605
			ct.ReadTotalTimeoutConstant = KReadOneOrMoreTimeout;
sl@0
  1606
			r = SetCommTimeouts(iCommPort, &ct);
sl@0
  1607
sl@0
  1608
			//if we are doing a terminated read....
sl@0
  1609
			if (iTerminatedRead)
sl@0
  1610
				{
sl@0
  1611
				iReadSoFar = 0;
sl@0
  1612
				ReadFileP(iCommPort,(void*)iInDes.Ptr(), 1, &dummyLen, &iReadOverLapped);
sl@0
  1613
				}
sl@0
  1614
			else
sl@0
  1615
				{
sl@0
  1616
				ReadFileP(iCommPort,(void*)iInDes.Ptr(), iClientReadLength, &dummyLen, &iReadOverLapped);
sl@0
  1617
				}
sl@0
  1618
sl@0
  1619
			iReadPending = EReceiveOneOrMore;
sl@0
  1620
			}
sl@0
  1621
		break;
sl@0
  1622
sl@0
  1623
	case EReceiveCancel:
sl@0
  1624
		if (iReadPending)
sl@0
  1625
			PurgeComm(iCommPort, PURGE_RXABORT);
sl@0
  1626
		else if (iDataAvailableNotification)
sl@0
  1627
			DataAvailableNotificationCancel();
sl@0
  1628
		break;
sl@0
  1629
sl@0
  1630
	case ENotifyDataAvailable:
sl@0
  1631
		{
sl@0
  1632
		iDataAvailableNotification = ETrue;
sl@0
  1633
		//setup the comms notifications for data available
sl@0
  1634
		break;
sl@0
  1635
		}
sl@0
  1636
sl@0
  1637
	case ENotifySignals:
sl@0
  1638
		{
sl@0
  1639
		TUint currentSignals = Signals();
sl@0
  1640
		TUint changed = (currentSignals ^ iSavedSignals) & iSignalsWanted;
sl@0
  1641
		if (changed) 
sl@0
  1642
			{
sl@0
  1643
			SignalCompletion(this, KErrNone, changed, currentSignals);
sl@0
  1644
			iSavedSignals = currentSignals;
sl@0
  1645
			iSignalsWanted = 0;				
sl@0
  1646
			}
sl@0
  1647
		else
sl@0
  1648
			iSignalsRequested = iSignalsWanted;	//checked when signals change
sl@0
  1649
		}
sl@0
  1650
		break;
sl@0
  1651
sl@0
  1652
sl@0
  1653
	default:
sl@0
  1654
		// Panic(EUnknownCommand);
sl@0
  1655
		break;
sl@0
  1656
		}
sl@0
  1657
	iCommand=EInvalidCommand;
sl@0
  1658
	SignalDriverThread();
sl@0
  1659
	}
sl@0
  1660
sl@0
  1661
sl@0
  1662
TDfcQue* DCommWins::DfcQ(TInt /*aUnit*/)
sl@0
  1663
	{
sl@0
  1664
	return Kern::DfcQue0();
sl@0
  1665
	}
sl@0
  1666
sl@0
  1667
sl@0
  1668
TInt DCommWins::ValidateConfig(const TCommConfigV01 &aConfig) const
sl@0
  1669
//
sl@0
  1670
// Check a config structure.
sl@0
  1671
//
sl@0
  1672
	{
sl@0
  1673
	if(aConfig.iRate & EBpsSpecial)
sl@0
  1674
		return KErrNotSupported;
sl@0
  1675
sl@0
  1676
	switch (aConfig.iParity)
sl@0
  1677
		{
sl@0
  1678
		case EParityNone:
sl@0
  1679
		case EParityOdd:
sl@0
  1680
		case EParityEven:
sl@0
  1681
			break;
sl@0
  1682
		default:
sl@0
  1683
			return KErrNotSupported;
sl@0
  1684
		}
sl@0
  1685
	switch (aConfig.iRate)
sl@0
  1686
		{
sl@0
  1687
		case EBps50:
sl@0
  1688
		case EBps75:
sl@0
  1689
		case EBps134:
sl@0
  1690
		case EBps1800:
sl@0
  1691
		case EBps2000:
sl@0
  1692
		case EBps3600:
sl@0
  1693
		case EBps7200:
sl@0
  1694
			return KErrNotSupported;
sl@0
  1695
		default:
sl@0
  1696
			break;
sl@0
  1697
		};
sl@0
  1698
	return KErrNone;
sl@0
  1699
	}
sl@0
  1700
sl@0
  1701
inline TBool DCommWins::LineFail()
sl@0
  1702
	{
sl@0
  1703
	return iLineFail;
sl@0
  1704
	}
sl@0
  1705
sl@0
  1706
sl@0
  1707
sl@0
  1708
DECLARE_STANDARD_PDD()
sl@0
  1709
	{
sl@0
  1710
	return new DDriverComm;
sl@0
  1711
	}
sl@0
  1712