toolsandutils/wintunnel/src_beech/d_cdrv.cpp
changeset 0 83f4b4db085c
child 10 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 // Copyright (c) 1995-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 // Modified serial pdd that supports IP tunneling data from the emulator to  socket.
       
    15 // Beech specific version.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #if defined(_UNICODE)
       
    24 #if !defined(UNICODE)
       
    25 #define UNICODE
       
    26 #endif
       
    27 #endif
       
    28 #define _WIN32_WINDOWS 0x0410 // Need NT4 / 98 or higher for the timer
       
    29 #define WIN32_LEAN_AND_MEAN
       
    30 #pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
       
    31 #include <windows.h>
       
    32 #include <winsock2.h>
       
    33 #pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
       
    34 #include <k32std.h>
       
    35 #include <e32wins.h>
       
    36 #include "uansi.h"
       
    37 #include "d_comm.h"
       
    38 
       
    39 //#include "iostream.h"
       
    40 
       
    41 // Dumps everything written to the serial port to temp files.
       
    42 //#define _LOG_OUTPUT
       
    43 
       
    44 
       
    45 //----------------------------------------------------------------
       
    46 //  logging macros. Just define WINTUN_PDD_LOGGING to enable debug trace
       
    47 //  require MSVCRTD.LIB
       
    48 #include <crtdbg.h>
       
    49 
       
    50 //#define WINTUN_PDD_LOGGING 
       
    51 
       
    52 #ifdef WINTUN_PDD_LOGGING 
       
    53     
       
    54     #pragma warning( disable : 4127 ) 
       
    55 
       
    56     #define _Log(a)         _RPT0(_CRT_WARN,a)
       
    57     #define _Log2(a,b)      _RPT1(_CRT_WARN,a,b)
       
    58     #define _Log3(a,b,c)    _RPT2(_CRT_WARN,a,b,c)
       
    59     #define _Log4(a,b,c,d)  _RPT3(_CRT_WARN,a,b,c,d)
       
    60 
       
    61 #else
       
    62     #define _Log(a)       
       
    63     #define _Log2(a,b)    
       
    64     #define _Log3(a,b,c)  
       
    65     #define _Log4(a,b,c,d)
       
    66 
       
    67 #endif
       
    68 
       
    69 const TInt KReadBufSize = 1024;
       
    70 const TInt KWriteBufSize = 16;
       
    71 //const TInt KWinNTReadBufSize = 1024;
       
    72 const TInt KWinNTReadBufSize = 1500;
       
    73 const TInt KWinNTWriteBufSize = KWriteBufSize;
       
    74 static DWORD dummyLen=0;
       
    75 
       
    76 enum TDCommWinsFault 
       
    77 	{
       
    78 	EWindowsUnexpectedError,
       
    79 	EUnknownCommand,
       
    80 	EBadIOLen,
       
    81 	EEofOnSerial,
       
    82 	EWriteEarlyCompletion,
       
    83 	ELineErrorNotReported,
       
    84 	};
       
    85 
       
    86 class DDriverComm : public DPhysicalDevice
       
    87 	{
       
    88 public:
       
    89 	DDriverComm();
       
    90 	virtual TInt Install();
       
    91 	virtual TInt Remove();
       
    92 	virtual void GetCaps(TDes8 &aDes) const;
       
    93 	virtual CBase *CreateL(TInt aUnit,const TDesC *anInfo,const TVersion &aVer);
       
    94 	};
       
    95 
       
    96 class DCommWins : public DComm
       
    97 	{
       
    98 public:
       
    99 	enum TDriverCommand {ESetBreak,EClearBreak,ETransmit,
       
   100 						EGetSignals,ESetSignals,EConfigure,
       
   101 						EStop,EStopNoDrain,EStart,EDie,EInvalidCommand};
       
   102 public:
       
   103 	DCommWins();
       
   104 	~DCommWins();
       
   105 	virtual TInt Start();
       
   106 	virtual void Stop(TStopMode aMode);
       
   107 	virtual void Break(TBool aState);
       
   108 	virtual void EnableTransmit();
       
   109 	virtual TUint Signals() const;
       
   110 	virtual void SetSignals(TUint aSetMask,TUint aClearMask);
       
   111 	virtual TInt Validate(const TCommConfigV01 &aConfig) const;
       
   112 	virtual void Configure(TCommConfigV01 &aConfig);
       
   113 	virtual void DoConfigure();
       
   114 	virtual void CheckConfig(TCommConfigV01& aConfig);
       
   115 	virtual void Caps(TDes8 &aCaps) const;
       
   116 	virtual void EnableInterrupts();
       
   117 	virtual void DisableInterrupts();
       
   118 	TInt CompleteSlowOpen(DThread *aThread,TRequestStatus *aReqStat);
       
   119 	void EnterCritical();
       
   120 	void LeaveCritical();
       
   121 	TInt DoCreate(TInt aUnit,const TDesC *anInfo);
       
   122 	void WaitForEvent();
       
   123 	void DriverCommand(TDriverCommand aCommand);
       
   124 	void DoTransmit(TInt aByteCount);
       
   125 	void DoReceive(TInt aByteCount);
       
   126 	void RunCommThread(TDriverCommand aCommand);
       
   127 	inline void SignalDriverThread();
       
   128 	TInt DoTransmitIsr(TInt anOffset);
       
   129 	void DoReceiveIsr(TUint aCharAndMask);
       
   130 	void DoStateIsr();
       
   131 	
       
   132     void SetTimer(const TUint aTimeOut); 
       
   133     void CancelTimer(); 
       
   134 	
       
   135 	
       
   136 private:
       
   137 	TBool iWritePending;
       
   138 	TBool iReadPending;
       
   139 
       
   140     TBool iStopping;
       
   141 	// TBool iReading;
       
   142 	TBool iRunning;
       
   143 	TDriverCommand iCommand;
       
   144 	TCommConfigV01 *iConfig;
       
   145 	TUint iSignals;
       
   146 	TUint8 iInBuf[KReadBufSize];
       
   147 	DWORD iNumInChars;
       
   148 	TUint8 iOutBuf[KWriteBufSize];
       
   149 	DWORD iNumOutChars;
       
   150 	HANDLE iThread;
       
   151 	HANDLE iCommThreadSem;
       
   152 	HANDLE iDriverThreadSem;
       
   153 	HANDLE iCommPort;
       
   154     HANDLE iWaitableTimer; 
       
   155     LARGE_INTEGER iTimeOut; 
       
   156 	DWORD iThreadID;
       
   157 	DWORD iSignalStatus;
       
   158 	OVERLAPPED iReadOverLapped;
       
   159 	OVERLAPPED iWriteOverLapped;
       
   160 	OVERLAPPED iSignalOverLapped;
       
   161 #if defined (_DEBUG)
       
   162 	TInt iUnit;
       
   163 	HANDLE iLogFile;
       
   164 #endif
       
   165 #if defined (_LOG_OUTPUT)
       
   166 	HANDLE iWritesHandle;
       
   167 	HANDLE iReadsHandle;
       
   168 #endif
       
   169 	CRITICAL_SECTION iCriticalSection;
       
   170 	TInt iIntRefCount;
       
   171 	TBool iSkipTransmitIsrNextTime;
       
   172 
       
   173 	SOCKET iSocket;
       
   174 	
       
   175 
       
   176     /** @return ETrue if we use socket instead of a real COM port */
       
   177     TBool inline UseSocket(void) const
       
   178         {return  (iSocket != INVALID_SOCKET) && (iSocket != NULL); }
       
   179     
       
   180     TInt QueSocketRead();
       
   181     
       
   182     TBool GetComPortMapping(LPCSTR aFileName, TInt aPortNum, TDes8& aPortMapStr);
       
   183 
       
   184 	};
       
   185 
       
   186 void Panic(TDCommWinsFault aFault)
       
   187 //
       
   188 // Panic the driver 
       
   189 //
       
   190 	{
       
   191 
       
   192 	Plat::Panic(_L("DCommWins"),aFault);
       
   193 	}
       
   194 
       
   195 
       
   196 TInt MapWinError(TInt aErrCode)
       
   197 {
       
   198 	switch (aErrCode)
       
   199 	{
       
   200 	case ERROR_INVALID_USER_BUFFER:
       
   201 	case ERROR_NOT_ENOUGH_MEMORY:
       
   202 	case ERROR_INSUFFICIENT_BUFFER:
       
   203 		return(KErrNoMemory);
       
   204 	case ERROR_ACCESS_DENIED:
       
   205 		return(KErrAccessDenied);
       
   206 	case ERROR_NOT_SUPPORTED:
       
   207 		return(KErrNotSupported);
       
   208 	default:
       
   209 		return(KErrGeneral);
       
   210 	} 
       
   211 }
       
   212 
       
   213 TInt MapWinError()
       
   214 //
       
   215 // Make an E32 error from the dodgy old thing windows tells us
       
   216 //
       
   217 {
       
   218 	DWORD winErr=GetLastError();
       
   219     return MapWinError(winErr);
       
   220 }
       
   221 
       
   222 TUint commThread(DCommWins *comm)
       
   223 //
       
   224 // Comm thread entry point
       
   225 //
       
   226 	{
       
   227 
       
   228 	comm->WaitForEvent();
       
   229 	return 0;
       
   230 	}
       
   231 
       
   232 //VOID WINAPI ReadComplete(DWORD anErr,DWORD numBytes,LPOVERLAPPED anOverLapped)
       
   233 //
       
   234 // Windows read completion routine
       
   235 //
       
   236 //	{
       
   237 //
       
   238 //	if (numBytes>KReadBufSize)
       
   239 //		Panic(EBadIOLen); 
       
   240 //	if (anErr==ERROR_HANDLE_EOF)
       
   241 //		Panic(EEofOnSerial);
       
   242 //	((DCommWins *)(anOverLapped->hEvent))->DoReceive(numBytes);
       
   243 //	}
       
   244 
       
   245 VOID WINAPI WriteCompletion(DCommWins *aDrv, DWORD anErr,DWORD numBytes)
       
   246 //
       
   247 // Windows read completion routine
       
   248 //
       
   249 	{
       
   250 
       
   251 	if (numBytes>KWriteBufSize+1)	// May have written an Xon
       
   252 		Panic(EBadIOLen); 
       
   253 	if (anErr==ERROR_HANDLE_EOF)
       
   254 		Panic(EEofOnSerial);
       
   255 	aDrv->DoTransmit(numBytes);
       
   256 	}
       
   257 
       
   258 BOOL WINAPI EscapeCommFunctionP(HANDLE hFile,DWORD dwFunc, BOOL bUseSocket)
       
   259 //
       
   260 // Protected Set/Clear modem control signals: protects against this operation being cancelled by another thread
       
   261 //
       
   262     {
       
   263 	if(bUseSocket)
       
   264         return TRUE;
       
   265 
       
   266     DWORD err,res,res1;
       
   267 	COMSTAT s;
       
   268 	BOOL result;
       
   269 
       
   270 	result=FALSE;
       
   271 	do
       
   272 		{
       
   273 		ClearCommError(hFile,&err,&s);
       
   274 		if((res1=EscapeCommFunction(hFile,dwFunc))==FALSE)
       
   275 			res=GetLastError();
       
   276 		else
       
   277 			{
       
   278 			result=TRUE;
       
   279 			break;
       
   280 			}
       
   281 		}
       
   282 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   283 	return(result);
       
   284 	}
       
   285 
       
   286 BOOL WINAPI GetCommModemStatusP(HANDLE hFile,LPDWORD lpModemStat, BOOL bUseSocket)
       
   287 //
       
   288 // Protected read modem control signals: protects against this operation being cancelled by another thread
       
   289 //
       
   290 	{
       
   291 	if(bUseSocket)
       
   292         return TRUE;
       
   293 
       
   294 	DWORD err,res,res1;
       
   295 	COMSTAT s;
       
   296 	BOOL result;
       
   297 
       
   298 	result=FALSE;
       
   299 	do
       
   300 		{
       
   301 		ClearCommError(hFile,&err,&s);
       
   302 		if((res1=GetCommModemStatus(hFile,lpModemStat))==FALSE)
       
   303 			res=GetLastError();
       
   304 		else
       
   305 			{
       
   306 			result=TRUE;
       
   307 			break;
       
   308 			}
       
   309 		}
       
   310 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   311 	return(result);
       
   312 	}
       
   313 
       
   314 BOOL WINAPI GetCommStateP(HANDLE hFile,LPDCB lpDCB, BOOL bUseSocket)
       
   315 //
       
   316 // Retrieves the current control settings for a specified communications device: protected against
       
   317 // this operation being cancelled by another thread
       
   318 //
       
   319 	{
       
   320 	if(bUseSocket)
       
   321         return TRUE;
       
   322 
       
   323 	DWORD err,res,res1;
       
   324 	COMSTAT s;
       
   325 	BOOL result;
       
   326 
       
   327 	result=FALSE;
       
   328 	do
       
   329 		{
       
   330 		ClearCommError(hFile,&err,&s);
       
   331 		if((res1=GetCommState(hFile,lpDCB))==FALSE)
       
   332 			res=GetLastError();
       
   333 		else
       
   334 			{
       
   335 			result=TRUE;
       
   336 			break;
       
   337 			}
       
   338 		}
       
   339 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   340 	return(result);
       
   341 	}
       
   342 
       
   343 BOOL WINAPI SetCommStateP(HANDLE hFile,LPDCB lpDCB, BOOL bUseSocket)
       
   344 //
       
   345 // Configures a communications device according to the specifications in a device-control block: protected against
       
   346 // this operation being cancelled by another thread
       
   347 //
       
   348 	{
       
   349 	if(bUseSocket)
       
   350         return TRUE;
       
   351 
       
   352 	DWORD err,res,res1;
       
   353 	COMSTAT s;
       
   354 	BOOL result;
       
   355 
       
   356 	result=FALSE;
       
   357 	do
       
   358 		{
       
   359 		ClearCommError(hFile,&err,&s);
       
   360 		if((res1=SetCommState(hFile,lpDCB))==FALSE)
       
   361 			res=GetLastError();
       
   362 		else
       
   363 			{
       
   364 			result=TRUE;
       
   365 			break;
       
   366 			}
       
   367 		}
       
   368 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   369 	return(result);
       
   370 	}
       
   371 
       
   372 BOOL WINAPI SetCommMaskP(HANDLE hFile,DWORD dwEvtMask, BOOL bUseSocket)
       
   373 //
       
   374 // Specifies a set of events to be monitored for a communications device: protected against
       
   375 // this operation being cancelled by another thread
       
   376 //
       
   377 	{
       
   378 	if(bUseSocket)
       
   379         return TRUE;
       
   380 
       
   381 	DWORD err,res,res1;
       
   382 	COMSTAT s;
       
   383 	BOOL result;
       
   384 
       
   385 	result=FALSE;
       
   386 	do
       
   387 		{
       
   388 		ClearCommError(hFile,&err,&s);
       
   389 		if((res1=SetCommMask(hFile,dwEvtMask))==FALSE)
       
   390 			res=GetLastError();
       
   391 		else
       
   392 			{
       
   393 			result=TRUE;
       
   394 			break;
       
   395 			}
       
   396 		}
       
   397 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   398 	return(result);
       
   399 	}
       
   400 
       
   401 BOOL WINAPI WriteFileP(HANDLE hFile,LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped)
       
   402 //
       
   403 // Writes data to device pointed by hFile: protected against
       
   404 // this operation being cancelled by another thread
       
   405 //
       
   406 	{
       
   407 	DWORD err,res,res1;
       
   408 	COMSTAT s;
       
   409 	BOOL result;
       
   410 
       
   411 	result=FALSE;
       
   412 	do
       
   413 		{
       
   414 		ClearCommError(hFile,&err,&s);
       
   415 		if((res1=WriteFile(hFile,lpBuffer,nNumberOfBytesToWrite,lpNumberOfBytesWritten,lpOverlapped))==FALSE)
       
   416 			res=GetLastError();
       
   417 		else
       
   418 			{
       
   419 			result=TRUE;
       
   420 			break;
       
   421 			}
       
   422 		}
       
   423 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   424 	return(result);
       
   425 	}
       
   426 
       
   427 BOOL WINAPI ReadFileP(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped)
       
   428 //
       
   429 // Writes data to device pointed by hFile: protected against
       
   430 // this operation being cancelled by another thread
       
   431 //
       
   432 	{
       
   433 	DWORD err,res,res1;
       
   434 	COMSTAT s;
       
   435 	BOOL result;
       
   436 
       
   437 	result=FALSE;
       
   438 	do
       
   439 		{
       
   440 		ClearCommError(hFile,&err,&s);
       
   441 		if((res1=ReadFile(hFile,lpBuffer,nNumberOfBytesToRead,lpNumberOfBytesRead,lpOverlapped))==FALSE)
       
   442 			res=GetLastError();
       
   443 		else
       
   444 			{
       
   445 			result=TRUE;
       
   446 			break;
       
   447 			}
       
   448 		}
       
   449 	while((res1==FALSE) && (res==ERROR_OPERATION_ABORTED));
       
   450 	return(result);
       
   451 	}
       
   452 
       
   453 DDriverComm::DDriverComm()
       
   454 //
       
   455 // Constructor
       
   456 //
       
   457 	{
       
   458 
       
   459 #if defined (__COM_ONE_ONLY__)
       
   460 	iUnitsMask=0x1; // Support units 0
       
   461 #elif defined (__COM_TWO_ONLY__)
       
   462 	iUnitsMask=0x2; // Support units 1
       
   463 #else
       
   464 	iUnitsMask=0x3ff; // Support units 0 to 9
       
   465 #endif
       
   466 
       
   467 	iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
       
   468 	}
       
   469 
       
   470 TInt DDriverComm::Install()
       
   471 //
       
   472 // Install the device driver.
       
   473 //
       
   474 	{
       
   475 #if defined (__COM_ONE_ONLY__)
       
   476 	TPtrC buf=_L("Comm.Wins1");
       
   477 	return(SetName(&buf));
       
   478 #elif defined (__COM_TWO_ONLY__)
       
   479 	TPtrC buf=_L("Comm.Wins2");
       
   480 	return(SetName(&buf));
       
   481 #else
       
   482 	TPtrC buf=_L("Comm.Wins");
       
   483 	return(SetName(&buf));
       
   484 #endif
       
   485 	}
       
   486 
       
   487 TInt DDriverComm::Remove()
       
   488 //
       
   489 // Remove the device driver.
       
   490 //
       
   491 	{
       
   492 	return(KErrNone);
       
   493 	}
       
   494 
       
   495 void GetWinsCommsCaps(TDes8 &aCaps)
       
   496 	{
       
   497 
       
   498 	TCommCaps2 capsBuf;
       
   499 	TCommCapsV02 &c=capsBuf();
       
   500 //
       
   501 // All rates except 50,2000, 3600 and special
       
   502 //
       
   503 	c.iRate=KCapsBps75|KCapsBps110|KCapsBps134|KCapsBps150|KCapsBps300|KCapsBps600|KCapsBps1200|KCapsBps1800|KCapsBps2400|KCapsBps4800|KCapsBps7200|KCapsBps9600|KCapsBps19200|KCapsBps38400|KCapsBps57600|KCapsBps115200;
       
   504 
       
   505 	c.iDataBits=0xf; // All data sizes
       
   506 	c.iStopBits=0x3; // 1 and 2 stop bits
       
   507 	c.iParity=0x7; // None, Even and Odd
       
   508 	c.iHandshake=0x1ff; // All handshakes
       
   509 	c.iSignals=0x3f; // All signals
       
   510 	c.iSIR=0;//No Ir
       
   511 	c.iNotificationCaps=KNotifySignalsChangeSupported|KNotifyDataAvailableSupported;
       
   512 	c.iRoleCaps=0;
       
   513 	c.iFlowControlCaps=0;
       
   514 	aCaps.FillZ(aCaps.MaxLength());
       
   515 	aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
       
   516 	}
       
   517 
       
   518 void DDriverComm::GetCaps(TDes8 &aDes) const
       
   519 //
       
   520 // Return the drivers capabilities.
       
   521 //
       
   522 	{
       
   523 
       
   524 	GetWinsCommsCaps(aDes);
       
   525 	}
       
   526 
       
   527 CBase *DDriverComm::CreateL(TInt aUnit,const TDesC *anInfo,const TVersion &aVer)
       
   528 //
       
   529 // Create a channel on the device.
       
   530 //
       
   531 	{
       
   532 
       
   533 	if (!User::QueryVersionSupported(iVersion,aVer))
       
   534 		User::Leave(KErrNotSupported);
       
   535 	DCommWins *pD=new(ELeave) DCommWins;
       
   536 	TInt ret=pD->DoCreate(aUnit,anInfo);
       
   537 	if (ret!=KErrNone)
       
   538 		{
       
   539 		delete pD;
       
   540 		User::Leave(ret);
       
   541 		}
       
   542 	return(pD);
       
   543 	}
       
   544 
       
   545 
       
   546 
       
   547 void DCommWins::DoTransmit(TInt aByteCount)
       
   548 //
       
   549 // Called from write completion routine
       
   550 //
       
   551 	{
       
   552 
       
   553 	if(aByteCount==0)
       
   554 		{
       
   555 		DWORD err,res;
       
   556 		COMSTAT s;
       
   557 		if (!UseSocket() && ClearCommError(iCommPort,&err,&s)==FALSE)
       
   558 			res=GetLastError();
       
   559 		}
       
   560 	__ASSERT_ALWAYS(iNumOutChars-aByteCount<=KWriteBufSize,Panic(EWriteEarlyCompletion));
       
   561 #if defined (_LOG_WRITES)
       
   562 		TBuf<0x40> buf;
       
   563 		DWORD dummy;
       
   564 		buf.Format(_L("write complete %d\r\n"),aByteCount);
       
   565 		WriteFile(iLogFile,buf.PtrZ(),buf.Length(),&dummy,NULL);
       
   566 #endif
       
   567 //
       
   568 	iNumOutChars-=aByteCount;
       
   569 	if (iCommand==EStop)
       
   570 		return;
       
   571 	if (iSkipTransmitIsrNextTime)
       
   572 		{
       
   573 		iSkipTransmitIsrNextTime=EFalse;
       
   574 		}
       
   575 	else
       
   576 		{
       
   577 		while (iNumOutChars<KWriteBufSize)
       
   578 			{
       
   579 			iSkipTransmitIsrNextTime=!DoTransmitIsr(iNumOutChars);
       
   580 			if (iSkipTransmitIsrNextTime)
       
   581 				break;
       
   582 			iNumOutChars++;
       
   583 			}
       
   584 		}
       
   585 	if(iNumOutChars>0)
       
   586 		{
       
   587 //		WriteFileEx(iCommPort,iOutBuf,iNumOutChars,&iWriteOverLapped,WriteComplete);
       
   588 		WriteFile(iCommPort,iOutBuf,iNumOutChars, &dummyLen, &iWriteOverLapped);
       
   589 		iWritePending=ETrue;
       
   590 
       
   591 #if defined (_LOG_OUTPUT)
       
   592 		DWORD dummy;
       
   593 		WriteFile(iWritesHandle,iOutBuf,iNumOutChars,&dummy,NULL);
       
   594 #endif
       
   595 #if defined (_LOG_WRITES)
       
   596 		buf.Format(_L("Writing %d\r\n"),iNumOutChars);
       
   597 		WriteFile(iLogFile,buf.PtrZ(),buf.Length(),&dummy,NULL);
       
   598 #endif
       
   599 
       
   600 		}
       
   601 	else
       
   602 		iWritePending=EFalse;
       
   603 	}
       
   604 
       
   605 /*
       
   606 For reference only:
       
   607 Returned from 2nd param to ClearCommError (err below)
       
   608 #define CE_RXOVER           0x0001  // Receive Queue overflow
       
   609 #define CE_OVERRUN          0x0002  // Receive Overrun Error
       
   610 #define CE_RXPARITY         0x0004  // Receive Parity Error
       
   611 #define CE_FRAME            0x0008  // Receive Framing error
       
   612 #define CE_BREAK            0x0010  // Break Detected
       
   613 #define CE_TXFULL           0x0100  // TX Queue is full
       
   614 #define CE_PTO              0x0200  // LPTx Timeout
       
   615 #define CE_IOE              0x0400  // LPTx I/O Error
       
   616 #define CE_DNS              0x0800  // LPTx Device not selected
       
   617 #define CE_OOP              0x1000  // LPTx Out-Of-Paper
       
   618 #define CE_MODE             0x8000  // Requested mode unsupported
       
   619 
       
   620 #define IE_BADID            (-1)    // Invalid or unsupported id
       
   621 #define IE_OPEN             (-2)    // Device Already Open
       
   622 #define IE_NOPEN            (-3)    // Device Not Open
       
   623 #define IE_MEMORY           (-4)    // Unable to allocate queues
       
   624 #define IE_DEFAULT          (-5)    // Error in default parameters
       
   625 #define IE_HARDWARE         (-10)   // Hardware Not Present
       
   626 #define IE_BYTESIZE         (-11)   // Illegal Byte Size
       
   627 #define IE_BAUDRATE         (-12)   // Unsupported BaudRate
       
   628 */
       
   629 
       
   630 //void DCommWins::DoReceive(TInt aByteCount)
       
   631 //
       
   632 // Called from read completion routine 
       
   633 //
       
   634 //	{
       
   635 //	if(aByteCount==0)
       
   636 //		{
       
   637 //		DWORD err=0,res;
       
   638 //		COMSTAT s;
       
   639 //		if (iCommPort && ClearCommError(iCommPort,&err,&s)==FALSE)
       
   640 //			res=GetLastError();
       
   641 //		if(err)
       
   642 //			{
       
   643 //			Panic(ELineErrorNotReported);
       
   644 //			}
       
   645 //		}
       
   646 //	TInt i=0;
       
   647 //	
       
   648 //	while(i<aByteCount)
       
   649 //		{
       
   650 //		DoReceiveIsr(iInBuf[i]);
       
   651 //		i++;
       
   652 //		}
       
   653 //#if defined (_LOG_OUTPUT)
       
   654 //		DWORD dummy;
       
   655 //		WriteFile(iReadsHandle,iInBuf,aByteCount,&dummy,NULL);
       
   656 //#endif 
       
   657 //	if(iStopping)
       
   658 //		{
       
   659 //		iStopping=EFalse;
       
   660 //		return;
       
   661 //		}
       
   662 //
       
   663 //	if (!ReadFileEx(iCommPort,iInBuf,KReadBufSize,&iReadOverLapped,ReadComplete))
       
   664 //		{
       
   665 //		TInt r=GetLastError();
       
   666 //		Panic(EWindowsUnexpectedError);
       
   667 //		}
       
   668 //	}
       
   669 
       
   670 void DCommWins::RunCommThread(TDriverCommand aCommand)
       
   671 //
       
   672 // Wake up the comms thread
       
   673 //
       
   674 	{
       
   675     _Log2("# DCommWins::RunCommThread, command=%d\n", aCommand);
       
   676 
       
   677 	__ASSERT_DEBUG(aCommand!=EInvalidCommand,Panic(EUnknownCommand));
       
   678 	iCommand=aCommand;
       
   679 //
       
   680 // Are we about to go re-entrant?
       
   681 //
       
   682 	if(GetCurrentThreadId()==iThreadID)
       
   683 		{
       
   684 		DriverCommand(aCommand);
       
   685 		WaitForSingleObject(iDriverThreadSem,INFINITE);
       
   686 		}
       
   687 	else
       
   688 		{
       
   689 		Sleep(0); // Possible deadlock solution - see MSDN Knowledge Base Article Q173260
       
   690 		
       
   691 		if (ReleaseSemaphore(iCommThreadSem,1,NULL)==FALSE)
       
   692 			{
       
   693 			DWORD ret=GetLastError();
       
   694 			ret=ret;
       
   695 			Panic(EWindowsUnexpectedError);
       
   696 			}
       
   697 		WaitForSingleObject(iDriverThreadSem,INFINITE);
       
   698 		}
       
   699 	}
       
   700 
       
   701 inline void DCommWins::SignalDriverThread()
       
   702 //
       
   703 // Wake up the comms thread
       
   704 //
       
   705 	{
       
   706 	_Log("# DCommWins::SignalDriverThread(), release iDriverThreadSem\n");
       
   707 	Sleep(0); // Possible deadlock solution - see MSDN Knowledge Base Article Q173260
       
   708 	if (ReleaseSemaphore(iDriverThreadSem,1,NULL)==FALSE)
       
   709 		{
       
   710 		DWORD ret=GetLastError();
       
   711 		ret=ret;
       
   712 		Panic(EWindowsUnexpectedError);
       
   713 		}
       
   714 	}
       
   715 
       
   716 
       
   717 
       
   718 //
       
   719 #pragma warning( disable : 4705 )	// statement has no effect
       
   720 DCommWins::DCommWins()
       
   721 //
       
   722 // Constructor
       
   723 //
       
   724 	{
       
   725 //	iRunning=EFalse;
       
   726 //	iCommand=ESetBreak;
       
   727 //	iSignals=0;
       
   728 //	iInBuf=0;
       
   729 //	iOutBuf=0;
       
   730 //	iThread=NULL;
       
   731 //	iCommThreadSem=NULL;
       
   732 //	iCommPort=NULL;
       
   733 //	iThreadID=0;
       
   734 	iWritePending = EFalse;
       
   735 	iReadPending  = EFalse;
       
   736 
       
   737 	Mem::FillZ(&iReadOverLapped,sizeof(OVERLAPPED));
       
   738 	Mem::FillZ(&iWriteOverLapped,sizeof(OVERLAPPED));
       
   739 	__DECLARE_NAME(_S("DCommWins"));
       
   740 #ifdef _DEBUG_DEVCOMM
       
   741 	iTxIntCount = 0;
       
   742 	iRxIntCount = 0;
       
   743 	iTxErrCount = 0;
       
   744 	iRxErrCount = 0;
       
   745 #endif
       
   746 	iIntRefCount = 0;
       
   747 	iSocket = INVALID_SOCKET;
       
   748 
       
   749     _Log("# ------------------------------------------------\n");
       
   750 	_Log("# DCommWins::DCommWins()\n");
       
   751     
       
   752 	}
       
   753 #pragma warning( default : 4705 )
       
   754 
       
   755 /**
       
   756 *   Read serial port mapping from ini file (dComm.ini usually)
       
   757 *
       
   758 *   @param  aFileName   ini full file path descriptor
       
   759 *   @param  aPortNum    serial port number (e.g. 0 for COMM::0)
       
   760 *   @param  aPortMapStr descriptor for returned port mapping (e.g. "10.35.2.53:110)
       
   761 *   
       
   762 *   @return ETrue if the parameter found and everything is OK.
       
   763 */
       
   764 TBool DCommWins::GetComPortMapping(LPCSTR aFileName, TInt aPortNum, TDes8& aPortMapStr)
       
   765 {
       
   766     TBool   bRes = ETrue;
       
   767 	TInt    fileSize;
       
   768     LPVOID	pFileData=NULL;
       
   769 
       
   770     //--  open dcomm.ini file
       
   771     HANDLE hFile=CreateFileA(aFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       
   772 	if (!hFile || hFile == INVALID_HANDLE_VALUE)
       
   773 	{//-- can't open file, maybe it is just not present
       
   774 		bRes = EFalse;
       
   775 		goto CleanUp;
       
   776 	}
       
   777 
       
   778     //-- get file size
       
   779     fileSize = GetFileSize(hFile, NULL);
       
   780     if (fileSize == INVALID_FILE_SIZE || !fileSize)
       
   781     {//-- something is wrong with file size
       
   782 		bRes = EFalse;
       
   783 		goto CleanUp;
       
   784     }
       
   785     
       
   786     //-- allocate data for buffer 
       
   787 	// fileSize+1 to ensure zero-termination of file, since Windows98 might use
       
   788 	// a dirty page of memory.  VirtualAlloc initializes memory to zero
       
   789     pFileData = VirtualAlloc(NULL, fileSize+1, MEM_COMMIT, PAGE_READWRITE);
       
   790     if(! pFileData)
       
   791     {//-- something is wrong with memory allocation
       
   792 		bRes = EFalse;
       
   793 		goto CleanUp;
       
   794     }
       
   795 
       
   796     //-- read whole file into buffer
       
   797     DWORD bytesRead;    
       
   798 
       
   799     if (! ReadFile(hFile, pFileData, fileSize, &bytesRead, NULL))
       
   800         bRes = EFalse;
       
   801     else
       
   802     {//-- parse file line by line looking for the appropriate port 
       
   803 	    LPSTR linePtr=(LPSTR)pFileData;
       
   804 		_LIT8(KCommToken, "COMM::");
       
   805         bRes = EFalse;
       
   806 
       
   807 
       
   808         while(linePtr && *linePtr)
       
   809 		{
       
   810 			//-- skip spaces at the beginning of the current line
       
   811             while (*linePtr && (*linePtr == '\r' || *linePtr == '\n' || *linePtr == ' ' || *linePtr =='\t'))
       
   812 			{
       
   813 				++linePtr;
       
   814 				--bytesRead;
       
   815 			}
       
   816 
       
   817             //-- find the end of the line
       
   818 			TPtrC8 line((unsigned char*)linePtr, bytesRead);
       
   819             TInt len;
       
   820 			for (len = 0; len < line.Length() && (line[len] != '\r' && line[len] != '\n'); ++len)
       
   821 				;
       
   822 
       
   823 			line.Set(line.Left(len));
       
   824 			bytesRead -= line.Length();
       
   825 			linePtr += line.Length();
       
   826 
       
   827             //-- parse the line
       
   828 			TLex8   lex(line);
       
   829 			TPtrC8  commname (lex.NextToken());
       
   830 			if(commname.Length() <= KCommToken().Size())
       
   831 				continue; // not enough chars
       
   832 			if(commname[0] == '#')
       
   833 				continue; // comment line
       
   834 
       
   835 			if (commname.Left(KCommToken().Size()).CompareF(KCommToken) != 0)
       
   836 				continue; // unreconised option. Should log?!?
       
   837     
       
   838             //-- extract comm port number
       
   839     		TLex8 numLex(commname.Mid(KCommToken().Size()));
       
   840 			TInt commNum;
       
   841 			if(numLex.Val(commNum) != KErrNone || commNum != aPortNum)
       
   842 				continue;
       
   843 
       
   844 			//-- extract comm port mapping substring
       
   845             lex.SkipSpace();
       
   846             aPortMapStr.Copy(lex.Remainder());
       
   847             aPortMapStr.PtrZ();
       
   848             bRes = ETrue;
       
   849 
       
   850             break;
       
   851         }//while(linePtr && *linePtr)
       
   852     }
       
   853 
       
   854     
       
   855   CleanUp:
       
   856 
       
   857     CloseHandle(hFile);
       
   858     VirtualFree(pFileData, 0, MEM_RELEASE);
       
   859 
       
   860     return bRes;
       
   861 }
       
   862 
       
   863 
       
   864 TInt DCommWins::DoCreate(TInt aUnit,const TDesC * /*anInfo*/)
       
   865 //
       
   866 // Create the comms driver.
       
   867 //
       
   868 	{
       
   869     _Log("# DCommWins::DoCreate()\n");
       
   870 
       
   871 	InitializeCriticalSection(&iCriticalSection);
       
   872 
       
   873 #if defined (__COM_ONE_ONLY__)
       
   874 	if (aUnit!=0)
       
   875 		return KErrNotSupported;
       
   876 #elif defined (__COM_TWO_ONLY__)
       
   877 	if (aUnit!=1)
       
   878 		return KErrNotSupported;
       
   879 #endif
       
   880 
       
   881     //-- get full path for the DComm.ini configuration file
       
   882 	TBuf8<MAX_PATH> iniFileName;
       
   883     iniFileName.Copy(EmulatorDataPath());
       
   884 	iniFileName.Append(_L8("DComm.ini"));
       
   885     LPCSTR  pszIniFle = (LPCSTR)iniFileName.PtrZ();
       
   886 
       
   887     //-- get com port mapping string
       
   888 	TBuf8<MAX_PATH> strPortMapping;
       
   889     TBool bFound = GetComPortMapping(pszIniFle, aUnit, strPortMapping);
       
   890 
       
   891     if(bFound)
       
   892     {//-- comm port mapping string is found in cofiguration file, we are dealing with sockets now
       
   893     
       
   894         //-- try to locate port number after colon
       
   895         TInt nColonPos = strPortMapping.Locate(':');
       
   896         if(nColonPos != KErrNotFound)
       
   897         {// Found a ':' ... must be a TCP name & port no.
       
   898             TPtrC8 hostAddr(strPortMapping.Left(nColonPos));
       
   899 
       
   900             ((char*)strPortMapping.Ptr())[nColonPos] = 0; // replace : with a null term
       
   901 
       
   902 		    TLex8 portLex (strPortMapping.Mid(nColonPos + 1));
       
   903 		    TInt port = 0;
       
   904 		    portLex.Val(port);
       
   905 
       
   906 
       
   907             //-- initialize socket
       
   908 
       
   909 		    WORD    wVersionRequested;
       
   910 		    WSADATA wsaData;
       
   911 		    int err; 
       
   912 		    wVersionRequested = MAKEWORD(2, 0); 
       
   913 		    err = WSAStartup(wVersionRequested, &wsaData);
       
   914 		    if (err != 0)
       
   915                 return MapWinError(WSAGetLastError());
       
   916 
       
   917 		    iSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
       
   918 		    if(iSocket == INVALID_SOCKET)
       
   919                 return MapWinError(WSAGetLastError());
       
   920             
       
   921             _Log2("# DCommWins: created socket id: %d\n", iSocket );
       
   922 		    
       
   923             sockaddr_in sin;
       
   924 
       
   925 		    char* devname = (char*)(strPortMapping.Ptr());
       
   926 		    u_long nRemoteAddr = inet_addr(devname);
       
   927 		    
       
   928             if (nRemoteAddr != INADDR_NONE)
       
   929 			{
       
   930 			    sin.sin_addr.s_addr = nRemoteAddr;
       
   931 			}
       
   932 		    else
       
   933 			{
       
   934 			    struct hostent FAR * hostaddr = gethostbyname (devname);
       
   935 			    if(hostaddr == NULL)
       
   936 				    return MapWinError(WSAGetLastError());
       
   937 			    
       
   938                 sin.sin_addr.s_addr = *((u_long*)hostaddr->h_addr_list[0]);
       
   939 			}
       
   940 
       
   941 		    sin.sin_family = AF_INET;
       
   942 		    sin.sin_port = htons(TUint16(port));
       
   943 
       
   944 		    err = WSAConnect(iSocket, (sockaddr*)&sin, sizeof(sin), 0, 0, 0, 0);
       
   945 		    if(err)
       
   946                 return MapWinError(WSAGetLastError());
       
   947 
       
   948             _Log2("# DCommWins: socket connected to the port: %d\n", port);
       
   949 
       
   950 		    iCommPort = (void*)iSocket;
       
   951             
       
   952         }
       
   953     }
       
   954    
       
   955                         
       
   956     //-----------------------------------------
       
   957 
       
   958     if(! UseSocket())
       
   959     {//-- use PC serial port as usual
       
   960         //-- open Windows serial port
       
   961 	    TBuf8<0x10> n;
       
   962 	    n.Format(_L8("\\\\.\\COM%d"),aUnit+1);
       
   963 	    iCommPort=CreateFileA((LPCSTR)n.PtrZ(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
       
   964 	    if (iCommPort==INVALID_HANDLE_VALUE)	
       
   965 		    {	
       
   966 	    //	Reused code from MapWinError() rather than adding an extra case 
       
   967 	    //	to MapWinError() because mapping KErrNotSupported to the returned
       
   968 	    //	FILE_NOT_FOUND is non-intuitive and special to this case only
       
   969 		    DWORD winErr=GetLastError();
       
   970 		    switch (winErr)
       
   971 			    {
       
   972 			    case ERROR_INVALID_USER_BUFFER:
       
   973 			    case ERROR_NOT_ENOUGH_MEMORY:
       
   974 			    case ERROR_INSUFFICIENT_BUFFER:
       
   975 				    return(KErrNoMemory);
       
   976 			    case ERROR_ACCESS_DENIED:
       
   977 				    return(KErrAccessDenied);
       
   978 			    case ERROR_FILE_NOT_FOUND:		//	Reflects value returned by
       
   979 				    return(KErrNotSupported);	//	corresponding MARM Pdd  
       
   980 			    case ERROR_NOT_SUPPORTED:
       
   981 				    return(KErrNotSupported);
       
   982 			    default:
       
   983 				    return(KErrGeneral);
       
   984 			    }
       
   985 		    }
       
   986 	    
       
   987 	    DCB dcb;
       
   988 	    if (!GetCommStateP(iCommPort,&dcb,UseSocket()))
       
   989 		    return MapWinError();
       
   990 
       
   991 	    dcb.fDtrControl=DTR_CONTROL_DISABLE;
       
   992 	    dcb.fRtsControl=RTS_CONTROL_DISABLE;
       
   993 	    dcb.fAbortOnError=TRUE;	// Tell me about your parity problems luvvy
       
   994 	    dcb.fParity=TRUE;
       
   995 	    dcb.fBinary=TRUE;
       
   996 	    dcb.fOutxCtsFlow=FALSE;
       
   997 	    dcb.fOutxDsrFlow=FALSE;  
       
   998 	    dcb.fDsrSensitivity=FALSE;
       
   999 	    dcb.fTXContinueOnXoff=TRUE;
       
  1000 	    dcb.fOutX=FALSE;
       
  1001 	    dcb.fInX=FALSE;
       
  1002 	    dcb.fErrorChar=FALSE;
       
  1003 	    dcb.fNull=FALSE;
       
  1004     //
       
  1005     //	dcb.ByteSize;		// number of bits/byte, 4-8
       
  1006     //	dcb.Parity;			// 0-4=no,odd,even,mark,space
       
  1007     //	dcb.StopBits;		// 0,1,2 = 1, 1.5, 2
       
  1008     //	dcb.XonChar;		// Tx and Rx XON character
       
  1009     //	dcb.XoffChar;		// Tx and Rx XOFF character
       
  1010     //	dcb.ErrorChar;		// error replacement character
       
  1011     //	dcb.EofChar;		// end of input character
       
  1012     //	dcb.EvtChar;
       
  1013     //
       
  1014 	    if (!SetCommStateP(iCommPort,&dcb, UseSocket()))
       
  1015 		    return MapWinError();
       
  1016 
       
  1017 	    EscapeCommFunctionP(iCommPort,0,UseSocket());
       
  1018 
       
  1019     //
       
  1020     // Could add EV_RXCHAR|EV_RXFLAG|EV_TXEMPTY to the following
       
  1021     // mask too and get all chars through the call to WaitForAnyObject
       
  1022     // rather then the completion routine followed by a manual read
       
  1023     //
       
  1024 	    if (!SetCommMaskP(iCommPort,EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR,UseSocket()))
       
  1025 		    return MapWinError();
       
  1026 
       
  1027 	    if(!SetupComm(iCommPort,KWinNTReadBufSize,KWinNTWriteBufSize))
       
  1028 		    return MapWinError();
       
  1029 
       
  1030     //
       
  1031     // The serial port seems to open with the error condition set
       
  1032     //
       
  1033 
       
  1034 	    DWORD err,res;
       
  1035 	    COMSTAT s;
       
  1036 	    if (ClearCommError(iCommPort,&err,&s)==FALSE)
       
  1037 		    res=GetLastError();
       
  1038     }//if(! UseSocket())
       
  1039 
       
  1040 	if ((iCommThreadSem=CreateSemaphoreA(NULL,0,0x7fffffff,NULL))==NULL)
       
  1041 	    return MapWinError();
       
  1042     
       
  1043     if ((iDriverThreadSem=CreateSemaphoreA(NULL,0,0x7fffffff,NULL))==NULL)
       
  1044 	    return MapWinError();
       
  1045 
       
  1046     if ((iWaitableTimer=CreateWaitableTimer(NULL, FALSE, NULL))==NULL)
       
  1047         return MapWinError();
       
  1048 
       
  1049 	if ((iThread=CreateThread(NULL,0x4000,(LPTHREAD_START_ROUTINE)commThread,(void *)this,CREATE_SUSPENDED,&iThreadID))==NULL)
       
  1050 	    return MapWinError();
       
  1051 
       
  1052     
       
  1053 
       
  1054 #if defined (_LOG_WRITES)
       
  1055 	TBuf8<0x40> logName;
       
  1056 	logName.Format(_L8("C:\\tmp\\log%d.tmp"),iUnit);
       
  1057 	DWORD fileErr;
       
  1058 	if((iLogFile=CreateFileA((char *)logName.PtrZ(),GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))==INVALID_HANDLE_VALUE)
       
  1059 		fileErr=GetLastError();
       
  1060 #endif
       
  1061 #if defined (_LOG_OUTPUT)
       
  1062 	TBuf8<0x40> fileName;
       
  1063 	DWORD fileErr;
       
  1064 	fileName.Format(_L8("C:\\tmp\\Writes%d.tmp"),iUnit);
       
  1065 	if((iWritesHandle=CreateFileA((char *)fileName.PtrZ(),GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))==INVALID_HANDLE_VALUE)
       
  1066 		fileErr=GetLastError();
       
  1067 	fileName.Format(_L8("C:\\tmp\\Reads%d.tmp"),iUnit);
       
  1068 	if((iReadsHandle=CreateFileA((char *)fileName.PtrZ(),GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))==INVALID_HANDLE_VALUE)
       
  1069 		fileErr=GetLastError();
       
  1070 #endif
       
  1071 	
       
  1072 	SetThreadPriority(iThread,THREAD_PRIORITY_HIGHEST);
       
  1073 	return(KErrNone);
       
  1074 	}
       
  1075 
       
  1076 DCommWins::~DCommWins()
       
  1077 //
       
  1078 // Destruct
       
  1079 //
       
  1080 	{
       
  1081 	if (iThread)
       
  1082 		{
       
  1083 		if (! iRunning)
       
  1084 			{
       
  1085 			__ASSERT_ALWAYS(
       
  1086 				ResumeThread(iThread) != 0xffffffff,
       
  1087 				User::Panic(_L("Wins comm error"), 0));
       
  1088 			}
       
  1089 
       
  1090 		iRunning=ETrue;
       
  1091 		RunCommThread(EDie);
       
  1092 		}
       
  1093 
       
  1094 	if(UseSocket())
       
  1095 	{
       
  1096 	    closesocket(iSocket);
       
  1097 	    WSACleanup();
       
  1098 		iCommPort = (HANDLE) NULL;
       
  1099 		iSocket   = NULL;
       
  1100 	}
       
  1101 
       
  1102 	if (iCommPort)
       
  1103 		CloseHandle(iCommPort);
       
  1104 
       
  1105 	if (iDriverThreadSem)
       
  1106 		CloseHandle(iDriverThreadSem);
       
  1107 
       
  1108 	if (iCommThreadSem)
       
  1109 		CloseHandle(iCommThreadSem);
       
  1110 
       
  1111     if (iWaitableTimer)
       
  1112         CloseHandle(iWaitableTimer);
       
  1113 
       
  1114 	if (iReadOverLapped.hEvent)
       
  1115 		CloseHandle(iReadOverLapped.hEvent);
       
  1116 
       
  1117 	if (iWriteOverLapped.hEvent)
       
  1118 		CloseHandle(iWriteOverLapped.hEvent);
       
  1119 
       
  1120 	if (iSignalOverLapped.hEvent)
       
  1121 		CloseHandle(iSignalOverLapped.hEvent);
       
  1122 
       
  1123 	if (iThread)
       
  1124 		CloseHandle(iThread);
       
  1125 
       
  1126 	DeleteCriticalSection(&iCriticalSection);
       
  1127 	}
       
  1128 
       
  1129 TInt DCommWins::Start()
       
  1130 //
       
  1131 // Start receiving characters
       
  1132 //
       
  1133 	{
       
  1134 
       
  1135 	__ASSERT_ALWAYS(ResumeThread(iThread)!=0xffffffff,User::Panic(_L("Wins comm error"),0));
       
  1136 //	if (ResumeThread(iThread)==0xffffffff)
       
  1137 //		return(MapWinError());
       
  1138 	iRunning=ETrue;
       
  1139 	RunCommThread(EStart);
       
  1140 	return(KErrNone);
       
  1141 	}
       
  1142 
       
  1143 void DCommWins::Stop(TStopMode aMode)
       
  1144 //
       
  1145 // Stop receiving characters
       
  1146 //
       
  1147 	{
       
  1148 
       
  1149 	iSkipTransmitIsrNextTime=EFalse;
       
  1150 	RunCommThread((aMode==EStopEmergency) ? EStopNoDrain : EStop);
       
  1151 	SuspendThread(iThread);
       
  1152 	iRunning=EFalse;
       
  1153 	iNumInChars=iNumOutChars=0;
       
  1154 	}
       
  1155 
       
  1156 void DCommWins::Break(TBool aState)
       
  1157 //
       
  1158 // Assert a break signal
       
  1159 //
       
  1160 	{
       
  1161 
       
  1162 	if (aState)
       
  1163 		RunCommThread(ESetBreak);
       
  1164 	else
       
  1165 		RunCommThread(EClearBreak);
       
  1166 	}
       
  1167 
       
  1168 void DCommWins::EnableTransmit()
       
  1169 //
       
  1170 // Start transmitting characters
       
  1171 //
       
  1172 	{
       
  1173 	RunCommThread(ETransmit);
       
  1174 	}
       
  1175 
       
  1176 
       
  1177 TUint DCommWins::Signals() const
       
  1178 //
       
  1179 // Return the current signals state
       
  1180 //
       
  1181 	{
       
  1182 	if(UseSocket()) 
       
  1183 		{
       
  1184 		return MS_CTS_ON|MS_DSR_ON|KSignalCTS|KSignalDSR;
       
  1185 		}
       
  1186 	
       
  1187     ULONG signals=0;
       
  1188 	GetCommModemStatusP(iCommPort,&signals, UseSocket());
       
  1189 	TUint status=0;
       
  1190 	if (signals&MS_CTS_ON)
       
  1191 		status|=KSignalCTS;
       
  1192 	if (signals&MS_DSR_ON)
       
  1193 		status|=KSignalDSR;
       
  1194 	if (signals&MS_RING_ON)
       
  1195 		status|=KSignalRNG;
       
  1196 	if (signals&MS_RLSD_ON)
       
  1197 		status|=KSignalDCD;
       
  1198 	CONST_CAST(DCommWins*,this)->iSkipTransmitIsrNextTime=EFalse;
       
  1199 	return(status|iSignals);
       
  1200 	}
       
  1201 
       
  1202 void DCommWins::SetSignals(TUint aSetMask,TUint aClearMask)
       
  1203 //
       
  1204 // Set the state of the output signals
       
  1205 //
       
  1206 	{
       
  1207 
       
  1208     if (aSetMask&KSignalRTS)
       
  1209 		{
       
  1210 		iSignals|=KSignalRTS;
       
  1211 		EscapeCommFunctionP(iCommPort,SETRTS, UseSocket());
       
  1212 		}
       
  1213 	if (aSetMask&KSignalDTR)
       
  1214 		{
       
  1215 		iSignals|=KSignalDTR;
       
  1216 		EscapeCommFunctionP(iCommPort,SETDTR, UseSocket());
       
  1217 		}
       
  1218 	if (aClearMask&KSignalRTS)
       
  1219 		{
       
  1220 		iSignals&=(~KSignalRTS);
       
  1221 		EscapeCommFunctionP(iCommPort,CLRRTS, UseSocket());
       
  1222 		}
       
  1223 	if (aClearMask&KSignalDTR)
       
  1224 		{
       
  1225 		iSignals&=(~KSignalDTR);
       
  1226 		EscapeCommFunctionP(iCommPort,CLRDTR, UseSocket());
       
  1227 		}
       
  1228         
       
  1229         _Log2("#~DCommWins::SetSignals, iSignals has become=0x%x\n", iSignals);
       
  1230 	}
       
  1231 
       
  1232 void DCommWins::CheckConfig(TCommConfigV01& /*aConfig*/)
       
  1233 	{
       
  1234 	// Do nothing
       
  1235 	}
       
  1236 
       
  1237 
       
  1238 TInt DCommWins::CompleteSlowOpen(DThread *aThread,TRequestStatus *aReqStat)
       
  1239 	{
       
  1240 	// Should never be called
       
  1241 	aThread->RequestComplete(aReqStat,KErrNone);
       
  1242 	return(KErrNone);
       
  1243 	}
       
  1244 
       
  1245 TInt DCommWins::Validate(const TCommConfigV01 &aConfig) const
       
  1246 //
       
  1247 // Confirm that aConfig is a valid configuration.
       
  1248 //
       
  1249 	{
       
  1250 
       
  1251 	if (aConfig.iSIREnable==ESIREnable)
       
  1252 		return KErrNotSupported;
       
  1253 
       
  1254 	if (aConfig.iRate&KCapsBpsSpecial)
       
  1255 		return(KErrNotSupported);
       
  1256 	switch (aConfig.iRate)
       
  1257 		{
       
  1258 	case EBps50:
       
  1259 	case EBps2000:
       
  1260 	case EBps3600:
       
  1261 		return(KErrNotSupported);
       
  1262 		};
       
  1263 	return(KErrNone);
       
  1264 	}
       
  1265 
       
  1266 void DCommWins::Configure(TCommConfigV01 &aConfig)
       
  1267 //
       
  1268 // Ask comm thread to set up the serial port
       
  1269 //
       
  1270 	{
       
  1271 
       
  1272 	iConfig=&aConfig;
       
  1273 	if (iRunning)
       
  1274 		{
       
  1275 		RunCommThread(EConfigure);
       
  1276 		}
       
  1277 	else
       
  1278 		{
       
  1279 //		iCommand=EConfigure;
       
  1280 		DoConfigure();
       
  1281 		}
       
  1282 	}
       
  1283 
       
  1284 void DCommWins::DoConfigure()
       
  1285 //
       
  1286 // Set up the serial port
       
  1287 //
       
  1288 	{
       
  1289 
       
  1290 
       
  1291 
       
  1292 	DCB dcb;
       
  1293 	if (!GetCommStateP(iCommPort,&dcb, UseSocket()))
       
  1294 		return;
       
  1295 
       
  1296     if(iRunning)
       
  1297         {
       
  1298         SetCommMaskP(iCommPort,EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR, UseSocket());
       
  1299         WaitForSingleObject(iSignalOverLapped.hEvent, INFINITE);
       
  1300         }
       
  1301 
       
  1302 //	
       
  1303 // Need only worry about the framing and speed.
       
  1304 //				   
       
  1305 	switch (iConfig->iRate)
       
  1306 		{
       
  1307 	case EBps75:
       
  1308 		dcb.BaudRate=75;
       
  1309 		break;
       
  1310 	case EBps110:
       
  1311 		dcb.BaudRate=110;
       
  1312 		break;
       
  1313 	case EBps134:
       
  1314 		dcb.BaudRate=134;
       
  1315 		break;
       
  1316 	case EBps150:
       
  1317 		dcb.BaudRate=150;
       
  1318 		break;
       
  1319 	case EBps300:
       
  1320 		dcb.BaudRate=300;
       
  1321 		break;
       
  1322 	case EBps600:
       
  1323 		dcb.BaudRate=600;
       
  1324 		break;
       
  1325 	case EBps1200:
       
  1326 		dcb.BaudRate=1200;
       
  1327 		break;
       
  1328 	case EBps1800:
       
  1329 		dcb.BaudRate=1800;
       
  1330 		break;
       
  1331 	case EBps2400:
       
  1332 		dcb.BaudRate=2400;
       
  1333 		break;
       
  1334 	case EBps4800:
       
  1335 		dcb.BaudRate=4800;
       
  1336 		break;
       
  1337 	case EBps7200:
       
  1338 		dcb.BaudRate=7200;
       
  1339 		break;
       
  1340 	case EBps9600:
       
  1341 		dcb.BaudRate=9600;
       
  1342 		break;
       
  1343 	case EBps19200:
       
  1344 		dcb.BaudRate=19200;
       
  1345 		break;
       
  1346 	case EBps38400:
       
  1347 		dcb.BaudRate=38400;
       
  1348 		break;
       
  1349 	case EBps57600:
       
  1350 		dcb.BaudRate=57600;
       
  1351 		break;
       
  1352 	case EBps115200:
       
  1353 		dcb.BaudRate=115200;
       
  1354 		break;
       
  1355 		}
       
  1356    
       
  1357    	switch(iConfig->iDataBits)
       
  1358 		{
       
  1359 	case EData5:
       
  1360 		dcb.ByteSize=5;
       
  1361 		break;
       
  1362 	case EData6:
       
  1363 		dcb.ByteSize=6;
       
  1364 		break;
       
  1365 	case EData7:
       
  1366 		dcb.ByteSize=7;
       
  1367 		break;
       
  1368 	case EData8:
       
  1369 		dcb.ByteSize=8;
       
  1370 		break;
       
  1371 		}
       
  1372 
       
  1373 	switch(iConfig->iStopBits)
       
  1374 		{
       
  1375 	case EStop1:
       
  1376 		dcb.StopBits=ONESTOPBIT;
       
  1377 		break;
       
  1378 	case EStop2:
       
  1379 		dcb.StopBits=TWOSTOPBITS;
       
  1380 		break;
       
  1381 		}
       
  1382 
       
  1383 	switch (iConfig->iParity)
       
  1384 		{
       
  1385 	case EParityNone:
       
  1386 		dcb.Parity=NOPARITY;
       
  1387 		break;
       
  1388 	case EParityEven:
       
  1389 		dcb.Parity=EVENPARITY;
       
  1390 		break;
       
  1391 	case EParityOdd:
       
  1392 		dcb.Parity=ODDPARITY;
       
  1393 		break;
       
  1394 		}
       
  1395 
       
  1396 	// make sure that SetCommState won't change the state of the Modem signals
       
  1397 	TUint prov=iSignals&KSignalRTS;
       
  1398 	if(prov)
       
  1399 		dcb.fRtsControl=RTS_CONTROL_ENABLE;
       
  1400 	else
       
  1401 		dcb.fRtsControl=RTS_CONTROL_DISABLE;
       
  1402 
       
  1403 	prov=iSignals&KSignalDTR;
       
  1404 	if(prov)
       
  1405 		dcb.fDtrControl=DTR_CONTROL_ENABLE;
       
  1406 	else
       
  1407 		dcb.fDtrControl=DTR_CONTROL_DISABLE;
       
  1408 		
       
  1409 	TInt error_r=KErrNone;
       
  1410 	if(!SetCommStateP(iCommPort,&dcb, UseSocket()))
       
  1411 		error_r=GetLastError();
       
  1412 //	SetSignals(iSignals, ~iSignals);	// For NT 4 -> redundant (see above comments on preserving Modem control signals)
       
  1413 //
       
  1414 // Clear any error we may have caused
       
  1415 //
       
  1416 	DWORD err,res;
       
  1417 	COMSTAT s;
       
  1418 	if (ClearCommError(iCommPort,&err,&s)==FALSE)
       
  1419 		res=GetLastError();
       
  1420 
       
  1421     if(iRunning)
       
  1422         {
       
  1423         if(!WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped))
       
  1424             {
       
  1425             TInt i=50;
       
  1426             while(--i)
       
  1427                 {
       
  1428                 if(WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped))
       
  1429                     break;
       
  1430                 }
       
  1431             }
       
  1432         }
       
  1433 	}
       
  1434 
       
  1435 void DCommWins::Caps(TDes8 &aCaps) const
       
  1436 //
       
  1437 // Return the current capabilities
       
  1438 //
       
  1439 	{
       
  1440 
       
  1441 	GetWinsCommsCaps(aCaps);
       
  1442 	}
       
  1443 
       
  1444 void DCommWins::EnableInterrupts()
       
  1445 //
       
  1446 // Wake the comms thread up
       
  1447 //
       
  1448 	{
       
  1449 	LeaveCritical();
       
  1450 //	if (ResumeThread(iThread)==0xFFFFFFFF)
       
  1451 //		{
       
  1452 //		DWORD err=GetLastError();
       
  1453 //		Panic(EWindowsUnexpectedError);
       
  1454 //		}
       
  1455 	iSkipTransmitIsrNextTime=EFalse;
       
  1456 	}
       
  1457 
       
  1458 void DCommWins::DisableInterrupts()
       
  1459 //
       
  1460 // Suspend the thread (assuming we're not it...)
       
  1461 //
       
  1462 	{
       
  1463 	EnterCritical();
       
  1464 //	if(GetCurrentThreadId()!=iThreadID)
       
  1465 //		if (SuspendThread(iThread)==0xFFFFFFFF)
       
  1466 //			{
       
  1467 //			DWORD err=GetLastError();
       
  1468 //			Panic(EWindowsUnexpectedError);
       
  1469 //			}
       
  1470 	}
       
  1471 
       
  1472 /**
       
  1473     Associate event with our socket
       
  1474 */
       
  1475 TInt DCommWins::QueSocketRead()
       
  1476 	{
       
  1477 	if(WSAEventSelect(iSocket, iReadOverLapped.hEvent, FD_READ))
       
  1478 		{// Some error?!?
       
  1479 		DWORD res = WSAGetLastError();
       
  1480 		return res;
       
  1481 		}
       
  1482 	return KErrNone;
       
  1483 
       
  1484 	}
       
  1485 
       
  1486 
       
  1487 void DCommWins::WaitForEvent()
       
  1488 //
       
  1489 // Comm port thread - wait for serial port and semaphore
       
  1490 //
       
  1491 	{
       
  1492 
       
  1493 	HANDLE objects[5];
       
  1494 
       
  1495 
       
  1496 	iReadOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL); 
       
  1497 	iWriteOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL);
       
  1498 	iSignalOverLapped.hEvent=CreateEventA(NULL,FALSE,FALSE,NULL);
       
  1499 	objects[0]=iSignalOverLapped.hEvent; // iCommPort;
       
  1500 	objects[1]=iCommThreadSem;
       
  1501 	objects[2]=iWriteOverLapped.hEvent;
       
  1502 	objects[3]=iReadOverLapped.hEvent;
       
  1503     objects[4]=iWaitableTimer;
       
  1504 
       
  1505 	FOREVER
       
  1506 		{
       
  1507 		DWORD waitTimeout = INFINITE; // Default timeout 
       
  1508 		if(iReadPending) // If we have a queued read event, we need to check periodically if it can be carried out.
       
  1509 			{
       
  1510 			waitTimeout = 150; 
       
  1511 			}
       
  1512 		
       
  1513 		// Once an event is signalled and WaitFor.. returns, it is reset by WaitFor.. just before it returns.
       
  1514 		// This means that once a read on the socket is signalled. we absolutely must read from it (eventually).
       
  1515 		// Otherwise, the read event remains reset and no further reads are signalled, even if data arrives. 
       
  1516 		// This means that if we cannot read immediately,we MUST queue the read, and carry it out sometimes in the future.
       
  1517 		DWORD ret=WaitForMultipleObjectsEx(5,objects,FALSE,waitTimeout,TRUE);
       
  1518 				
       
  1519 		// If the wait for an event has timed out, AND we have a queued read, try to carry out the read.
       
  1520 		// If we have not timed out, carry out the operation as usual:
       
  1521 		// it cannot be a read, but it may be something which enables us to read later.
       
  1522 		if(ret == WAIT_TIMEOUT && iReadPending)
       
  1523 			{			
       
  1524 			ret = WAIT_OBJECT_0 + 3; // Fall through to the read. 			
       
  1525 			}
       
  1526 		
       
  1527 		switch (ret)
       
  1528 			{
       
  1529 		case WAIT_OBJECT_0:
       
  1530 			ASSERT(iCommPort);
       
  1531 			EnterCritical();
       
  1532 			DWORD commErrors;
       
  1533 			COMSTAT cstat;
       
  1534 //	
       
  1535 // iCommPort has completed other than read/write - could be either error or line status change
       
  1536 //
       
  1537 			if ((iSignalStatus&EV_ERR) || (iSignalStatus&EV_RXCHAR))
       
  1538 				{ 
       
  1539 				ClearCommError(iCommPort,&commErrors,&cstat);
       
  1540 				if (cstat.cbInQue)
       
  1541 					{
       
  1542 //
       
  1543 // Drain the input buffer
       
  1544 //				
       
  1545 					while (cstat.cbInQue>0)
       
  1546 						{
       
  1547                         _Log2("#~ WAIT_OBJECT_0 cstat.cbInQue=%d\n",cstat.cbInQue);//
       
  1548 
       
  1549                         TInt min = Min((TInt)cstat.cbInQue, (TInt)KReadBufSize); 
       
  1550                         TInt i;
       
  1551 						ReadFile(iCommPort,iInBuf,min,(LPDWORD)&i,&iReadOverLapped);
       
  1552 						WaitForSingleObject(iReadOverLapped.hEvent,INFINITE);
       
  1553 						GetOverlappedResult(iCommPort, &iReadOverLapped, (LPDWORD)&i, FALSE);
       
  1554                         __ASSERT_ALWAYS(i==min,Panic(EBadIOLen)); 
       
  1555 
       
  1556                         cstat.cbInQue-=min;
       
  1557 						i=0;
       
  1558 						while (i<min)
       
  1559                             {
       
  1560 
       
  1561                             if(i==(min-1) && !cstat.cbInQue)
       
  1562                                 {
       
  1563                                 //
       
  1564                                 // Mark the final byte with the parity error
       
  1565                                 //
       
  1566 
       
  1567 
       
  1568                                 TInt temp=0;
       
  1569 					            if (commErrors&CE_RXPARITY)
       
  1570 						            temp|=KReceiveIsrParityError;
       
  1571 					            if (commErrors&CE_FRAME)
       
  1572 						            temp|=KReceiveIsrFrameError;
       
  1573 					            if (commErrors&CE_OVERRUN)
       
  1574 						            temp|=KReceiveIsrOverrunError;
       
  1575                                 DoReceiveIsr(iInBuf[i++]|temp);
       
  1576                                 }
       
  1577                             else
       
  1578 							    DoReceiveIsr(iInBuf[i++]);
       
  1579                             }
       
  1580 						}
       
  1581                     
       
  1582 
       
  1583 					}
       
  1584 				}
       
  1585 			if (iSignalStatus&(EV_DSR|EV_CTS|EV_RLSD))
       
  1586 				DoStateIsr();
       
  1587 			iSignalStatus=0;
       
  1588 			WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped);
       
  1589 			LeaveCritical();
       
  1590 			break;
       
  1591 		case WAIT_OBJECT_0+1:
       
  1592 //
       
  1593 // iCommThreadSemaphore has been signalled
       
  1594 //
       
  1595 			DriverCommand(iCommand);
       
  1596 			break;
       
  1597 		case WAIT_OBJECT_0+2:
       
  1598 			//
       
  1599 			//	Write completion
       
  1600 			//
       
  1601 			{
       
  1602 			DWORD len=iWriteOverLapped.InternalHigh;
       
  1603 //			GetOverlappedResult(iCommPort, &iWriteOverLapped, &len, FALSE);
       
  1604 
       
  1605 			EnterCritical();
       
  1606 			WriteCompletion(this, 0, len);
       
  1607 			LeaveCritical();
       
  1608 			break;
       
  1609 			}
       
  1610 
       
  1611 	    case WAIT_OBJECT_0+3:
       
  1612 			//
       
  1613 			// Read completion
       
  1614 			//
       
  1615 			{
       
  1616             ASSERT(iSocket);
       
  1617 			EnterCritical();
       
  1618 			if(iConfig->iHandshake & KConfigFreeRTS || iSignals & KSignalRTS)
       
  1619 				{// Only read when RTS is freed or asserted
       
  1620 
       
  1621                 int num = recv(iSocket, (char*)iInBuf, 16, 0); // Only read 16 bytes at a go, to give LDD plenty of chance to flow off
       
  1622                 
       
  1623                 if(num == 0 ||  (num == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) || num < 0)
       
  1624 					{
       
  1625 					DoReceiveIsr(KReceiveIsrFrameError);
       
  1626 					num = 0;
       
  1627 					}
       
  1628 
       
  1629 				for(int i = 0; i<num; ++i)
       
  1630 					{
       
  1631 					DoReceiveIsr(iInBuf[i]);
       
  1632 					}
       
  1633 				// We'll automatically be re-signalled if there's more data waiting
       
  1634 
       
  1635 				iSignalStatus=0;
       
  1636 	//			if(QueSocketRead() != KErrNone)
       
  1637 	//				{
       
  1638 	//				DoReceiveIsr(KReceiveIsrFrameError);
       
  1639 	//				iNumInChars = 0;
       
  1640 	//				}
       
  1641 					
       
  1642 				iReadPending = EFalse; // Make sure read is not queued
       
  1643 				}
       
  1644 			else // We cannot read at this time. 
       
  1645                 {
       
  1646 				// We have skipped the read, and the read event is reset at this point.
       
  1647 				iReadPending = ETrue; // Queue the read event
       
  1648                 _Log3("#~ ReadCompletion FC, iSignals=0x%x, iConfig->iHandshake=%d\n", iSignals, iConfig->iHandshake);
       
  1649                 }
       
  1650 			LeaveCritical();
       
  1651 			break;
       
  1652 			}		
       
  1653       
       
  1654 
       
  1655         case WAIT_OBJECT_0+4:
       
  1656             //
       
  1657             //    Timer completion
       
  1658             //
       
  1659             {
       
  1660             Comm().TurnaroundStartDfcImplementation();
       
  1661             break;
       
  1662             }
       
  1663 		
       
  1664 		case WAIT_IO_COMPLETION:
       
  1665 //
       
  1666 // A read or write completion routine has been queued - why would we care?
       
  1667 // Do nothing?
       
  1668             _Log("#~ WAIT_IO_COMPLETION\n");//
       
  1669 
       
  1670 		break;
       
  1671 		
       
  1672 		case WAIT_TIMEOUT: // Ignore the timeout.
       
  1673 			// Just in case we timed out and no read is queued. 
       
  1674 			// This is impossible, because we can time out only when a read is queued, 
       
  1675 			// so we'll try to read rather than end up here. 
       
  1676 			// This code is just in case there are further modifications to the event handling code.			
       
  1677 			break;
       
  1678 		
       
  1679 		default:
       
  1680 			MapWinError();
       
  1681 			Panic(EWindowsUnexpectedError);
       
  1682 			}
       
  1683 		}
       
  1684 	}
       
  1685 
       
  1686 void DCommWins::DriverCommand(TDriverCommand aCommand)
       
  1687 //
       
  1688 // Do a driver command - executed when the semaphore has been signalled in the comm port thread
       
  1689 //
       
  1690 	{
       
  1691 	switch (aCommand)
       
  1692 		{
       
  1693 	case ESetBreak:
       
  1694 		if(!UseSocket()) SetCommBreak(iCommPort);
       
  1695 		break;
       
  1696 	case EClearBreak:
       
  1697 		if(!UseSocket()) ClearCommBreak(iCommPort);
       
  1698 		break;
       
  1699 	case ETransmit:
       
  1700 		// Only Transmit one character to get the driver transmit cycle going
       
  1701 		// otherwise we can empty the buffer and get double starts and re-write death
       
  1702 		if (!iWritePending)
       
  1703 			{
       
  1704 			if(DoTransmitIsr(iNumOutChars))
       
  1705 				iNumOutChars++;
       
  1706 #if defined (_LOG_OUTPUT)
       
  1707 			DWORD dummy;
       
  1708 			WriteFile(iWritesHandle,iOutBuf,iNumOutChars,&dummy,NULL);
       
  1709 #endif 
       
  1710 			if (iNumOutChars>0)
       
  1711 				{
       
  1712 				iWritePending=ETrue;
       
  1713 //				WriteFileEx(iCommPort,iOutBuf,iNumOutChars,&iWriteOverLapped,WriteComplete);
       
  1714 				WriteFile(iCommPort,iOutBuf,iNumOutChars, NULL, &iWriteOverLapped);
       
  1715 
       
  1716 #if defined (_LOG_WRITES)
       
  1717 					TBuf<0x40> buf;
       
  1718 					DWORD dummy;
       
  1719 					buf.Format(_L("writing %d\r\n"),iNumOutChars);
       
  1720 					WriteFile(iLogFile,buf.PtrZ(),buf.Length(),&dummy,NULL);
       
  1721 #endif
       
  1722 
       
  1723 				}
       
  1724 			}
       
  1725 		break;
       
  1726 	case EStart:
       
  1727 
       
  1728 		if(UseSocket())
       
  1729 		{
       
  1730 			if(QueSocketRead() != KErrNone)
       
  1731 				{// Couldn't que initial read :-(
       
  1732 				__DEBUGGER();
       
  1733 				}
       
  1734 		}
       
  1735 		else
       
  1736         {
       
  1737             DWORD err,res;
       
  1738 		    COMSTAT s;
       
  1739 		    if (iCommPort && ClearCommError(iCommPort,&err,&s)==FALSE)
       
  1740 			    res=GetLastError();
       
  1741 		    PurgeComm(iCommPort ,PURGE_RXCLEAR);
       
  1742 		    iSignalStatus=0;
       
  1743 		    WaitCommEvent(iCommPort,&iSignalStatus,&iSignalOverLapped);
       
  1744         }
       
  1745 
       
  1746 	//	if (ReadFileEx(iCommPort,iInBuf,1,&iReadOverLapped,ReadComplete)==FALSE)
       
  1747 	//		DWORD res=GetLastError();
       
  1748 		break;
       
  1749 	case EStop:
       
  1750 		if(!UseSocket() && iNumOutChars)
       
  1751 			{
       
  1752 #if defined (_LOG_OUTPUT)
       
  1753 			DWORD dummy;
       
  1754 			WriteFile(iWritesHandle,iOutBuf,iNumOutChars,&dummy,NULL);
       
  1755 #endif 
       
  1756             // Flush last write
       
  1757 			if(iWritePending)
       
  1758 			    {
       
  1759 			    WaitForSingleObject(iWriteOverLapped.hEvent, INFINITE);
       
  1760 			    FlushFileBuffers(iCommPort);
       
  1761                 iWritePending=EFalse;
       
  1762 				}
       
  1763 			}
       
  1764 		// Fall through
       
  1765 	case EStopNoDrain:
       
  1766 		if(UseSocket())
       
  1767 			{
       
  1768 			CancelIo(iCommPort); // cancels read & write (see below)
       
  1769 			}
       
  1770 		// Cancel any pending writes
       
  1771         if(iWritePending)
       
  1772 		{
       
  1773 			if(!UseSocket()) 
       
  1774             {
       
  1775                 PurgeComm(iCommPort, PURGE_TXABORT|PURGE_TXCLEAR);
       
  1776                 WaitForSingleObject(iWriteOverLapped.hEvent, INFINITE);
       
  1777             }
       
  1778 			iWritePending=EFalse;
       
  1779 		}   
       
  1780 
       
  1781 		iStopping=ETrue;
       
  1782         if(iRunning)
       
  1783 		{
       
  1784 			if(!UseSocket())
       
  1785 			{
       
  1786 				SetCommMask(iCommPort,EV_CTS|EV_ERR|EV_DSR|EV_RLSD|EV_RXCHAR);
       
  1787 				WaitForSingleObject(iSignalOverLapped.hEvent, INFINITE);
       
  1788 			}
       
  1789         }
       
  1790 		break;
       
  1791 	case EDie:	
       
  1792 		SignalDriverThread();
       
  1793 		ExitThread(1);
       
  1794 		break;
       
  1795 	case EConfigure:
       
  1796 		DoConfigure();
       
  1797 		break;
       
  1798 	default:
       
  1799 		// Panic(EUnknownCommand);
       
  1800 		break;
       
  1801 		}
       
  1802 	iCommand=EInvalidCommand;
       
  1803 	SignalDriverThread();
       
  1804 	}
       
  1805 
       
  1806 TInt DCommWins::DoTransmitIsr(TInt anOffset)
       
  1807 //
       
  1808 // Call the transmit Isr in the LDD to get the next character
       
  1809 //
       
  1810 	{
       
  1811 
       
  1812 	TInt ret;
       
  1813 	ret=Comm().TransmitIsr();
       
  1814 	iOutBuf[anOffset]=(*(char *)&ret);
       
  1815 #ifdef _DEBUG_DEVCOMM
       
  1816 	iTxIntCount += (ret!=KTransmitIrqEmpty);
       
  1817 #endif
       
  1818 	return(ret!=KTransmitIrqEmpty);
       
  1819 	}
       
  1820 
       
  1821 void DCommWins::DoReceiveIsr(TUint anCharAndMask)
       
  1822 //
       
  1823 // Call the Isr in the LDD to process this character
       
  1824 //
       
  1825 	{
       
  1826 #ifdef _DEBUG_DEVCOMM
       
  1827 	iRxIntCount++;
       
  1828 	if (anCharAndMask & ~0xff)
       
  1829 		iRxErrCount++;
       
  1830 #endif
       
  1831 	Comm().ReceiveIsr(anCharAndMask);
       
  1832 	}
       
  1833 
       
  1834 void DCommWins::DoStateIsr()
       
  1835 //
       
  1836 // Call the Isr in the device to handle a line status change.
       
  1837 //
       
  1838 	{
       
  1839 	Comm().StateIsr(Signals());
       
  1840 	}
       
  1841 
       
  1842 void DCommWins::EnterCritical()
       
  1843 //
       
  1844 // Call the Isr in the device to handle a line status change.
       
  1845 //
       
  1846 	{
       
  1847 	EnterCriticalSection(&iCriticalSection);
       
  1848 	iIntRefCount++;
       
  1849 	}
       
  1850 
       
  1851 void DCommWins::LeaveCritical()
       
  1852 //
       
  1853 // Call the Isr in the device to handle a line status change.
       
  1854 //
       
  1855 	{
       
  1856 	--iIntRefCount;
       
  1857 	LeaveCriticalSection(&iCriticalSection);
       
  1858 	}
       
  1859  
       
  1860 void DCommWins::SetTimer(const TUint aTimeOut) 
       
  1861     { 
       
  1862     TInt timeout = aTimeOut; 
       
  1863     timeout *= 10; // to 100ns units 
       
  1864     timeout = -timeout; // make relative to current time 
       
  1865     iTimeOut.QuadPart = timeout; 
       
  1866     SetWaitableTimer(iWaitableTimer, &iTimeOut, 0, NULL, NULL, 0); 
       
  1867     } 
       
  1868  
       
  1869 void DCommWins::CancelTimer() 
       
  1870     { 
       
  1871     CancelWaitableTimer(iWaitableTimer); 
       
  1872     } 
       
  1873 
       
  1874 EXPORT_C DPhysicalDevice *CreatePhysicalDevice()
       
  1875 //
       
  1876 // Create a new physical device driver
       
  1877 //
       
  1878 	{
       
  1879 
       
  1880 	return(new DDriverComm);
       
  1881 	}
       
  1882 
       
  1883 GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
       
  1884 //
       
  1885 // DLL entry point
       
  1886 //
       
  1887 	{
       
  1888 
       
  1889 	return(KErrNone);
       
  1890 	}