os/boardsupport/emulator/emulatorbsp/specific/serialpdd.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/serialpdd.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1712 @@
     1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// wins/specific/serialpdd.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "winscomm.h"
    1.22 +#include "nk_priv.h"
    1.23 +#include "nk_plat.h"
    1.24 +#include <emulator.h>
    1.25 +
    1.26 +#define WIN32_LEAN_AND_MEAN
    1.27 +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
    1.28 +#include <windows.h>
    1.29 +#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
    1.30 +
    1.31 +#ifdef FAULT
    1.32 +#undef FAULT
    1.33 +#endif
    1.34 +#define FAULT() Kern::Fault(__FILE__,__LINE__)
    1.35 +
    1.36 +_LIT(KComName, "\\\\.\\com");
    1.37 +
    1.38 +// needs ldd version..
    1.39 +const TInt KMinimumLddMajorVersion=1;
    1.40 +const TInt KMinimumLddMinorVersion=1;
    1.41 +const TInt KMinimumLddBuild=1;		
    1.42 +
    1.43 +//used for the read and write buffers in the driver.
    1.44 +//large buffer reserved so any transfer to/from the client can fit into a driver buffer
    1.45 +const TInt KSerialBufferMaxSize = 0x800000;
    1.46 +const TInt KSerialBufferInitialSize = 0x10000;
    1.47 +const TInt KSerialBufferIncrementSize = 0x1000;	//granularity.  must be power of 2	
    1.48 +
    1.49 +
    1.50 +const DWORD KReadOneOrMoreTimeout = MAXDWORD-1;	//milliseconds
    1.51 +
    1.52 +
    1.53 +//buffer sizes passed to NT for setting its own driver buffer sizes
    1.54 +const TInt KDefaultWinNTReadBufSize = 1024;
    1.55 +const TInt KDefaultWinNTWriteBufSize = 1024;
    1.56 +
    1.57 +static DWORD dummyLen=0;
    1.58 +
    1.59 +enum TDCommWinsFault 
    1.60 +	{
    1.61 +	EWindowsUnexpectedError,
    1.62 +	EUnknownCommand,
    1.63 +	EBadIOLen,
    1.64 +	EEofOnSerial,
    1.65 +	EWriteEarlyCompletion,
    1.66 +	ELineErrorNotReported,
    1.67 +	ESerialBufferTooBig,
    1.68 +	EReadLength,
    1.69 +	};
    1.70 +
    1.71 +
    1.72 +class DDriverComm : public DPhysicalDevice
    1.73 +	{
    1.74 +public:
    1.75 +	DDriverComm();
    1.76 +	virtual TInt Install();
    1.77 +	virtual TInt Remove();
    1.78 +	virtual void GetCaps(TDes8 &aDes) const;
    1.79 +	virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
    1.80 +	virtual TInt Validate(TInt aUnit, const TDesC8* aInfo, const TVersion &aVer);
    1.81 +	};
    1.82 +
    1.83 +
    1.84 +class DCommWins : public DComm
    1.85 +	{
    1.86 +public:
    1.87 +	enum TDriverCommand {ESetBreak=1,EClearBreak,ETransmit,ETransmit0,
    1.88 +						EGetSignals,ESetSignals,EConfigure,
    1.89 +						EStop,EStopNoDrain,EStart,EDie,	ETransmitCancel,
    1.90 +						EReceive, EReceiveOneOrMore, EReceiveCancel,ENotifyDataAvailable,
    1.91 +						ENotifySignals, EInvalidCommand};
    1.92 +public:
    1.93 +	DCommWins();
    1.94 +	~DCommWins();
    1.95 +	virtual TInt Start();
    1.96 +	virtual void Stop(TStopMode aMode);
    1.97 +	virtual void Break(TBool aState);
    1.98 +	virtual void Write(DThread* aThread, TAny *aTxDes, TInt aLength);
    1.99 +	virtual void Read(DThread* aThread, TAny *aTxDes, TInt aLength);
   1.100 +	virtual void NotifySignals(DThread* aThread, TInt aMask);
   1.101 +	virtual void NotifyDataAvailable();
   1.102 +	virtual TUint Signals() const;
   1.103 +	virtual void SetSignals(TUint aSetMask,TUint aClearMask);
   1.104 +	virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const;
   1.105 +	virtual void Configure(TCommConfigV01 &aConfig);
   1.106 +	virtual void Caps(TDes8 &aCaps) const;
   1.107 +	virtual void CheckConfig(TCommConfigV01& aConfig);
   1.108 +	virtual TDfcQue* DfcQ(TInt aUnit);
   1.109 +
   1.110 +	inline void CheckTxBuffer();
   1.111 +	inline TBool Transmitting();
   1.112 +	virtual TInt RxCount();
   1.113 +	virtual void ResetBuffers(TBool);
   1.114 +	virtual TInt SetRxBufferSize(TInt aSize);
   1.115 +	virtual TInt RxBufferSize();
   1.116 +	virtual TDes8* RxBuffer();
   1.117 +	virtual void DoConfigure();
   1.118 +	virtual TBool AreAnyPending();
   1.119 +	virtual void ReadCancel();
   1.120 +	virtual void WriteCancel();
   1.121 +	virtual void SignalChangeCancel();
   1.122 +	TInt DoCreate(TInt aUnit,const TDesC8 *aInfo);
   1.123 +	void WaitForEvent();
   1.124 +	void DriverCommand(TDriverCommand aCommand);
   1.125 +	void DoWriteComplete(TInt aErr);
   1.126 +	void DoReadComplete(TInt aErr, TInt aBytes);
   1.127 +	void DoSignalCompletion(TInt aError, TUint changed, TUint aValues);
   1.128 +	void DoDataAvailableCompletion();
   1.129 +	void RunCommThread(TDriverCommand aCommand);
   1.130 +	inline void SignalDriverThread();
   1.131 +	inline TBool LineFail();
   1.132 +	
   1.133 +private:
   1.134 +	void ReleaseBuffers();
   1.135 +	void ReSizeBuffer(TUint8*& aBuf, TInt& iBufLen, TPtr8& aDes, const TInt aNewLen);
   1.136 +	TBool IsATerminator(TText8 aChar);
   1.137 +	void CompleteRead(TInt aLength);
   1.138 +	void DataAvailableNotificationCancel();
   1.139 +
   1.140 +
   1.141 +private:
   1.142 +	TInt iWritePending;
   1.143 +	TInt iReadPending;
   1.144 +	TBool iStopping;
   1.145 +	TBool iRunning;
   1.146 +	TDriverCommand iCommand;
   1.147 +	TCommConfigV01 *iConfig;
   1.148 +	TUint iSignals;
   1.149 +	TUint iFailSignals;
   1.150 +	TUint iSavedSignals;
   1.151 +	TBool iLineFail;
   1.152 +	TBool iRXLineFail;
   1.153 +	TBool iTXLineFail;
   1.154 +
   1.155 +	TUint8 * iInBufPtr;		//input buffer used by driver.
   1.156 +	TInt iInBufLength;
   1.157 +	TPtr8 iInDes;
   1.158 +
   1.159 +	TInt iReadSoFar;
   1.160 +	TBool iTerminatedRead;	//true if we are reading with 1 or more terminating characters
   1.161 +
   1.162 +	TUint8 * iOutBufPtr;
   1.163 +	TInt iOutBufLength;
   1.164 +	TPtr8 iOutDes;
   1.165 +
   1.166 +	TInt iRxBufferSize;		//size of receivebuffer passed to windows & set by calls to SetReceiveBufferSize 
   1.167 +							//used to determine xon and xoff levels
   1.168 +	TUint iSignalsRequested;  //mask of signals we are waiting for
   1.169 +	TUint iSignalsWanted;		//mask we are asked to check 
   1.170 +	TBool iDataAvailableNotification;
   1.171 +	HANDLE iThread;
   1.172 +	HANDLE iCommThreadSem;
   1.173 +	HANDLE iDriverThreadSem;
   1.174 +	HANDLE iCommPort;
   1.175 +	DWORD iThreadID;
   1.176 +	DWORD iSignalStatus;
   1.177 +	OVERLAPPED iReadOverLapped;
   1.178 +	OVERLAPPED iWriteOverLapped;
   1.179 +	OVERLAPPED iSignalOverLapped;
   1.180 +
   1.181 +	TInt iClientReadLength;		//how much data the client has requested in a read
   1.182 +	TBool		iBreakDetected;
   1.183 +	};
   1.184 +
   1.185 +void Panic(TDCommWinsFault aFault)
   1.186 +//
   1.187 +// Panic the driver 
   1.188 +//
   1.189 +	{
   1.190 +	Kern::PanicCurrentThread(_L("DCommWins"), aFault);
   1.191 +	}
   1.192 +
   1.193 +
   1.194 +TUint commThread(DCommWins *comm)
   1.195 +//
   1.196 +// Comm thread entry point
   1.197 +//
   1.198 +	{
   1.199 +
   1.200 +	comm->WaitForEvent();
   1.201 +	return 0;
   1.202 +	}
   1.203 +
   1.204 +VOID WINAPI WriteCompletion(DCommWins *aDrv, DWORD aErr,DWORD /*numBytes*/)
   1.205 +	{
   1.206 +
   1.207 +	aDrv->DoWriteComplete(aErr);
   1.208 +	}
   1.209 +
   1.210 +
   1.211 +VOID WINAPI ReadCompletion(DCommWins *aDrv, DWORD aErr,DWORD numBytes)
   1.212 +	{
   1.213 +
   1.214 +	aDrv->DoReadComplete(aErr, numBytes);
   1.215 +	}
   1.216 +
   1.217 +VOID WINAPI SignalCompletion(DCommWins *aDrv, TInt aError, TUint aChanged, TUint aValues)
   1.218 +	{
   1.219 +	aDrv->DoSignalCompletion(aError, aChanged, aValues);
   1.220 +	}
   1.221 +
   1.222 +VOID WINAPI DataAvailableCompletion(DCommWins *aDrv)
   1.223 +	{
   1.224 +	aDrv->DoDataAvailableCompletion();
   1.225 +	}
   1.226 +
   1.227 +
   1.228 +
   1.229 +BOOL WINAPI EscapeCommFunctionP(HANDLE hFile,DWORD dwFunc)
   1.230 +	{
   1.231 +	DWORD err;
   1.232 +	DWORD lastError = 0;
   1.233 +	BOOL res;
   1.234 +	COMSTAT s;
   1.235 +	
   1.236 +	do
   1.237 +		{
   1.238 +		ClearCommError(hFile, &err, &s);
   1.239 +		res = EscapeCommFunction(hFile,dwFunc);
   1.240 +		if(!res)
   1.241 +			lastError = GetLastError();
   1.242 +		}
   1.243 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.244 +
   1.245 +	return(res);
   1.246 +	}
   1.247 +
   1.248 +
   1.249 +BOOL WINAPI GetCommModemStatusP(HANDLE hFile,LPDWORD lpModemStat)
   1.250 +	{
   1.251 +	DWORD err;
   1.252 +	DWORD lastError = 0;
   1.253 +	BOOL res;
   1.254 +	COMSTAT s;
   1.255 +	
   1.256 +	do
   1.257 +		{
   1.258 +		ClearCommError(hFile, &err, &s);
   1.259 +		res = GetCommModemStatus(hFile,lpModemStat);
   1.260 +		if(!res)
   1.261 +			lastError  = GetLastError();
   1.262 +		}
   1.263 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.264 +
   1.265 +	return(res);
   1.266 +	}
   1.267 +
   1.268 +
   1.269 +BOOL WINAPI GetCommStateP(HANDLE hFile,LPDCB lpDCB)
   1.270 +	{
   1.271 +	DWORD err;
   1.272 +	DWORD lastError = 0;
   1.273 +	BOOL res;
   1.274 +	COMSTAT s;
   1.275 +	
   1.276 +	do
   1.277 +		{
   1.278 +		ClearCommError(hFile,&err,&s);
   1.279 +		res = GetCommState(hFile,lpDCB);
   1.280 +		if (!res)
   1.281 +			lastError = GetLastError();
   1.282 +		}
   1.283 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.284 +
   1.285 +	return(res);
   1.286 +	}
   1.287 +
   1.288 +BOOL WINAPI SetCommStateP(HANDLE hFile,LPDCB lpDCB)
   1.289 +	{
   1.290 +	DWORD err;
   1.291 +	DWORD lastError = 0;
   1.292 +	BOOL res;
   1.293 +	COMSTAT s;
   1.294 +	
   1.295 +	do
   1.296 +		{
   1.297 +		ClearCommError(hFile, &err, &s);
   1.298 +		res = SetCommState(hFile, lpDCB);
   1.299 +		if (!res)
   1.300 +			lastError = GetLastError();
   1.301 +		}
   1.302 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.303 +
   1.304 +	return(res);
   1.305 +	}
   1.306 +
   1.307 +BOOL WINAPI SetCommMaskP(HANDLE hFile,DWORD dwEvtMask)
   1.308 +	{
   1.309 +	DWORD err;
   1.310 +	DWORD lastError = 0;
   1.311 +	BOOL res;
   1.312 +	COMSTAT s;
   1.313 +	
   1.314 +	do
   1.315 +		{
   1.316 +		ClearCommError(hFile, &err, &s);
   1.317 +		res = SetCommMask(hFile, dwEvtMask);
   1.318 +		if (!res)
   1.319 +			lastError = GetLastError();
   1.320 +		}
   1.321 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.322 +
   1.323 +	return(res);
   1.324 +	}
   1.325 +
   1.326 +BOOL WINAPI WriteFileP(HANDLE hFile,LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped)
   1.327 +	{
   1.328 +	DWORD err;
   1.329 +	DWORD lastError = 0;
   1.330 +	BOOL res;
   1.331 +	COMSTAT s;
   1.332 +	
   1.333 +	do
   1.334 +		{
   1.335 +		ClearCommError(hFile, &err, &s);
   1.336 +		res = WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
   1.337 +		if (!res)
   1.338 +			lastError = GetLastError();
   1.339 +		}
   1.340 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.341 +
   1.342 +	return(res);
   1.343 +	}
   1.344 +
   1.345 +BOOL WINAPI ReadFileP(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped)
   1.346 +	{
   1.347 +	DWORD err;
   1.348 +	DWORD lastError = 0;
   1.349 +	BOOL res;
   1.350 +	COMSTAT s;
   1.351 +	
   1.352 +	do
   1.353 +		{
   1.354 +		ClearCommError(hFile, &err, &s);
   1.355 +		res = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
   1.356 +		if (!res)
   1.357 +			lastError = GetLastError();
   1.358 +		}
   1.359 +	while((!res) && (lastError == ERROR_OPERATION_ABORTED));
   1.360 +
   1.361 +	return(res);
   1.362 +	}
   1.363 +
   1.364 +
   1.365 +
   1.366 +
   1.367 +DDriverComm::DDriverComm()
   1.368 +	{
   1.369 +#if defined (__COM_ONE_ONLY__)
   1.370 +	iUnitsMask=0x1; // Support units 0
   1.371 +#elif defined (__COM_TWO_ONLY__)
   1.372 +	iUnitsMask=0x2; // Support units 1
   1.373 +#else
   1.374 +	iUnitsMask=0x3ff; // Support units 0 to 9
   1.375 +#endif
   1.376 +
   1.377 +	iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
   1.378 +	}
   1.379 +
   1.380 +TInt DDriverComm::Install()
   1.381 +	{
   1.382 +#if defined (__COM_ONE_ONLY__)
   1.383 +	TPtrC buf=_L("Comm.Wins1");
   1.384 +	return(SetName(&buf));
   1.385 +#elif defined (__COM_TWO_ONLY__)
   1.386 +	TPtrC buf=_L("Comm.Wins2");
   1.387 +	return(SetName(&buf));
   1.388 +#else
   1.389 +	TPtrC buf=_L("Comm.Wins");
   1.390 +	return(SetName(&buf));
   1.391 +#endif
   1.392 +	}
   1.393 +
   1.394 +TInt DDriverComm::Remove()
   1.395 +	{
   1.396 +	return(KErrNone);
   1.397 +	}
   1.398 +
   1.399 +
   1.400 +TInt DDriverComm::Validate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
   1.401 +//
   1.402 +//	Validate the requested configuration
   1.403 +//
   1.404 +	{
   1.405 +	if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,KMinimumLddMinorVersion,KMinimumLddBuild))))
   1.406 +		return KErrNotSupported;
   1.407 +#if defined (__COM_ONE_ONLY__)
   1.408 +	if (aUnit!=0)
   1.409 +		return KErrNotSupported;
   1.410 +#elif defined (__COM_TWO_ONLY__)
   1.411 +	if (aUnit!=1)
   1.412 +		return KErrNotSupported;
   1.413 +#endif
   1.414 +	// leave Unit check to CreateFile
   1.415 +	return KErrNone;
   1.416 +	}
   1.417 +
   1.418 +
   1.419 +void GetWinsCommsCaps(TDes8 &aCaps)
   1.420 +	{
   1.421 +	TCommCaps3 capsBuf;
   1.422 +	TCommCapsV03 &c=capsBuf();
   1.423 +//
   1.424 +// All rates except 50,2000, 3600 and special
   1.425 +//
   1.426 +	c.iRate=KCapsBps75|KCapsBps110|KCapsBps134|KCapsBps150|KCapsBps300|KCapsBps600|KCapsBps1200|KCapsBps1800|KCapsBps2400|KCapsBps4800|KCapsBps7200|KCapsBps9600|KCapsBps19200|KCapsBps38400|KCapsBps57600|KCapsBps115200;
   1.427 +
   1.428 +	c.iDataBits=0xf; // All data sizes
   1.429 +	c.iStopBits=0x3; // 1 and 2 stop bits
   1.430 +	c.iParity=0x7; // None, Even and Odd
   1.431 +	c.iHandshake = 0x3BF;	//all except KConfigObeyDCD
   1.432 +	c.iSignals=0x3f; // All signals
   1.433 +	c.iSIR=0;//No Ir
   1.434 +	c.iNotificationCaps=KNotifySignalsChangeSupported|KNotifyDataAvailableSupported;
   1.435 +	c.iRoleCaps=0;
   1.436 +	c.iFlowControlCaps=0;
   1.437 +	c.iBreakSupported=ETrue;
   1.438 +	aCaps.FillZ(aCaps.MaxLength());
   1.439 +	aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
   1.440 +	}
   1.441 +
   1.442 +void DDriverComm::GetCaps(TDes8 &aDes) const
   1.443 +	{
   1.444 +	GetWinsCommsCaps(aDes);
   1.445 +	}
   1.446 +
   1.447 +TInt DDriverComm::Create(DBase*& aChannel, TInt aUnit,const TDesC8* aInfo,const TVersion& aVer)
   1.448 +	{
   1.449 +
   1.450 +	if (!Kern::QueryVersionSupported(iVersion,aVer))
   1.451 +		return KErrNotSupported;
   1.452 +
   1.453 +	DCommWins *pD= new DCommWins;
   1.454 +	if (!pD) return KErrNoMemory;
   1.455 +
   1.456 +	TInt ret=pD->DoCreate(aUnit,aInfo);
   1.457 +
   1.458 +	if (ret!=KErrNone)
   1.459 +	{
   1.460 +		delete pD;
   1.461 +		return ret;
   1.462 +	}
   1.463 +	
   1.464 +	aChannel = pD;
   1.465 +
   1.466 +	return KErrNone;
   1.467 +	}
   1.468 +
   1.469 +void DCommWins::DoWriteComplete(TInt aErr)
   1.470 +	{
   1.471 +	iWritePending = 0;
   1.472 +	iTransmitting = EFalse;
   1.473 +	StartOfInterrupt();
   1.474 +	iLdd->iTxError = aErr;
   1.475 +	iLdd->iTxCompleteDfc.Add();
   1.476 +	EndOfInterrupt();
   1.477 +	}
   1.478 +
   1.479 +
   1.480 +
   1.481 +void DCommWins::DoSignalCompletion(TInt aError, TUint aChanged, TUint aValues)
   1.482 +	{
   1.483 +	//aValues contains the signal values.  EPOC constants
   1.484 +	//aChanged contains the signals which have changed
   1.485 +	//we return the signal values
   1.486 +	TUint res = aValues & iSignalsWanted;
   1.487 +	res |= (aChanged << 12);
   1.488 +	
   1.489 +	iLdd->iSignalResult = res;
   1.490 +	iLdd->iSignalError = aError;
   1.491 +	StartOfInterrupt();
   1.492 +	iLdd->iSigNotifyDfc.Add();
   1.493 +	EndOfInterrupt();
   1.494 +	}
   1.495 +
   1.496 +void DCommWins::DoDataAvailableCompletion()
   1.497 +	{
   1.498 +	StartOfInterrupt();
   1.499 +	iLdd->iRxDataAvailableDfc.Add();
   1.500 +	EndOfInterrupt();
   1.501 +	}
   1.502 +
   1.503 +
   1.504 +
   1.505 +void DCommWins::CompleteRead(TInt aLength)
   1.506 +	{
   1.507 +	iReadPending = 0;
   1.508 +	iInDes.SetLength(aLength);
   1.509 +	StartOfInterrupt();
   1.510 +	iLdd->iRxCompleteDfc.Add();
   1.511 +	EndOfInterrupt();
   1.512 +	}
   1.513 +
   1.514 +
   1.515 +
   1.516 +void DCommWins::DoReadComplete(TInt aErr, TInt aBytes)
   1.517 +	{
   1.518 +	iLdd->iRxError = aErr;
   1.519 +	//write back the length and the data
   1.520 +	//process for any terminating characters.
   1.521 +	//win32 only does binary reads and ignores the eofchar, so terminated reads
   1.522 +	//require reading one char at a time
   1.523 +	if (iTerminatedRead && !aErr)
   1.524 +		{
   1.525 +		__NK_ASSERT_ALWAYS(aBytes <= 1);
   1.526 +		if (aBytes == 0)
   1.527 +			{
   1.528 +			// not sure why we get this somtimes, but handle it anyway : read another character
   1.529 +			ReadFileP(iCommPort,(void*)(iInBufPtr+iReadSoFar), 1, &dummyLen, &iReadOverLapped);
   1.530 +			}
   1.531 +		else if (++iReadSoFar == iClientReadLength)	//see if we have read enough characters into the buffer
   1.532 +			{
   1.533 +			//got them all so complete it
   1.534 +			CompleteRead(iReadSoFar);
   1.535 +			}
   1.536 +		else if (IsATerminator(iInBufPtr[iReadSoFar-1]))	//see if the char just read was the terminator
   1.537 +			{
   1.538 +			//it's a terminated read and we've found one of the terminbators
   1.539 +			CompleteRead(iReadSoFar);
   1.540 +			}
   1.541 +		else if (iReadPending == EReceive)
   1.542 +			{
   1.543 +			//read another character
   1.544 +			ReadFileP(iCommPort,(void*)(iInBufPtr+iReadSoFar), 1, &dummyLen, &iReadOverLapped);
   1.545 +			}
   1.546 +		else
   1.547 +			{
   1.548 +			//it's a receive 1 or more with terminators, we've got 1 so that'll do
   1.549 +			CompleteRead(iReadSoFar);
   1.550 +			}
   1.551 +		}
   1.552 +	else
   1.553 +		{
   1.554 +		CompleteRead(aBytes);
   1.555 +		}
   1.556 +	}
   1.557 +
   1.558 +
   1.559 +
   1.560 +
   1.561 +void DCommWins::RunCommThread(TDriverCommand aCommand)
   1.562 +//
   1.563 +// Wake up the comms thread
   1.564 +//
   1.565 +	{
   1.566 +
   1.567 +	__ASSERT_DEBUG(aCommand!=EInvalidCommand,Panic(EUnknownCommand));
   1.568 +	iCommand=aCommand;
   1.569 +//
   1.570 +// Are we about to go re-entrant?
   1.571 +//
   1.572 +	if(GetCurrentThreadId()==iThreadID)
   1.573 +		{
   1.574 +		DriverCommand(aCommand);
   1.575 +		WaitForSingleObject(iDriverThreadSem,INFINITE);
   1.576 +		}
   1.577 +	else
   1.578 +		{
   1.579 +		Sleep(0); // Possible deadlock solution - see MSDN Knowledge Base Article Q173260
   1.580 +		if (ReleaseSemaphore(iCommThreadSem,1,NULL)==FALSE)
   1.581 +			{
   1.582 +			DWORD ret=GetLastError();
   1.583 +			ret=ret;
   1.584 +			Panic(EWindowsUnexpectedError);
   1.585 +			}
   1.586 +		WaitForSingleObject(iDriverThreadSem,INFINITE);
   1.587 +		}
   1.588 +	}
   1.589 +
   1.590 +inline void DCommWins::SignalDriverThread()
   1.591 +//
   1.592 +// Wake up the comms thread
   1.593 +//
   1.594 +	{
   1.595 +	Sleep(0); // Possible deadlock solution - see MSDN Knowledge Base Article Q173260
   1.596 +	if (ReleaseSemaphore(iDriverThreadSem,1,NULL)==FALSE)
   1.597 +		{
   1.598 +		DWORD ret=GetLastError();
   1.599 +		ret=ret;
   1.600 +		Panic(EWindowsUnexpectedError);
   1.601 +		}
   1.602 +	}
   1.603 +
   1.604 +
   1.605 +
   1.606 +//
   1.607 +#pragma warning( disable : 4705 )	// statement has no effect
   1.608 +DCommWins::DCommWins() :  iOutDes(0,0), iInDes(0,0), iRxBufferSize(KDefaultWinNTReadBufSize), iSignalsRequested(0)
   1.609 +	{
   1.610 +	__DECLARE_NAME(_S("DCommWins"));
   1.611 +	}
   1.612 +#pragma warning( default : 4705 )
   1.613 +
   1.614 +TInt DCommWins::DoCreate(TInt aUnit,const TDesC8 * /*aInfo*/)
   1.615 +//
   1.616 +// Create the comms driver.
   1.617 +//
   1.618 +	{
   1.619 +
   1.620 +#if defined (__COM_ONE_ONLY__)
   1.621 +	if (aUnit!=0)
   1.622 +		return KErrNotSupported;
   1.623 +#elif defined (__COM_TWO_ONLY__)
   1.624 +	if (aUnit!=1)
   1.625 +		return KErrNotSupported;
   1.626 +#endif
   1.627 +
   1.628 +	TBuf8<0x10> n;
   1.629 +	n.Append(KComName);
   1.630 +	n.AppendNum(aUnit+1);
   1.631 +	n.Append('\0');
   1.632 +
   1.633 +	iCommPort=CreateFileA((LPCSTR)n.Ptr(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
   1.634 +	if (iCommPort==INVALID_HANDLE_VALUE)	
   1.635 +		{	
   1.636 +	//	Reused code from Emulator::LastError() rather than adding an extra case 
   1.637 +	//	to Emulator::LastError() because mapping KErrNotSupported to the returned
   1.638 +	//	FILE_NOT_FOUND is non-intuitive and special to this case only
   1.639 +		DWORD winErr=GetLastError();
   1.640 +		switch (winErr)
   1.641 +			{
   1.642 +			case ERROR_INVALID_USER_BUFFER:
   1.643 +			case ERROR_NOT_ENOUGH_MEMORY:
   1.644 +			case ERROR_INSUFFICIENT_BUFFER:
   1.645 +				return(KErrNoMemory);
   1.646 +			case ERROR_ACCESS_DENIED:
   1.647 +				return(KErrAccessDenied);
   1.648 +			case ERROR_FILE_NOT_FOUND:		//	Reflects value returned by
   1.649 +				return(KErrNotSupported);	//	corresponding MARM Pdd  
   1.650 +			case ERROR_NOT_SUPPORTED:
   1.651 +				return(KErrNotSupported);
   1.652 +			default:
   1.653 +				return(KErrGeneral);
   1.654 +			}
   1.655 +		}
   1.656 +	
   1.657 +
   1.658 +	//create the buffers.
   1.659 +	//the buffers need to be as big as the client will ever use.  8mb reserved, but commit less
   1.660 +	iInBufPtr = (TUint8*)VirtualAlloc(NULL, KSerialBufferMaxSize,MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
   1.661 +	if (!iInBufPtr)
   1.662 +		return(Emulator::LastError());
   1.663 +
   1.664 +	//commit the first bit of the buffer
   1.665 +	if (!VirtualAlloc(iInBufPtr, KSerialBufferInitialSize, MEM_COMMIT,PAGE_READWRITE))
   1.666 +		return(Emulator::LastError());
   1.667 +
   1.668 +	iInBufLength = KSerialBufferInitialSize;
   1.669 +	iInDes.Set(iInBufPtr, 0, iInBufLength);
   1.670 +
   1.671 +	//reserve address space for the output buffer
   1.672 +	iOutBufPtr = (TUint8*)VirtualAlloc(NULL, KSerialBufferMaxSize,MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
   1.673 +	if (!iOutBufPtr)
   1.674 +		return(Emulator::LastError());
   1.675 +
   1.676 +	//commit a smaller region of it
   1.677 +	if (!VirtualAlloc(iOutBufPtr, KSerialBufferInitialSize, MEM_COMMIT,PAGE_READWRITE))
   1.678 +		return(Emulator::LastError());
   1.679 +
   1.680 +	iOutBufLength = KSerialBufferInitialSize;
   1.681 +	iOutDes.Set(iOutBufPtr, 0, iOutBufLength);
   1.682 +	
   1.683 +	DCB dcb;
   1.684 +	//set the dcb size
   1.685 +	dcb.DCBlength = sizeof(dcb);
   1.686 +	if (!GetCommStateP(iCommPort,&dcb))
   1.687 +		return(Emulator::LastError());
   1.688 +
   1.689 +	EscapeCommFunctionP(iCommPort,0);
   1.690 +
   1.691 +//
   1.692 +	if (!SetCommMaskP(iCommPort,EV_BREAK|EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR|EV_RING))
   1.693 +		return(Emulator::LastError());
   1.694 +
   1.695 +	if(!SetupComm(iCommPort,KDefaultWinNTReadBufSize,KDefaultWinNTWriteBufSize))
   1.696 +		return(Emulator::LastError());
   1.697 +
   1.698 +	if ((iCommThreadSem=CreateSemaphoreA(NULL,0,0x7fffffff,NULL))==NULL)
   1.699 +		return(Emulator::LastError());
   1.700 +
   1.701 +	if ((iDriverThreadSem=CreateSemaphoreA(NULL,0,0x7fffffff,NULL))==NULL)
   1.702 +		return(Emulator::LastError());
   1.703 +
   1.704 +//
   1.705 +// The serial port seems to open with the error condition set
   1.706 +//
   1.707 +
   1.708 +	DWORD err,res;
   1.709 +	COMSTAT s;
   1.710 +	if (ClearCommError(iCommPort,&err,&s)==FALSE)
   1.711 +		res=GetLastError();
   1.712 +
   1.713 +	if ((iThread=CreateWin32Thread(EThreadEvent,(LPTHREAD_START_ROUTINE)commThread,(void *)this, FALSE))==NULL)
   1.714 +		return(Emulator::LastError());
   1.715 +
   1.716 +	SetThreadPriority(iThread,THREAD_PRIORITY_HIGHEST);
   1.717 +	return(KErrNone);
   1.718 +	}
   1.719 +
   1.720 +
   1.721 +	
   1.722 +void DCommWins::ReleaseBuffers()
   1.723 +	{
   1.724 +	if (iInBufPtr)
   1.725 +		{
   1.726 +		//decommit the buffer
   1.727 +		VirtualFree(iInBufPtr,KSerialBufferMaxSize, MEM_DECOMMIT);
   1.728 +		//and release the region
   1.729 +		VirtualFree(iInBufPtr, NULL, MEM_RELEASE);
   1.730 +		iInBufPtr = NULL;
   1.731 +		}
   1.732 +	if (iOutBufPtr)
   1.733 +		{
   1.734 +		VirtualFree(iOutBufPtr,KSerialBufferMaxSize, MEM_DECOMMIT);
   1.735 +		VirtualFree(iOutBufPtr, NULL, MEM_RELEASE);
   1.736 +		iOutBufPtr = NULL;
   1.737 +		}
   1.738 +	}
   1.739 +	
   1.740 +
   1.741 +DCommWins::~DCommWins()
   1.742 +	{
   1.743 +	if (iThread)
   1.744 +		{
   1.745 +		if (! iRunning)
   1.746 +			{
   1.747 +			__ASSERT_ALWAYS(
   1.748 +				ResumeThread(iThread) != 0xffffffff,
   1.749 +				Panic(EWindowsUnexpectedError)); 
   1.750 +			}
   1.751 +
   1.752 +		iRunning=ETrue;
   1.753 +		RunCommThread(EDie);
   1.754 +		}
   1.755 +
   1.756 +	if (iCommPort)
   1.757 +		CloseHandle(iCommPort);
   1.758 +
   1.759 +	if (iDriverThreadSem)
   1.760 +		CloseHandle(iDriverThreadSem);
   1.761 +
   1.762 +	if (iCommThreadSem)
   1.763 +		CloseHandle(iCommThreadSem);
   1.764 +
   1.765 +	if (iReadOverLapped.hEvent)
   1.766 +		CloseHandle(iReadOverLapped.hEvent);
   1.767 +
   1.768 +	if (iWriteOverLapped.hEvent)
   1.769 +		CloseHandle(iWriteOverLapped.hEvent);
   1.770 +
   1.771 +	if (iSignalOverLapped.hEvent)
   1.772 +		CloseHandle(iSignalOverLapped.hEvent);
   1.773 +
   1.774 +	if (iThread)
   1.775 +		CloseHandle(iThread);
   1.776 +
   1.777 +	//free up the memory
   1.778 +	ReleaseBuffers();
   1.779 +	}
   1.780 +
   1.781 +TInt DCommWins::Start()
   1.782 +	{
   1.783 +
   1.784 +	__ASSERT_ALWAYS(ResumeThread(iThread)!=0xffffffff,Panic(EWindowsUnexpectedError));
   1.785 +	iRunning=ETrue;
   1.786 +	RunCommThread(EStart);
   1.787 +	return(KErrNone);
   1.788 +	}
   1.789 +
   1.790 +void DCommWins::Stop(TStopMode aMode)
   1.791 +	{
   1.792 +
   1.793 +	RunCommThread((aMode==EStopEmergency) ? EStopNoDrain : EStop);
   1.794 +	SuspendThread(iThread);
   1.795 +	iRunning=EFalse;
   1.796 +	}
   1.797 +
   1.798 +void DCommWins::Break(TBool aState)
   1.799 +//
   1.800 +// Assert a break signal
   1.801 +//
   1.802 +	{
   1.803 +	if (aState)
   1.804 +		RunCommThread(ESetBreak);
   1.805 +	else
   1.806 +		RunCommThread(EClearBreak);
   1.807 +	}
   1.808 +
   1.809 +
   1.810 +
   1.811 +TInt DCommWins::RxCount()
   1.812 +	{
   1.813 +	DWORD err =0;
   1.814 +	COMSTAT stat;
   1.815 +	if (ClearCommError(iCommPort,&err, &stat))
   1.816 +		return stat.cbInQue;
   1.817 +	else
   1.818 +		return Emulator::LastError();
   1.819 +	}
   1.820 +
   1.821 +
   1.822 +void DCommWins::ResetBuffers(TBool aTx)
   1.823 +	{
   1.824 +	PurgeComm(iCommPort, PURGE_RXCLEAR | (aTx ? PURGE_TXCLEAR : 0));
   1.825 +	}
   1.826 +
   1.827 +
   1.828 +TBool DCommWins::AreAnyPending()
   1.829 +	{
   1.830 +	return (iReadPending != 0) || (iWritePending != 0);
   1.831 +	}
   1.832 +
   1.833 +
   1.834 +void DCommWins::WriteCancel()
   1.835 +	{
   1.836 +	DriverCommand(ETransmitCancel);
   1.837 +	}
   1.838 +
   1.839 +
   1.840 +void DCommWins::ReadCancel()
   1.841 +	{
   1.842 +	DriverCommand(EReceiveCancel);
   1.843 +	}
   1.844 +
   1.845 +void DCommWins::SignalChangeCancel()
   1.846 +	{
   1.847 +	if (iSignalsRequested)
   1.848 +		{
   1.849 +		iSignalsRequested = 0;
   1.850 +		}
   1.851 +
   1.852 +	}
   1.853 +
   1.854 +void DCommWins::DataAvailableNotificationCancel()
   1.855 +	{
   1.856 +	if (iDataAvailableNotification)
   1.857 +		{
   1.858 +		iDataAvailableNotification = EFalse;
   1.859 +		iLdd->iRxDAError = KErrCancel;
   1.860 +		iLdd->iRxDataAvailableDfc.Enque();
   1.861 +		}
   1.862 +	}
   1.863 +
   1.864 +TDes8* DCommWins::RxBuffer()
   1.865 +	{
   1.866 +	return &iInDes;
   1.867 +	}
   1.868 +
   1.869 +TInt DCommWins::SetRxBufferSize(TInt aSize)
   1.870 +	{
   1.871 +	aSize += aSize&1;	//round up to multiple of 2 bytes as windows complains if odd
   1.872 +	TInt ret = SetupComm(iCommPort, aSize, KDefaultWinNTWriteBufSize);
   1.873 +	if (ret)
   1.874 +		{
   1.875 +		iRxBufferSize = aSize;
   1.876 +		
   1.877 +		DCB dcb = {0};
   1.878 +		dcb.DCBlength = sizeof(dcb);
   1.879 +		
   1.880 +		if (!GetCommStateP(iCommPort,&dcb))
   1.881 +			return Emulator::LastError();
   1.882 +
   1.883 +		//use rx buffer size to configure xon/xoff limits
   1.884 +		dcb.XoffLim = (WORD)(iRxBufferSize / 4);		//25%
   1.885 +		if (iConfig->iParityError & KConfigXonXoffDebug)
   1.886 +			dcb.XonLim = (WORD)((iRxBufferSize / 2) -5);	//50%-5
   1.887 +		else
   1.888 +			dcb.XonLim = (WORD)((iRxBufferSize / 4) * 3);	//75%
   1.889 +
   1.890 +		if (!SetCommStateP(iCommPort,&dcb))
   1.891 +			return Emulator::LastError();
   1.892 +
   1.893 +		return KErrNone;
   1.894 +		}
   1.895 +	return Emulator::LastError();
   1.896 +	}
   1.897 +
   1.898 +
   1.899 +TInt DCommWins::RxBufferSize()
   1.900 +	{
   1.901 +	return iRxBufferSize;
   1.902 +	}
   1.903 +
   1.904 +
   1.905 +TBool DCommWins::IsATerminator(TText8 aChar)
   1.906 +	{
   1.907 +	TInt x;
   1.908 +	for (x=0; x < iConfig->iTerminatorCount; x++)
   1.909 +		if (aChar == iConfig->iTerminator[x])
   1.910 +			return ETrue;
   1.911 +	return EFalse;
   1.912 +	}
   1.913 +
   1.914 +
   1.915 +void DCommWins::ReSizeBuffer(TUint8*& aBuf, TInt& aBufLen, TPtr8& aDes, const TInt aNewLen)
   1.916 +	{
   1.917 +
   1.918 +	if (aNewLen > KSerialBufferMaxSize)
   1.919 +		Panic(ESerialBufferTooBig);
   1.920 +
   1.921 +	aBufLen = ((aNewLen + KSerialBufferIncrementSize-1) / KSerialBufferIncrementSize) * KSerialBufferIncrementSize;
   1.922 +
   1.923 +	if (aBufLen > KSerialBufferMaxSize)
   1.924 +		aBufLen = KSerialBufferMaxSize;
   1.925 +
   1.926 +	if (!VirtualAlloc(aBuf, aBufLen, MEM_COMMIT,PAGE_READWRITE))
   1.927 +		{
   1.928 +		ReleaseBuffers();
   1.929 +		Panic(ESerialBufferTooBig);
   1.930 +		}
   1.931 +	aDes.Set(aBuf, 0, aBufLen);
   1.932 +	}
   1.933 +
   1.934 +
   1.935 +void DCommWins::Write(DThread* aThread, TAny* aSrc, TInt aLength)
   1.936 +
   1.937 +	{
   1.938 +	if (aLength==0)
   1.939 +		{
   1.940 +		RunCommThread(ETransmit0);
   1.941 +		}
   1.942 +	else
   1.943 +		{
   1.944 +		if (aLength > iOutBufLength)
   1.945 +			ReSizeBuffer(iOutBufPtr, iOutBufLength, iOutDes, aLength);
   1.946 +
   1.947 +		//copy the data from the client
   1.948 +		Kern::ThreadDesRead(aThread, aSrc, iOutDes, 0,0);
   1.949 +		iOutDes.SetLength(aLength);
   1.950 +		//tell the comms thread to write the data
   1.951 +		RunCommThread(ETransmit);
   1.952 +		}
   1.953 +	}
   1.954 +
   1.955 +void DCommWins::NotifySignals(DThread* /*aThread*/, TInt aMask)
   1.956 +	{
   1.957 +	iSignalsWanted = aMask;
   1.958 +	RunCommThread(ENotifySignals);
   1.959 +	}
   1.960 +
   1.961 +
   1.962 +void DCommWins::NotifyDataAvailable()
   1.963 +	{
   1.964 +	RunCommThread(ENotifyDataAvailable);
   1.965 +	}
   1.966 +
   1.967 +
   1.968 +void DCommWins::Read(DThread* /*aThread*/, TAny* /*aDest*/, TInt aLength)
   1.969 +
   1.970 +	{
   1.971 +	TDriverCommand command;
   1.972 +
   1.973 +	if (aLength < 0)
   1.974 +		{
   1.975 +		iClientReadLength = Abs(aLength);
   1.976 +		command = EReceiveOneOrMore;
   1.977 +		}
   1.978 +	else
   1.979 +		{
   1.980 +		iClientReadLength = aLength;
   1.981 +		command = EReceive;
   1.982 +		}
   1.983 +
   1.984 +	if (iClientReadLength > iInBufLength)
   1.985 +		ReSizeBuffer(iInBufPtr, iInBufLength, iInDes, iClientReadLength);
   1.986 +	
   1.987 +	//tell the comms thread to read the data
   1.988 +	RunCommThread(command);
   1.989 +	}
   1.990 +
   1.991 +
   1.992 +
   1.993 +
   1.994 +
   1.995 +TUint DCommWins::Signals() const
   1.996 +	{
   1.997 +
   1.998 +	ULONG signals=0;
   1.999 +	GetCommModemStatusP(iCommPort,&signals);
  1.1000 +	TUint status=0;
  1.1001 +	if (signals&MS_CTS_ON)
  1.1002 +		status|=KSignalCTS;
  1.1003 +	if (signals&MS_DSR_ON)
  1.1004 +		status|=KSignalDSR;
  1.1005 +	if (signals&MS_RING_ON)
  1.1006 +		status|=KSignalRNG;
  1.1007 +	if (signals&MS_RLSD_ON)
  1.1008 +		status|=KSignalDCD;
  1.1009 +	return(status|iSignals);
  1.1010 +	}
  1.1011 +
  1.1012 +
  1.1013 +void DCommWins::SetSignals(TUint aSetMask,TUint aClearMask)
  1.1014 +	{
  1.1015 +	if (aSetMask&KSignalRTS)
  1.1016 +		{
  1.1017 +		iSignals|=KSignalRTS;
  1.1018 +		EscapeCommFunctionP(iCommPort,SETRTS);
  1.1019 +		}
  1.1020 +	if (aSetMask&KSignalDTR)
  1.1021 +		{
  1.1022 +		iSignals|=KSignalDTR;
  1.1023 +		EscapeCommFunctionP(iCommPort,SETDTR);
  1.1024 +		}
  1.1025 +	if (aClearMask&KSignalRTS)
  1.1026 +		{
  1.1027 +		iSignals&=(~KSignalRTS);
  1.1028 +		EscapeCommFunctionP(iCommPort,CLRRTS);
  1.1029 +		}
  1.1030 +	if (aClearMask&KSignalDTR)
  1.1031 +		{
  1.1032 +		iSignals&=(~KSignalDTR);
  1.1033 +		EscapeCommFunctionP(iCommPort,CLRDTR);
  1.1034 +		}
  1.1035 +	}
  1.1036 +
  1.1037 +
  1.1038 +
  1.1039 +void DCommWins::CheckConfig(TCommConfigV01& /*aConfig*/)
  1.1040 +	{
  1.1041 +	// Do nothing
  1.1042 +	}
  1.1043 +
  1.1044 +
  1.1045 +
  1.1046 +void DCommWins::Configure(TCommConfigV01 &aConfig)
  1.1047 +//
  1.1048 +// Ask comm thread to set up the serial port
  1.1049 +//
  1.1050 +	{
  1.1051 +
  1.1052 +	iConfig=&aConfig;
  1.1053 +	if (iRunning)
  1.1054 +		{
  1.1055 +		RunCommThread(EConfigure);
  1.1056 +		}
  1.1057 +	else
  1.1058 +		{
  1.1059 +//		iCommand=EConfigure;
  1.1060 +		DoConfigure();
  1.1061 +		}
  1.1062 +	}
  1.1063 +
  1.1064 +void DCommWins::DoConfigure()
  1.1065 +//
  1.1066 +// Set up the serial port
  1.1067 +//
  1.1068 +	{
  1.1069 +
  1.1070 +	DCB dcb = {0};
  1.1071 +	//set the dcb size
  1.1072 +	dcb.DCBlength = sizeof(dcb);
  1.1073 +	if (!GetCommStateP(iCommPort,&dcb))
  1.1074 +		return;
  1.1075 +
  1.1076 +			
  1.1077 +	//stop if an error happens
  1.1078 +	dcb.fAbortOnError = TRUE;
  1.1079 +	
  1.1080 +	//baud rate
  1.1081 +	switch (iConfig->iRate)
  1.1082 +		{
  1.1083 +	case EBps75:
  1.1084 +		dcb.BaudRate=75;
  1.1085 +		break;
  1.1086 +	case EBps110:
  1.1087 +		dcb.BaudRate=110;
  1.1088 +		break;
  1.1089 +	case EBps134:
  1.1090 +		dcb.BaudRate=134;
  1.1091 +		break;
  1.1092 +	case EBps150:
  1.1093 +		dcb.BaudRate=150;
  1.1094 +		break;
  1.1095 +	case EBps300:
  1.1096 +		dcb.BaudRate=300;
  1.1097 +		break;
  1.1098 +	case EBps600:
  1.1099 +		dcb.BaudRate=600;
  1.1100 +		break;
  1.1101 +	case EBps1200:
  1.1102 +		dcb.BaudRate=1200;
  1.1103 +		break;
  1.1104 +	case EBps1800:
  1.1105 +		dcb.BaudRate=1800;
  1.1106 +		break;
  1.1107 +	case EBps2400:
  1.1108 +		dcb.BaudRate=2400;
  1.1109 +		break;
  1.1110 +	case EBps4800:
  1.1111 +		dcb.BaudRate=4800;
  1.1112 +		break;
  1.1113 +	case EBps7200:
  1.1114 +		dcb.BaudRate=7200;
  1.1115 +		break;
  1.1116 +	case EBps9600:
  1.1117 +		dcb.BaudRate=9600;
  1.1118 +		break;
  1.1119 +	case EBps19200:
  1.1120 +		dcb.BaudRate=19200;
  1.1121 +		break;
  1.1122 +	case EBps38400:
  1.1123 +		dcb.BaudRate=38400;
  1.1124 +		break;
  1.1125 +	case EBps57600:
  1.1126 +		dcb.BaudRate=57600;
  1.1127 +		break;
  1.1128 +	case EBps115200:
  1.1129 +		dcb.BaudRate=115200;
  1.1130 +		break;
  1.1131 +		}
  1.1132 +   
  1.1133 +	switch (iConfig->iParity)
  1.1134 +		{
  1.1135 +	case EParityNone:
  1.1136 +		dcb.Parity=NOPARITY;
  1.1137 +		dcb.fParity = FALSE;
  1.1138 +		break;
  1.1139 +	case EParityEven:
  1.1140 +		dcb.Parity=EVENPARITY;
  1.1141 +		dcb.fParity = TRUE;
  1.1142 +		break;
  1.1143 +	case EParityOdd:
  1.1144 +		dcb.Parity=ODDPARITY;
  1.1145 +		dcb.fParity = TRUE;
  1.1146 +		break;
  1.1147 +	case EParityMark:
  1.1148 +		dcb.Parity = MARKPARITY;
  1.1149 +		dcb.fParity = TRUE;
  1.1150 +		break;
  1.1151 +	case EParitySpace:
  1.1152 +		dcb.Parity = SPACEPARITY;
  1.1153 +		dcb.fParity = TRUE;
  1.1154 +		break;
  1.1155 +		}
  1.1156 +
  1.1157 +	switch (iConfig->iParityError)
  1.1158 +		{
  1.1159 +	case KConfigParityErrorFail:
  1.1160 +		dcb.fErrorChar = FALSE;
  1.1161 +		break;
  1.1162 +
  1.1163 +	case KConfigParityErrorIgnore:
  1.1164 +		dcb.fErrorChar = FALSE;
  1.1165 +		dcb.fAbortOnError = FALSE;
  1.1166 +		break;
  1.1167 +
  1.1168 +	case KConfigParityErrorReplaceChar:
  1.1169 +		dcb.fErrorChar = TRUE;
  1.1170 +		dcb.ErrorChar = iConfig->iParityErrorChar;
  1.1171 +		break;
  1.1172 +		}
  1.1173 +
  1.1174 +
  1.1175 +	TUint& hs = iConfig->iHandshake;
  1.1176 +
  1.1177 +
  1.1178 +	//SOFTWARE FLOW CONTROL
  1.1179 +	dcb.fInX  = (hs & KConfigObeyXoff) ? TRUE : FALSE;
  1.1180 +	dcb.fOutX = (hs & KConfigSendXoff) ? TRUE : FALSE;
  1.1181 +
  1.1182 +	dcb.XonChar = iConfig->iXonChar;
  1.1183 +	dcb.XoffChar = iConfig->iXoffChar;
  1.1184 +	dcb.ErrorChar = iConfig->iParityErrorChar;
  1.1185 +
  1.1186 +	//use rx buffer size to configure xon/xoff limits
  1.1187 +	dcb.XoffLim = (WORD)(iRxBufferSize / 4);		//25%
  1.1188 +	if (iConfig->iParityError & KConfigXonXoffDebug)
  1.1189 +		dcb.XonLim = (WORD)((iRxBufferSize / 2) -5);	//50%-5
  1.1190 +	else
  1.1191 +		dcb.XonLim = (WORD)((iRxBufferSize / 4) * 3);	//75%
  1.1192 +
  1.1193 +
  1.1194 +
  1.1195 +	//OUTPUT HARDWARE FLOW CONTROL
  1.1196 +	//set out DSR control to be off
  1.1197 +	dcb.fOutxDsrFlow = FALSE;
  1.1198 +	dcb.fOutxCtsFlow = (hs & KConfigObeyCTS) ? TRUE : FALSE;
  1.1199 +	dcb.fDsrSensitivity =  (hs & KConfigObeyDSR) ? TRUE : FALSE;
  1.1200 +
  1.1201 +
  1.1202 +	if (hs & KConfigObeyDCD)
  1.1203 +		{
  1.1204 +		}
  1.1205 +
  1.1206 +	
  1.1207 +	//INPUT HARDWARE FLOW CONTROL
  1.1208 +	dcb.fRtsControl = (hs & KConfigFreeRTS) ? RTS_CONTROL_DISABLE : RTS_CONTROL_HANDSHAKE;
  1.1209 +	dcb.fDtrControl = (hs & KConfigFreeDTR) ? DTR_CONTROL_DISABLE : DTR_CONTROL_ENABLE;
  1.1210 +
  1.1211 +
  1.1212 +	//complete with KErrCommsLineFail if these are set and the line goes low
  1.1213 +	iFailSignals = 0;
  1.1214 +	if (hs & KConfigFailDSR)
  1.1215 +		iFailSignals |= KSignalDSR;
  1.1216 +	
  1.1217 +	if (hs & KConfigFailCTS)
  1.1218 +		iFailSignals |= KSignalCTS;
  1.1219 +
  1.1220 +	if (hs & KConfigFailDCD)
  1.1221 +		iFailSignals |= KSignalDCD;
  1.1222 +	
  1.1223 +	
  1.1224 +	iTerminatedRead = iConfig->iTerminatorCount > 0;
  1.1225 +
  1.1226 +   	switch(iConfig->iDataBits)
  1.1227 +		{
  1.1228 +	case EData5:
  1.1229 +		dcb.ByteSize=5;	
  1.1230 +		break;
  1.1231 +	case EData6:
  1.1232 +		dcb.ByteSize=6;
  1.1233 +		break;
  1.1234 +	case EData7:
  1.1235 +		dcb.ByteSize=7;
  1.1236 +		break;
  1.1237 +	case EData8:
  1.1238 +		dcb.ByteSize=8;
  1.1239 +		break;
  1.1240 +		}
  1.1241 +
  1.1242 +	switch(iConfig->iStopBits)
  1.1243 +		{
  1.1244 +	case EStop1:
  1.1245 +		dcb.StopBits=ONESTOPBIT;
  1.1246 +		break;
  1.1247 +	case EStop2:
  1.1248 +		dcb.StopBits=TWOSTOPBITS;
  1.1249 +		break;
  1.1250 +		}
  1.1251 +
  1.1252 +
  1.1253 +
  1.1254 +	TInt error_r=KErrNone;
  1.1255 +	if(!SetCommStateP(iCommPort,&dcb))
  1.1256 +		error_r=GetLastError();
  1.1257 +
  1.1258 +// Clear any error we may have caused
  1.1259 +//
  1.1260 +	DWORD err,res;
  1.1261 +	COMSTAT s;
  1.1262 +	if (ClearCommError(iCommPort,&err,&s)==FALSE)
  1.1263 +		res=GetLastError();
  1.1264 +
  1.1265 +	}
  1.1266 +
  1.1267 +void DCommWins::Caps(TDes8 &aCaps) const
  1.1268 +//
  1.1269 +// Return the current capabilities
  1.1270 +//
  1.1271 +	{
  1.1272 +
  1.1273 +	GetWinsCommsCaps(aCaps);
  1.1274 +	}
  1.1275 +
  1.1276 +
  1.1277 +void DCommWins::WaitForEvent()
  1.1278 +	{
  1.1279 +
  1.1280 +	HANDLE objects[4];
  1.1281 +
  1.1282 +
  1.1283 +	iReadOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL); 
  1.1284 +	iWriteOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL);
  1.1285 +	iSignalOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL);
  1.1286 +	objects[0]=iSignalOverLapped.hEvent; // iCommPort;
  1.1287 +	objects[1]=iCommThreadSem;
  1.1288 +	objects[2]=iWriteOverLapped.hEvent;
  1.1289 +	objects[3]=iReadOverLapped.hEvent;
  1.1290 +
  1.1291 +	FOREVER
  1.1292 +		{
  1.1293 +		DWORD ret=WaitForMultipleObjectsEx(4,objects,FALSE,INFINITE,TRUE);
  1.1294 +		switch (ret)
  1.1295 +			{
  1.1296 +		case WAIT_OBJECT_0:
  1.1297 +			{
  1.1298 +			//			EnterCritical();
  1.1299 +
  1.1300 +			if (iDataAvailableNotification)
  1.1301 +				{
  1.1302 +				DataAvailableCompletion(this);
  1.1303 +				iDataAvailableNotification = EFalse;	//stop us repeatedly reporting it
  1.1304 +				}
  1.1305 +
  1.1306 +			// Detect breaks
  1.1307 +			if (iSignalStatus & EV_BREAK)
  1.1308 +				{
  1.1309 +				iBreakDetected=ETrue; // the read will complete with an error
  1.1310 +				}
  1.1311 +				
  1.1312 +			TUint currentSignals = Signals();
  1.1313 +
  1.1314 +			//mask out all the signals but the ones we are interested in
  1.1315 +			iLineFail = (iFailSignals & currentSignals) != iFailSignals;
  1.1316 +			if (iLineFail)
  1.1317 +				{
  1.1318 +				//if we have the handshake options of
  1.1319 +				//KConfigFailDSR, KConfigFailDCD KFailConfigCTS set
  1.1320 +				//we need to do something if any of them are low so
  1.1321 +				//complete any outstanding ops with failure
  1.1322 +				if (iReadPending)
  1.1323 +					{
  1.1324 +					//we have a read to complete
  1.1325 +					iRXLineFail = ETrue;
  1.1326 +					PurgeComm(iCommPort, PURGE_RXABORT);
  1.1327 +					}
  1.1328 +
  1.1329 +				if (iWritePending)
  1.1330 +					{
  1.1331 +					//we have a write to complete
  1.1332 +					iTXLineFail = ETrue;
  1.1333 +					PurgeComm(iCommPort, PURGE_TXABORT);
  1.1334 +					}
  1.1335 +				}
  1.1336 +
  1.1337 +
  1.1338 +			//iSignalsRequested will only have bits set if outstanding request
  1.1339 +			TUint changed = (currentSignals ^ iSavedSignals) & iSignalsRequested;
  1.1340 +			if (changed) 
  1.1341 +				{
  1.1342 +				SignalCompletion(this, KErrNone, changed, currentSignals);
  1.1343 +				iSavedSignals = currentSignals;
  1.1344 +				iSignalsRequested = 0;				//stop us repeatedly reporting it.
  1.1345 +												//iSignalsRequested is setup in the call to notify
  1.1346 +				}
  1.1347 +			
  1.1348 +			if (iWritePending == ETransmit0 && (currentSignals & KSignalCTS) != 0)
  1.1349 +				WriteCompletion(this, KErrNone, 0);
  1.1350 +
  1.1351 +			//request another notification event.  All events are requested.
  1.1352 +			iSignalStatus=0;
  1.1353 +			DWORD commErrors;
  1.1354 +			BOOL res;
  1.1355 +			DWORD lastError = 0;
  1.1356 +			COMSTAT cstat;
  1.1357 +
  1.1358 +			do
  1.1359 +				{
  1.1360 +				ClearCommError(iCommPort,&commErrors,&cstat);
  1.1361 +				res = WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped);
  1.1362 +				if (!res)
  1.1363 +					lastError = GetLastError();
  1.1364 +				}
  1.1365 +			while((!res) && (lastError != ERROR_IO_PENDING));
  1.1366 +
  1.1367 +			break;
  1.1368 +			}
  1.1369 +
  1.1370 +		case WAIT_OBJECT_0+1:
  1.1371 +//
  1.1372 +// iCommThreadSemaphore has been signalled
  1.1373 +//
  1.1374 +			DriverCommand(iCommand);
  1.1375 +			break;
  1.1376 +		case WAIT_OBJECT_0+2:
  1.1377 +			//
  1.1378 +			//	Write completion
  1.1379 +			//
  1.1380 +			{
  1.1381 +
  1.1382 +			DWORD len = 0;
  1.1383 +			TInt error = KErrNone;
  1.1384 +			if (!GetOverlappedResult(iCommPort, &iWriteOverLapped, &len, FALSE))
  1.1385 +				error = Emulator::LastError();
  1.1386 +			
  1.1387 +			COMSTAT s;
  1.1388 +			DWORD err = 0;
  1.1389 +			ClearCommError(iCommPort,&err,&s);
  1.1390 +
  1.1391 +			//if we are failing if one or more of CTS, DSR, DCD go low
  1.1392 +			if (iTXLineFail)
  1.1393 +				{
  1.1394 +				error = KErrCommsLineFail;
  1.1395 +				iTXLineFail = EFalse;
  1.1396 +				}
  1.1397 +			else if (err)
  1.1398 +				{
  1.1399 +				if (err & CE_FRAME)
  1.1400 +					error = KErrCommsFrame;
  1.1401 +				else if (err & CE_OVERRUN)
  1.1402 +					error = KErrCommsOverrun;
  1.1403 +				else if (err & CE_RXPARITY)
  1.1404 +					error = KErrCommsParity;
  1.1405 +				}
  1.1406 +
  1.1407 +			WriteCompletion(this, error, len);
  1.1408 +			break;
  1.1409 +			}
  1.1410 +
  1.1411 +		case WAIT_OBJECT_0+3:
  1.1412 +			//
  1.1413 +			//	Read completion
  1.1414 +			//
  1.1415 +			{
  1.1416 +			DWORD len = 0;
  1.1417 +			TInt error = KErrNone;
  1.1418 +			if (!GetOverlappedResult(iCommPort, &iReadOverLapped, &len, FALSE))
  1.1419 +				{
  1.1420 +				// May have a break already detected to report
  1.1421 +				if (iBreakDetected)
  1.1422 +					{
  1.1423 +					error=KErrCommsBreak;
  1.1424 +					iBreakDetected=EFalse;
  1.1425 +					}
  1.1426 +				else
  1.1427 +					error = Emulator::LastError();
  1.1428 +				}
  1.1429 +			else
  1.1430 +				iBreakDetected=EFalse; // No error, so any breaks have finished
  1.1431 +			
  1.1432 +			COMSTAT s;
  1.1433 +			DWORD err = 0;
  1.1434 +			ClearCommError(iCommPort,&err,&s);
  1.1435 +
  1.1436 +			//if we are failing if one or more of CTS, DSR, DCD go low
  1.1437 +			if (iRXLineFail)
  1.1438 +				{
  1.1439 +				error = KErrCommsLineFail;
  1.1440 +				iRXLineFail = EFalse;
  1.1441 +				}
  1.1442 +			else if (err)
  1.1443 +				{
  1.1444 +				if (err & CE_FRAME)
  1.1445 +					error = KErrCommsFrame;
  1.1446 +				else if (err & CE_OVERRUN)
  1.1447 +					error = KErrCommsOverrun;
  1.1448 +				else if (err & CE_RXPARITY)
  1.1449 +					error = KErrCommsParity;
  1.1450 +				}
  1.1451 +
  1.1452 +			ReadCompletion(this, error, len);
  1.1453 +			break;
  1.1454 +			}
  1.1455 +
  1.1456 +		case WAIT_IO_COMPLETION:
  1.1457 +			break;
  1.1458 +
  1.1459 +		default:
  1.1460 +			Emulator::LastError();
  1.1461 +			FAULT();
  1.1462 +			}
  1.1463 +		}
  1.1464 +	}
  1.1465 +
  1.1466 +void DCommWins::DriverCommand(TDriverCommand aCommand)
  1.1467 +//
  1.1468 +// Do a driver command - executed when the semaphore has been signalled in the comm port thread
  1.1469 +//
  1.1470 +	{
  1.1471 +	switch (aCommand)
  1.1472 +		{
  1.1473 +	case ESetBreak:
  1.1474 +		FlushFileBuffers(iCommPort);
  1.1475 +		SetCommBreak(iCommPort);
  1.1476 +		break;
  1.1477 +
  1.1478 +	case EClearBreak:
  1.1479 +		ClearCommBreak(iCommPort);
  1.1480 +		break;
  1.1481 +
  1.1482 +	case ETransmit0:
  1.1483 +		
  1.1484 +		if (!iWritePending)
  1.1485 +			{
  1.1486 +			if ((iConfig->iHandshake & KConfigObeyCTS) != 0 && (Signals() & KSignalCTS) == 0)
  1.1487 +				iWritePending = ETransmit0;
  1.1488 +			else
  1.1489 +				DoWriteComplete(KErrNone);
  1.1490 +			}
  1.1491 +		break;
  1.1492 +
  1.1493 +	case ETransmit:
  1.1494 +		
  1.1495 +		if (!iWritePending)
  1.1496 +			{
  1.1497 +			COMMTIMEOUTS ct;
  1.1498 +			int r = GetCommTimeouts(iCommPort, &ct);
  1.1499 +			ct.WriteTotalTimeoutConstant = 0;
  1.1500 +			ct.WriteTotalTimeoutMultiplier = 0;
  1.1501 +			r = SetCommTimeouts(iCommPort, &ct);
  1.1502 +
  1.1503 +			WriteFileP(iCommPort,iOutDes.Ptr(), iOutDes.Length(), &dummyLen, &iWriteOverLapped);
  1.1504 +			iWritePending = ETransmit;
  1.1505 +			iTransmitting= ETrue;
  1.1506 +			}
  1.1507 +		break;
  1.1508 +
  1.1509 +	case EStart:
  1.1510 +		{
  1.1511 +		iSignalStatus=0;
  1.1512 +		iSignalStatus=0;
  1.1513 +		DWORD commErrors;
  1.1514 +		BOOL res;
  1.1515 +		DWORD lastError = 0;
  1.1516 +		COMSTAT cstat;
  1.1517 +
  1.1518 +		do
  1.1519 +			{
  1.1520 +			ClearCommError(iCommPort,&commErrors,&cstat);
  1.1521 +			res = WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped);
  1.1522 +			if (!res)
  1.1523 +				lastError = GetLastError();
  1.1524 +			}
  1.1525 +		while((!res) && (lastError != ERROR_IO_PENDING));
  1.1526 +		}
  1.1527 +		break;
  1.1528 +	
  1.1529 +	case EStop:
  1.1530 +        // Flush last write
  1.1531 +		if(iWritePending == ETransmit)
  1.1532 +			{
  1.1533 +			WaitForSingleObject(iWriteOverLapped.hEvent, INFINITE);
  1.1534 +			FlushFileBuffers(iCommPort);
  1.1535 +			}
  1.1536 +        iWritePending=0;
  1.1537 +        iTransmitting=EFalse;
  1.1538 +		// Fall through
  1.1539 +	case EStopNoDrain:
  1.1540 +		// Cancel any pending writes
  1.1541 +        if(iWritePending == ETransmit)
  1.1542 +		    {
  1.1543 +			PurgeComm(iCommPort, PURGE_TXABORT|PURGE_TXCLEAR);
  1.1544 +            WaitForSingleObject(iWriteOverLapped.hEvent, INFINITE);
  1.1545 +		    }   
  1.1546 +        iWritePending=0;
  1.1547 +		iTransmitting=EFalse;
  1.1548 +		iStopping=ETrue;
  1.1549 +        if(iRunning)
  1.1550 +            {
  1.1551 +            SetCommMaskP(iCommPort,EV_BREAK|EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR);
  1.1552 +            WaitForSingleObject(iSignalOverLapped.hEvent, INFINITE);
  1.1553 +            }
  1.1554 +		break;
  1.1555 +
  1.1556 +	case EDie:	
  1.1557 +		SignalDriverThread();
  1.1558 +		ExitThread(1);
  1.1559 +		break;
  1.1560 +	
  1.1561 +	case EConfigure:
  1.1562 +		DoConfigure();
  1.1563 +		break;
  1.1564 +	
  1.1565 +	case ETransmitCancel:
  1.1566 +		if (iWritePending == ETransmit)
  1.1567 +			PurgeComm(iCommPort, PURGE_TXABORT);
  1.1568 +//		else if (iWritePending == ETransmit0)
  1.1569 +//			{
  1.1570 +			// careful - this runs in the context of the kernel thread, not the event thread
  1.1571 +		iLdd->iTxError = KErrCancel;
  1.1572 +		iLdd->iTxCompleteDfc.Enque();
  1.1573 +//			}
  1.1574 +		break;
  1.1575 +
  1.1576 +	case EReceive:
  1.1577 +		if (!iReadPending)
  1.1578 +			{
  1.1579 +			COMMTIMEOUTS ct;
  1.1580 +			int r = GetCommTimeouts(iCommPort, &ct);
  1.1581 +			ct.ReadIntervalTimeout = 0;
  1.1582 +			ct.ReadTotalTimeoutMultiplier = 0;
  1.1583 +			ct.ReadTotalTimeoutConstant = 0;
  1.1584 +			r = SetCommTimeouts(iCommPort, &ct);
  1.1585 +
  1.1586 +			//if we are doing a terminated read.... we need to do it a byte at a time!
  1.1587 +			if (iTerminatedRead)
  1.1588 +				{
  1.1589 +				iReadSoFar = 0;
  1.1590 +				ReadFileP(iCommPort,(void*)iInDes.Ptr(), 1, &dummyLen, &iReadOverLapped);
  1.1591 +				}
  1.1592 +			else
  1.1593 +				{
  1.1594 +				ReadFileP(iCommPort,(void*)iInDes.Ptr(), iClientReadLength, &dummyLen, &iReadOverLapped);
  1.1595 +				}
  1.1596 +
  1.1597 +			iReadPending = EReceive;
  1.1598 +			}
  1.1599 +		break;
  1.1600 +
  1.1601 +	case EReceiveOneOrMore:
  1.1602 +		if (!iReadPending)
  1.1603 +			{
  1.1604 +			COMMTIMEOUTS ct;
  1.1605 +			int r = GetCommTimeouts(iCommPort, &ct);
  1.1606 +			ct.ReadIntervalTimeout = MAXDWORD;
  1.1607 +			ct.ReadTotalTimeoutMultiplier = MAXDWORD;
  1.1608 +			ct.ReadTotalTimeoutConstant = KReadOneOrMoreTimeout;
  1.1609 +			r = SetCommTimeouts(iCommPort, &ct);
  1.1610 +
  1.1611 +			//if we are doing a terminated read....
  1.1612 +			if (iTerminatedRead)
  1.1613 +				{
  1.1614 +				iReadSoFar = 0;
  1.1615 +				ReadFileP(iCommPort,(void*)iInDes.Ptr(), 1, &dummyLen, &iReadOverLapped);
  1.1616 +				}
  1.1617 +			else
  1.1618 +				{
  1.1619 +				ReadFileP(iCommPort,(void*)iInDes.Ptr(), iClientReadLength, &dummyLen, &iReadOverLapped);
  1.1620 +				}
  1.1621 +
  1.1622 +			iReadPending = EReceiveOneOrMore;
  1.1623 +			}
  1.1624 +		break;
  1.1625 +
  1.1626 +	case EReceiveCancel:
  1.1627 +		if (iReadPending)
  1.1628 +			PurgeComm(iCommPort, PURGE_RXABORT);
  1.1629 +		else if (iDataAvailableNotification)
  1.1630 +			DataAvailableNotificationCancel();
  1.1631 +		break;
  1.1632 +
  1.1633 +	case ENotifyDataAvailable:
  1.1634 +		{
  1.1635 +		iDataAvailableNotification = ETrue;
  1.1636 +		//setup the comms notifications for data available
  1.1637 +		break;
  1.1638 +		}
  1.1639 +
  1.1640 +	case ENotifySignals:
  1.1641 +		{
  1.1642 +		TUint currentSignals = Signals();
  1.1643 +		TUint changed = (currentSignals ^ iSavedSignals) & iSignalsWanted;
  1.1644 +		if (changed) 
  1.1645 +			{
  1.1646 +			SignalCompletion(this, KErrNone, changed, currentSignals);
  1.1647 +			iSavedSignals = currentSignals;
  1.1648 +			iSignalsWanted = 0;				
  1.1649 +			}
  1.1650 +		else
  1.1651 +			iSignalsRequested = iSignalsWanted;	//checked when signals change
  1.1652 +		}
  1.1653 +		break;
  1.1654 +
  1.1655 +
  1.1656 +	default:
  1.1657 +		// Panic(EUnknownCommand);
  1.1658 +		break;
  1.1659 +		}
  1.1660 +	iCommand=EInvalidCommand;
  1.1661 +	SignalDriverThread();
  1.1662 +	}
  1.1663 +
  1.1664 +
  1.1665 +TDfcQue* DCommWins::DfcQ(TInt /*aUnit*/)
  1.1666 +	{
  1.1667 +	return Kern::DfcQue0();
  1.1668 +	}
  1.1669 +
  1.1670 +
  1.1671 +TInt DCommWins::ValidateConfig(const TCommConfigV01 &aConfig) const
  1.1672 +//
  1.1673 +// Check a config structure.
  1.1674 +//
  1.1675 +	{
  1.1676 +	if(aConfig.iRate & EBpsSpecial)
  1.1677 +		return KErrNotSupported;
  1.1678 +
  1.1679 +	switch (aConfig.iParity)
  1.1680 +		{
  1.1681 +		case EParityNone:
  1.1682 +		case EParityOdd:
  1.1683 +		case EParityEven:
  1.1684 +			break;
  1.1685 +		default:
  1.1686 +			return KErrNotSupported;
  1.1687 +		}
  1.1688 +	switch (aConfig.iRate)
  1.1689 +		{
  1.1690 +		case EBps50:
  1.1691 +		case EBps75:
  1.1692 +		case EBps134:
  1.1693 +		case EBps1800:
  1.1694 +		case EBps2000:
  1.1695 +		case EBps3600:
  1.1696 +		case EBps7200:
  1.1697 +			return KErrNotSupported;
  1.1698 +		default:
  1.1699 +			break;
  1.1700 +		};
  1.1701 +	return KErrNone;
  1.1702 +	}
  1.1703 +
  1.1704 +inline TBool DCommWins::LineFail()
  1.1705 +	{
  1.1706 +	return iLineFail;
  1.1707 +	}
  1.1708 +
  1.1709 +
  1.1710 +
  1.1711 +DECLARE_STANDARD_PDD()
  1.1712 +	{
  1.1713 +	return new DDriverComm;
  1.1714 +	}
  1.1715 +