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