|
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 } |