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