source: trunk/src/kernel32/hmcomm.cpp@ 9079

Last change on this file since 9079 was 9079, checked in by sandervl, 23 years ago

EV_RLSD/MS_RLSD_ON status corresponds to OS/2 DCD (data carrier detect) status GetCommModemStatus & GetCommEvent changed

File size: 58.1 KB
Line 
1/* $Id: hmcomm.cpp,v 1.38 2002-08-21 17:23:12 sandervl Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 COM device access class
7 *
8 * 1999 Achim Hasenmueller <achimha@innotek.de>
9 * 2001 Sander van Leeuwen <sandervl@xs4all.nl>
10 *
11 *
12 */
13
14
15
16#include <os2win.h>
17#include <string.h>
18#include <handlemanager.h>
19#include "handlenames.h"
20#include <heapstring.h>
21#include "hmcomm.h"
22#include "oslibdos.h"
23
24#define DBG_LOCALLOG DBG_hmcomm
25#include "dbglocal.h"
26
27//#define TESTING_COMM
28#ifdef TESTING_COMM
29#undef dprintf
30#define dprintf(a) WriteLog a
31#undef dprintf2
32#define dprintf2(a) WriteLog a
33#endif
34
35BAUDTABLEENTRY BaudTable[] =
36{
37 {75,BAUD_075},
38 {110,BAUD_110},
39 {134,BAUD_134_5},
40 {150,BAUD_150},
41 {300,BAUD_300},
42 {600,BAUD_600},
43 {1200,BAUD_1200},
44 {1800,BAUD_1800},
45 {2400,BAUD_2400},
46 {4800,BAUD_4800},
47 {7200,BAUD_7200},
48 {9600,BAUD_9600},
49 {14400,BAUD_14400},
50 {19200,BAUD_19200},
51 {38400,BAUD_38400},
52 {56000,BAUD_56K},
53 {57600,BAUD_57600},
54 {115200,BAUD_115200},
55 {128000,BAUD_128K}
56};
57
58#define BaudTableSize (sizeof(BaudTable)/sizeof(BAUDTABLEENTRY))
59
60static DWORD CommReadIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut);
61static DWORD CommWriteIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut);
62static DWORD CommPollIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut);
63#ifdef DEBUG
64static char *DebugCommEvent(DWORD dwEvents);
65static char *DebugModemStatus(DWORD dwModemStatus);
66#endif
67//******************************************************************************
68//******************************************************************************
69static VOID *CreateDevData()
70{
71 PHMDEVCOMDATA pData;
72
73 pData = new HMDEVCOMDATA();
74 if(NULL!=pData)
75 {
76 memset(pData,0,sizeof(HMDEVCOMDATA));
77 pData->ulMagic = MAGIC_COM;
78 pData->CommCfg.dwSize = sizeof(COMMCONFIG);
79 pData->CommCfg.wVersion = 1;
80 pData->CommCfg.dwProviderSubType = PST_RS232;
81 pData->CommCfg.dcb.DCBlength = sizeof(DCB);
82 pData->CommCfg.dcb.BaudRate = CBR_1200;
83 pData->CommCfg.dcb.ByteSize = 8;
84 pData->CommCfg.dcb.Parity = NOPARITY;
85 pData->CommCfg.dcb.StopBits = ONESTOPBIT;
86 pData->dwInBuffer = 16;
87 pData->dwOutBuffer = 16;
88 }
89 return pData;
90}
91//******************************************************************************
92//******************************************************************************
93HMDeviceCommClass::HMDeviceCommClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName)
94{
95 VOID *pData;
96
97 dprintf(("HMDeviceCommClass: Register COM1 to COM8 with Handle Manager\n"));
98 pData = CreateDevData();
99 if(pData!= NULL)
100 HMDeviceRegisterEx("COM1", this, pData);
101
102 // add symbolic links to the "real name" of the device
103 // @@@PH what's the long device name: SerialPortx ?
104 // HandleNamesAddSymbolicLink("\\Device\\ParallelPort3", "COM3");
105 // Note: \\.\COMx: is invalid (NT4SP6)
106
107 PSZ pszCOM = strdup("\\\\.\\COMx");
108 for (char ch = '1'; ch < '9'; ch++)
109 {
110 pszCOM[7] = ch;
111 HandleNamesAddSymbolicLink(pszCOM, pszCOM+4);
112 }
113 free(pszCOM);
114
115 // add "AUX" device
116 HandleNamesAddSymbolicLink("AUX", "COM1");
117 HandleNamesAddSymbolicLink("AUX:", "COM1");
118 HandleNamesAddSymbolicLink("\\\\.\\AUX", "COM1");
119}
120
121/*****************************************************************************
122 * Name : HMDeviceCommClass::FindDevice
123 * Purpose : Checks if lpDeviceName belongs to this device class
124 * Parameters: LPCSTR lpClassDevName
125 * LPCSTR lpDeviceName
126 * int namelength
127 * Variables :
128 * Result : checks if name is COMx or COMx: (x=1..8)
129 * Remark :
130 * Status :
131 *
132 * Author : SvL
133 *****************************************************************************/
134BOOL HMDeviceCommClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
135{
136 dprintf2(("HMDeviceCommClass::FindDevice %s %s", lpClassDevName, lpDeviceName));
137
138 //first 3 letters 'COM'?
139 if(lstrncmpiA(lpDeviceName, lpClassDevName, 3) != 0) {
140 return FALSE;
141 }
142
143 if(namelength == 5 && lpDeviceName[4] != ':') {
144 return FALSE;
145 }
146 switch(lpDeviceName[3]) {
147 case '1':
148 case '2':
149 case '3':
150 case '4':
151 case '5':
152 case '6':
153 case '7':
154 case '8':
155 return TRUE; //we support up to COM8
156 }
157 return FALSE;
158}
159//******************************************************************************
160//******************************************************************************
161DWORD HMDeviceCommClass::CreateFile(LPCSTR lpFileName,
162 PHMHANDLEDATA pHMHandleData,
163 PVOID lpSecurityAttributes,
164 PHMHANDLEDATA pHMHandleDataTemplate)
165{
166 char comname[6];
167 DWORD ret = ERROR_SUCCESS;
168
169 dprintf(("HMComm: Serial communication port %s open request\n", lpFileName));
170
171 if(strlen(lpFileName) > 5) {
172 lpFileName += 4; //skip prefix
173 }
174
175 pHMHandleData->hHMHandle = 0;
176
177 strcpy(comname, lpFileName);
178 comname[4] = 0; //get rid of : (if present) (eg COM1:)
179
180 //AH: TODO parse Win32 security handles
181 ULONG oldmode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
182 pHMHandleData->hHMHandle = OSLibDosOpen(comname,
183 OSLIB_ACCESS_READWRITE |
184 OSLIB_ACCESS_SHAREDENYREAD |
185 OSLIB_ACCESS_SHAREDENYWRITE);
186 ::SetErrorMode(oldmode);
187 if (pHMHandleData->hHMHandle != 0)
188 {
189 ULONG ulLen;
190 APIRET rc;
191 pHMHandleData->lpHandlerData = new HMDEVCOMDATA();
192 // Init The handle instance with the default default device config
193 memcpy( pHMHandleData->lpHandlerData,
194 pHMHandleData->lpDeviceData,
195 sizeof(HMDEVCOMDATA));
196
197 ulLen = sizeof(DCBINFO);
198
199 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
200 IOCTL_ASYNC,
201 ASYNC_GETDCBINFO,
202 0,0,0,
203 &((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2,ulLen,&ulLen);
204 dprintf(("DCB Of %s :\n"
205 " WriteTimeout : %d\n"
206 " ReadTimeout : %d\n"
207 " CtlHandshake : 0x%x\n"
208 " FlowReplace : 0x%x\n"
209 " Timeout : 0x%x\n"
210 " Error replacement Char : 0x%x\n"
211 " Break replacement Char : 0x%x\n"
212 " XON Char : 0x%x\n"
213 " XOFF Char : 0x%x\n",
214 comname,
215 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.usWriteTimeout,
216 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.usReadTimeout,
217 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbCtlHndShake,
218 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbFlowReplace,
219 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbTimeOut,
220 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bErrorReplacementChar,
221 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bBreakReplacementChar,
222 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bXONChar,
223 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bXOFFChar));
224
225 if(rc)
226 {
227 OSLibDosClose(pHMHandleData->hHMHandle);
228 delete pHMHandleData->lpHandlerData;
229 return rc;
230 }
231 rc = SetBaud(pHMHandleData,9600);
232 dprintf(("Init Baud to 9600 rc = %d",rc));
233 rc = SetLine(pHMHandleData,8,0,0);
234 dprintf(("Set Line to 8/N/1 rc = %d",rc));
235
236 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
237 {
238 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
239 int comnr;
240
241 comnr = comname[3] - '1';
242
243 if(handler[comnr] == NULL)
244 {
245 try {
246 handler[comnr] = new OverlappedIOHandler(CommReadIOHandler, CommWriteIOHandler, CommPollIOHandler, ASYNC_TYPE_FULLDUPLEX);
247 }
248 catch(...)
249 {
250 ret = ERROR_NOT_ENOUGH_MEMORY;
251 goto fail;
252 }
253 if(handler[comnr] == NULL) {
254 ret = ERROR_NOT_ENOUGH_MEMORY;
255 goto fail;
256 }
257 handler[comnr]->AddRef();
258 }
259 pDevData->iohandler = handler[comnr];
260 }
261 return ERROR_SUCCESS;
262 }
263 else
264 return ERROR_ACCESS_DENIED;
265
266fail:
267
268 delete pHMHandleData->lpHandlerData;
269 OSLibDosClose(pHMHandleData->hHMHandle);
270 return ret;
271}
272/*****************************************************************************
273 * Name : DWORD HMDeviceCommClass::GetFileType
274 * Purpose : determine the handle type
275 * Parameters: PHMHANDLEDATA pHMHandleData
276 * Variables :
277 * Result : API returncode
278 * Remark :
279 * Status :
280 *
281 * Author : SvL
282 *****************************************************************************/
283DWORD HMDeviceCommClass::GetFileType(PHMHANDLEDATA pHMHandleData)
284{
285 dprintf(("KERNEL32: HMDeviceCommClass::GetFileType %s(%08x)\n",
286 lpHMDeviceName, pHMHandleData));
287
288 return FILE_TYPE_CHAR;
289}
290//******************************************************************************
291//******************************************************************************
292BOOL HMDeviceCommClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
293{
294 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
295 dprintf(("HMComm: Serial communication port close request"));
296
297 delete pHMHandleData->lpHandlerData;
298 return OSLibDosClose(pHMHandleData->hHMHandle);
299}
300//******************************************************************************
301//Overlapped read handler
302//******************************************************************************
303DWORD CommReadIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut)
304{
305 PHMHANDLEDATA pHMHandleData;
306 BOOL ret;
307 ULONG ulBytesRead, len;
308
309 pHMHandleData = HMQueryHandleData(lpRequest->hHandle);
310 if(pHMHandleData == NULL) {
311 dprintf(("!ERROR!: CommReadIOHandler handle %x not valid", lpRequest->hHandle));
312 DebugInt3();
313 return ERROR_INVALID_HANDLE;
314 }
315
316#ifdef DEBUG
317 RXQUEUE qInfo;
318 ULONG ulLen = sizeof(qInfo);
319 ULONG rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
320 IOCTL_ASYNC,
321 ASYNC_GETINQUECOUNT,
322 0,0,0,
323 &qInfo,ulLen,&ulLen);
324 dprintf(("ASYNC_GETINQUECOUNT -> qInfo.cch %d (queue size %d) rc %d", qInfo.cch, qInfo.cb, rc));
325#endif
326
327 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpRequest->lpBuffer, lpRequest->nNumberOfBytes, &ulBytesRead);
328
329 *lpdwResult = (ret) ? ulBytesRead : 0;
330 dprintf2(("KERNEL32: CommReadIOHandler %d bytes read", *lpdwResult));
331
332 if(ret == FALSE) {
333 dprintf(("!ERROR!: CommReadIOHandler failed with rc %d", GetLastError()));
334 }
335 else {
336#ifdef DEBUG
337 dprintf2(("%d Bytes read:", ulBytesRead));
338 for(int i=0;i<min(ulBytesRead, 16);i++) {
339 dprintf2(("%x %c", ((char *)lpRequest->lpBuffer)[i], ((char *)lpRequest->lpBuffer)[i]));
340 }
341#endif
342 }
343 return GetLastError();
344}
345//******************************************************************************
346//Overlapped write handler
347//******************************************************************************
348DWORD CommWriteIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut)
349{
350 PHMHANDLEDATA pHMHandleData;
351 BOOL ret;
352 ULONG ulBytesWritten;
353
354 pHMHandleData = HMQueryHandleData(lpRequest->hHandle);
355 if(pHMHandleData == NULL) {
356 dprintf(("!ERROR!: CommWriteIOHandler handle %x not valid", lpRequest->hHandle));
357 DebugInt3();
358 return ERROR_INVALID_HANDLE;
359 }
360
361#ifdef DEBUG
362 dprintf2(("Bytes to write:"));
363 for(int i=0;i<min(lpRequest->nNumberOfBytes, 16);i++) {
364 dprintf2(("%x %c", ((char *)lpRequest->lpBuffer)[i], ((char *)lpRequest->lpBuffer)[i]));
365 }
366#endif
367
368 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpRequest->lpBuffer, lpRequest->nNumberOfBytes,
369 &ulBytesWritten);
370
371 *lpdwResult = (ret) ? ulBytesWritten : 0;
372 dprintf2(("KERNEL32:CommWriteIOHandler %d byte(s) written", *lpdwResult));
373
374 if(ret == FALSE) {
375 dprintf(("!ERROR!: CommWriteIOHandler failed with rc %d", GetLastError()));
376 }
377 return GetLastError();
378}
379//******************************************************************************
380//Overlapped WaitCommEvent handler
381//******************************************************************************
382DWORD CommPollIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut)
383{
384 APIRET rc;
385 ULONG ulLen;
386 USHORT COMEvt;
387 DWORD dwEvent,dwMask;
388 PHMHANDLEDATA pHMHandleData;
389 PHMDEVCOMDATA pDevData;
390
391 pHMHandleData = HMQueryHandleData(lpRequest->hHandle);
392 if(pHMHandleData == NULL || pHMHandleData->lpHandlerData == NULL) {
393 dprintf(("!ERROR!: CommWriteIOHandler handle %x not valid", lpRequest->hHandle));
394 DebugInt3();
395 return ERROR_INVALID_HANDLE;
396 }
397
398 pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
399
400//// dprintf(("CommPollIOHandler %x %x", pHMHandleData->hHMHandle, lpRequest->dwEventMask));
401
402 *lpdwTimeOut = TIMEOUT_COMM;
403
404 ulLen = sizeof(CHAR);
405 dwEvent = 0;
406 rc = 0;
407 ulLen = sizeof(COMEvt);
408 dwMask = lpRequest->dwEventMask;
409
410 if(lpRequest->dwEventMask != pDevData->dwEventMask) {
411 dprintf(("!WARNING!: CommPollIOHandler: operation aborted (event mask changed)"));
412 return ERROR_OPERATION_ABORTED; // Exit if the Mask gets changed
413 }
414 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
415 IOCTL_ASYNC,
416 ASYNC_GETCOMMEVENT,
417 0,0,0,
418 &COMEvt,ulLen,&ulLen);
419 if(!rc)
420 {
421#ifdef DEBUG
422 if(COMEvt) dprintf(("ASYNC_GETCOMMEVENT %x", COMEvt));
423#endif
424 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
425 //dwEvent |= (COMEvt&0x0002)? 0:0;
426 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
427 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
428 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
429 dwEvent |= (COMEvt&0x0020)? EV_RLSD:0;
430 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
431 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
432 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
433
434 if((dwEvent & EV_RXCHAR) && (dwMask & EV_RXCHAR))
435 {
436 //check if there's really data in the in queue
437 RXQUEUE qInfo;
438 ULONG ulLen = sizeof(qInfo);
439 ULONG rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
440 IOCTL_ASYNC,
441 ASYNC_GETINQUECOUNT,
442 0,0,0,
443 &qInfo,ulLen,&ulLen);
444 if(qInfo.cch == 0) {
445 dprintf(("!WARNING!: CommPollIOHandler -> EV_RXCHAR but no DATA"));
446 dwEvent &= ~EV_RXCHAR;
447 }
448 }
449 if((dwEvent & dwMask)) {
450 dprintf(("CommPollIOHandler: event(s) %s %x occured", DebugCommEvent((dwEvent & dwMask)), (dwEvent & dwMask)));
451 *lpdwResult = (dwEvent & dwMask);
452 return ERROR_SUCCESS;
453 }
454 }
455 else {
456 dprintf(("!ERROR!: CommPollIOHandler: OSLibDosDevIOCtl failed with rc %d", rc));
457 *lpdwResult = 0;
458 return ERROR_OPERATION_ABORTED;
459 }
460 return ERROR_IO_PENDING;
461}
462/*****************************************************************************
463 * Name : BOOL HMDeviceCommClass::WriteFile
464 * Purpose : write data to handle / device
465 * Parameters: PHMHANDLEDATA pHMHandleData,
466 * LPCVOID lpBuffer,
467 * DWORD nNumberOfBytesToWrite,
468 * LPDWORD lpNumberOfBytesWritten,
469 * LPOVERLAPPED lpOverlapped
470 * Variables :
471 * Result : Boolean
472 * Remark :
473 * Status :
474 *
475 * Author : SvL
476 *****************************************************************************/
477BOOL HMDeviceCommClass::WriteFile(PHMHANDLEDATA pHMHandleData,
478 LPCVOID lpBuffer,
479 DWORD nNumberOfBytesToWrite,
480 LPDWORD lpNumberOfBytesWritten,
481 LPOVERLAPPED lpOverlapped,
482 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
483{
484 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
485 BOOL ret;
486 ULONG ulBytesWritten;
487
488 dprintf(("KERNEL32:HMDeviceCommClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
489 lpHMDeviceName, pHMHandleData->hHMHandle, lpBuffer, nNumberOfBytesToWrite,
490 lpNumberOfBytesWritten, lpOverlapped));
491
492
493 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
494 {
495 ::SetLastError(ERROR_INVALID_HANDLE);
496 return FALSE;
497 }
498
499 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
500 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
501 ::SetLastError(ERROR_INVALID_PARAMETER);
502 return FALSE;
503 }
504 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
505 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
506 }
507 if(lpCompletionRoutine) {
508 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
509 }
510
511 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
512 return pDevData->iohandler->WriteFile(pHMHandleData->hWin32Handle, lpBuffer, nNumberOfBytesToWrite,
513 lpNumberOfBytesWritten, lpOverlapped, lpCompletionRoutine, (DWORD)pDevData);
514 }
515
516 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite,
517 &ulBytesWritten);
518
519 if(lpNumberOfBytesWritten) {
520 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0;
521 dprintf2(("KERNEL32:HMDeviceCommClass::WriteFile %d byte(s) written", *lpNumberOfBytesWritten));
522 }
523 if(ret == FALSE) {
524 dprintf(("!ERROR!: WriteFile failed with rc %d", GetLastError()));
525 }
526
527 return ret;
528}
529/*****************************************************************************
530 * Name : BOOL HMDeviceCommClass::ReadFile
531 * Purpose : read data from handle / device
532 * Parameters: PHMHANDLEDATA pHMHandleData,
533 * LPCVOID lpBuffer,
534 * DWORD nNumberOfBytesToRead,
535 * LPDWORD lpNumberOfBytesRead,
536 * LPOVERLAPPED lpOverlapped
537 * Variables :
538 * Result : Boolean
539 * Remark :
540 * Status :
541 *
542 * Author : SvL
543 *****************************************************************************/
544
545BOOL HMDeviceCommClass::ReadFile(PHMHANDLEDATA pHMHandleData,
546 LPCVOID lpBuffer,
547 DWORD nNumberOfBytesToRead,
548 LPDWORD lpNumberOfBytesRead,
549 LPOVERLAPPED lpOverlapped,
550 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
551{
552 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
553 BOOL ret;
554 ULONG ulBytesRead;
555
556 dprintf(("KERNEL32:HMDeviceCommClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
557 lpHMDeviceName, pHMHandleData->hHMHandle, lpBuffer, nNumberOfBytesToRead,
558 lpNumberOfBytesRead, lpOverlapped));
559
560 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
561 {
562 ::SetLastError(ERROR_INVALID_HANDLE);
563 return FALSE;
564 }
565
566 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
567 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
568 ::SetLastError(ERROR_INVALID_PARAMETER);
569 return FALSE;
570 }
571 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
572 dprintf(("!WARNING!: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
573 }
574
575 if(lpCompletionRoutine) {
576 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
577 }
578
579 RXQUEUE qInfo;
580 ULONG ulLen = sizeof(qInfo);
581 ULONG rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, IOCTL_ASYNC, ASYNC_GETINQUECOUNT, 0,0,0, &qInfo,ulLen,&ulLen);
582 dprintf(("ASYNC_GETINQUECOUNT -> qInfo.cch %d (queue size %d) rc %d", qInfo.cch, qInfo.cb, rc));
583
584 if(!qInfo.cch && pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
585 return pDevData->iohandler->ReadFile(pHMHandleData->hWin32Handle, lpBuffer, nNumberOfBytesToRead,
586 lpNumberOfBytesRead, lpOverlapped, lpCompletionRoutine, (DWORD)pDevData);
587 }
588
589 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
590 &ulBytesRead);
591
592 if(lpNumberOfBytesRead) {
593 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0;
594 dprintf2(("KERNEL32:HMDeviceCommClass::ReadFile %d bytes read", *lpNumberOfBytesRead));
595 }
596 if(ret == FALSE) {
597 dprintf(("!ERROR!: ReadFile failed with rc %d", GetLastError()));
598 }
599#ifdef DEBUG
600 else {
601 dprintf2(("%d Bytes read:", ulBytesRead));
602 for(int i=0;i<min(ulBytesRead, 16);i++) {
603 dprintf2(("%x %c", ((char *)lpBuffer)[i], ((char *)lpBuffer)[i]));
604 }
605 }
606#endif
607
608 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
609 //reset overlapped semaphore to non-signalled
610 ::ResetEvent(lpOverlapped->hEvent);
611
612 //set event to make sure next GetOverlappedResult doesn't block
613 ::SetEvent(lpOverlapped->hEvent);
614
615 lpOverlapped->Internal = GetLastError();
616 lpOverlapped->InternalHigh = ulBytesRead;
617 }
618 return ret;
619}
620/*****************************************************************************
621 * Name : DWORD HMDeviceHandler::SetupComm
622 * Purpose : set com port parameters (queue)
623 * Variables :
624 * Result :
625 * Remark :
626 * Status :
627 *
628 * Author : Achim Hasenmueller
629 *****************************************************************************/
630
631BOOL HMDeviceCommClass::SetupComm( PHMHANDLEDATA pHMHandleData,
632 DWORD dwInQueue,
633 DWORD dwOutQueue)
634{
635 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
636
637 dprintf(("HMDeviceCommClass::SetupComm "));
638 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
639 {
640 ::SetLastError(ERROR_INVALID_HANDLE);
641 return FALSE;
642 }
643 pDevData->dwInBuffer = dwInQueue;
644 pDevData->dwOutBuffer = dwOutQueue;
645
646 return(TRUE);
647}
648//******************************************************************************
649//******************************************************************************
650BOOL HMDeviceCommClass::WaitCommEvent( PHMHANDLEDATA pHMHandleData,
651 LPDWORD lpfdwEvtMask,
652 LPOVERLAPPED lpo)
653{
654 APIRET rc;
655 ULONG ulLen;
656 USHORT COMEvt;
657 DWORD dwEvent,dwMask;
658
659 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
660
661 dprintf(("HMDeviceCommClass::WaitCommEvent %x %x %x", pHMHandleData->hHMHandle, lpfdwEvtMask, lpo));
662
663 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo) {
664 dprintf(("!WARNING! pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo"));
665 ::SetLastError(ERROR_INVALID_PARAMETER);
666 return FALSE;
667 }
668
669 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
670 {
671 return pDevData->iohandler->WaitForEvent(pHMHandleData->hWin32Handle, pDevData->dwEventMask, lpfdwEvtMask,
672 lpo, NULL, (DWORD)pDevData);
673 }
674
675 ulLen = sizeof(CHAR);
676
677 dwEvent = 0;
678 rc = 0;
679 ulLen = sizeof(COMEvt);
680 dwMask = pDevData->dwEventMask;
681 while( (0==rc) &&
682 !(dwEvent & dwMask) &&
683 (dwMask ==pDevData->dwEventMask) ) // Exit if the Mask gets changed
684 {
685 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
686 IOCTL_ASYNC,
687 ASYNC_GETCOMMEVENT,
688 0,0,0,
689 &COMEvt,ulLen,&ulLen);
690 if(!rc)
691 {
692 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
693 //dwEvent |= (COMEvt&0x0002)? 0:0;
694 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
695 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
696 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
697 dwEvent |= (COMEvt&0x0020)? EV_RLSD:0;
698 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
699 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
700 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
701 if((dwEvent & dwMask)) break;
702 }
703 else break;
704
705 DosSleep(TIMEOUT_COMM);
706 }
707 if(dwMask == pDevData->dwEventMask) {
708 *lpfdwEvtMask = (rc==0) ? (dwEvent & dwMask) : 0;
709 dprintf(("WaitCommEvent returned %s %x", DebugCommEvent(*lpfdwEvtMask), *lpfdwEvtMask));
710 }
711 else *lpfdwEvtMask = 0;
712
713 ::SetLastError(rc);
714 return (rc==0);
715}
716/*****************************************************************************
717 * Name : DWORD HMDeviceCommClass::CancelIo
718 * Purpose : cancel pending IO operation
719 * Variables :
720 * Result :
721 * Remark :
722 * Status :
723 *
724 * Author : SvL
725 *****************************************************************************/
726BOOL HMDeviceCommClass::CancelIo(PHMHANDLEDATA pHMHandleData)
727{
728 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
729
730 dprintf(("HMDeviceCommClass::CancelIo"));
731 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
732 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
733 return FALSE;
734 }
735
736 return pDevData->iohandler->CancelIo(pHMHandleData->hWin32Handle);
737}
738/*****************************************************************************
739 * Name : DWORD HMDeviceFileClass::GetOverlappedResult
740 * Purpose : asynchronus I/O
741 * Parameters: PHMHANDLEDATA pHMHandleData
742 * LPOVERLAPPED arg2
743 * LPDWORD arg3
744 * BOOL arg4
745 * Variables :
746 * Result : API returncode
747 * Remark :
748 * Status :
749 *
750 * Author : SvL
751 *****************************************************************************/
752BOOL HMDeviceCommClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData,
753 LPOVERLAPPED lpOverlapped,
754 LPDWORD lpcbTransfer,
755 BOOL fWait)
756{
757 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
758
759 dprintf(("KERNEL32-HMDeviceCommClass: HMDeviceCommClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh)",
760 pHMHandleData->hHMHandle, lpOverlapped, lpcbTransfer, fWait));
761
762 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
763 dprintf(("!WARNING!: GetOverlappedResult called for a handle that wasn't opened with FILE_FLAG_OVERLAPPED"));
764 return TRUE; //NT4, SP6 doesn't fail
765 }
766
767 if(pDevData == NULL) {
768 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
769 return FALSE;
770 }
771 if(!lpOverlapped) {
772 ::SetLastError(ERROR_INVALID_PARAMETER);
773 return FALSE;
774 }
775 return pDevData->iohandler->GetOverlappedResult(pHMHandleData->hWin32Handle, lpOverlapped, lpcbTransfer, fWait);
776}
777//******************************************************************************
778//******************************************************************************
779BOOL HMDeviceCommClass::GetCommProperties(PHMHANDLEDATA pHMHandleData,
780 LPCOMMPROP lpcmmp)
781{
782 EXTBAUDGET BaudInfo;
783 APIRET rc;
784 ULONG ulLen;
785 USHORT COMErr;
786 int i;
787 dprintf(("HMDeviceCommClass::GetCommProperties"));
788
789 ulLen = sizeof(EXTBAUDGET);
790 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
791 IOCTL_ASYNC,
792 ASYNC_EXTGETBAUDRATE,
793 0,0,0,
794 &BaudInfo,ulLen,&ulLen);
795 memset(lpcmmp,0,sizeof(COMMPROP));
796 lpcmmp->wPacketLength = sizeof(COMMPROP);
797 lpcmmp->wPacketVersion = 1; //???
798 lpcmmp->dwServiceMask = SP_SERIALCOMM;
799 for(i=0;i<BaudTableSize && BaudInfo.ulMaxBaud <= BaudTable[i].dwBaudRate;i++);
800 lpcmmp->dwMaxBaud = BaudTable[i].dwBaudFlag;
801 lpcmmp->dwProvSubType = PST_RS232;
802 lpcmmp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK |
803 PCF_RTSCTS | PCF_SETXCHAR |
804 PCF_XONXOFF;
805 lpcmmp->dwSettableParams = SP_BAUD | SP_DATABITS |
806 SP_HANDSHAKEING | SP_PARITY |
807 SP_PARITY_CHECK | SP_STOPBIT;
808 lpcmmp->dwSettableBaud = 0;
809 for(i=0;i<BaudTableSize;i++)
810 {
811 if ( (BaudTable[i].dwBaudRate>=BaudInfo.ulMinBaud) &&
812 (BaudTable[i].dwBaudRate<=BaudInfo.ulMaxBaud) )
813 lpcmmp->dwSettableBaud |= BaudTable[i].dwBaudFlag;
814 }
815 lpcmmp->dwSettableBaud |= BAUD_USER;
816 lpcmmp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
817 lpcmmp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
818 PARITY_NONE | PARITY_ODD | PARITY_EVEN |
819 PARITY_MARK | PARITY_SPACE;
820 return(rc==0);
821}
822//******************************************************************************
823//******************************************************************************
824BOOL HMDeviceCommClass::GetCommMask( PHMHANDLEDATA pHMHandleData,
825 LPDWORD lpfdwEvtMask)
826{
827 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
828
829 dprintf(("HMDeviceCommClass::GetCommMask"));
830
831 *lpfdwEvtMask = pDevData->dwEventMask;
832 return(TRUE);
833}
834//******************************************************************************
835//******************************************************************************
836BOOL HMDeviceCommClass::SetCommMask( PHMHANDLEDATA pHMHandleData,
837 DWORD fdwEvtMask)
838{
839 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
840 dprintf(("HMDeviceCommClass::SetCommMask %x", fdwEvtMask));
841
842 if(fdwEvtMask & (EV_RXFLAG)) {
843 dprintf(("!WARNING! SetCommMask: unsupported flag EV_RXFLAG!!"));
844 }
845
846 pDevData->dwEventMask = fdwEvtMask & ~(EV_RXFLAG); // Clear the not supported Flag.
847 return(TRUE);
848}
849//******************************************************************************
850//******************************************************************************
851BOOL HMDeviceCommClass::PurgeComm( PHMHANDLEDATA pHMHandleData,
852 DWORD fdwAction)
853{
854 ULONG ulParLen, ulDataLen, rc = ERROR_SUCCESS;
855 BYTE par = 0;
856 WORD data = 0;
857
858 dprintf(("HMDeviceCommClass::PurgeComm (flags 0x%x) partly implemented",fdwAction));
859 // ToDo: find a way to stop the current transmision didn't find
860 // any clue how to in Control Program Guide and reference
861
862 ulParLen = sizeof(par);
863 ulDataLen = sizeof(data);
864 if(fdwAction & PURGE_TXCLEAR) {
865 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
866 IOCTL_GENERAL,
867 DEV_FLUSHOUTPUT,
868 &par,ulParLen,&ulParLen,
869 &data,ulDataLen,&ulDataLen);
870 }
871 if(fdwAction & PURGE_RXCLEAR) {
872 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
873 IOCTL_GENERAL,
874 DEV_FLUSHINPUT,
875 &par,ulParLen,&ulParLen,
876 &data,ulDataLen,&ulDataLen);
877 }
878 if(rc) {
879 dprintf(("!WARNING! OSLibDosDevIOCtl failed with rc %d", rc));
880 }
881 return (rc == ERROR_SUCCESS);
882}
883//******************************************************************************
884//******************************************************************************
885BOOL HMDeviceCommClass::ClearCommError( PHMHANDLEDATA pHMHandleData,
886 LPDWORD lpdwErrors,
887 LPCOMSTAT lpcst)
888{
889 APIRET rc;
890 ULONG ulLen;
891 USHORT COMErr;
892
893 dprintf(("HMDeviceCommClass::ClearCommError"));
894 ulLen = sizeof(USHORT);
895
896 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
897 IOCTL_ASYNC,
898 ASYNC_GETCOMMERROR,
899 0,0,0,
900 &COMErr,2,&ulLen);
901 *lpdwErrors = 0;
902 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
903 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
904 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
905 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
906
907 if(lpcst)
908 {
909 UCHAR ucStatus;
910 RXQUEUE qInfo;
911 ulLen = 1;
912 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
913 IOCTL_ASYNC,
914 ASYNC_GETCOMMSTATUS,
915 0,0,0,
916 &ucStatus,ulLen,&ulLen);
917 if(!rc)
918 {
919 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
920 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
921 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
922 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
923 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
924 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
925 lpcst->fTxim = ((ucStatus & 0x40)>0);
926
927 ulLen = sizeof(qInfo);
928 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
929 IOCTL_ASYNC,
930 ASYNC_GETINQUECOUNT,
931 0,0,0,
932 &qInfo,ulLen,&ulLen);
933 if(!rc)
934 {
935 lpcst->cbInQue = qInfo.cch;
936 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
937 IOCTL_ASYNC,
938 ASYNC_GETOUTQUECOUNT,
939 0,0,0,
940 &qInfo,ulLen,&ulLen);
941 if(!rc)
942 lpcst->cbOutQue = qInfo.cch;
943 }
944 }
945 }
946
947 return(rc==0);
948}
949//******************************************************************************
950//******************************************************************************
951BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData,
952 LPDCB lpDCB)
953{
954 APIRET rc;
955 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
956 DCB *pCurDCB = &pDevData->CommCfg.dcb;
957 dprintf(("HMDeviceCommClass::SetCommState"));
958
959 rc = 0;
960 if(pCurDCB->BaudRate != lpDCB->BaudRate) {
961 dprintf(("SetCommState: change baud rate from %d to %d", pCurDCB->BaudRate, lpDCB->BaudRate));
962 rc = SetBaud( pHMHandleData,
963 lpDCB->BaudRate);
964 }
965
966 if(!rc)
967 {
968 if( (pCurDCB->ByteSize != lpDCB->ByteSize) ||
969 (pCurDCB->Parity != lpDCB->Parity) ||
970 (pCurDCB->StopBits != lpDCB->StopBits))
971 {
972 dprintf(("SetCommState: change line %d %d %d", lpDCB->ByteSize, lpDCB->Parity, lpDCB->StopBits));
973 rc = SetLine( pHMHandleData,
974 lpDCB->ByteSize,
975 lpDCB->Parity,
976 lpDCB->StopBits);
977 }
978 }
979
980 if(!rc)
981 {
982 if( (pCurDCB->fOutxCtsFlow != lpDCB->fOutxCtsFlow) ||
983 (pCurDCB->fOutxDsrFlow != lpDCB->fOutxDsrFlow) ||
984 (pCurDCB->fDtrControl != lpDCB->fDtrControl) ||
985 (pCurDCB->fDsrSensitivity != lpDCB->fDsrSensitivity) ||
986 (pCurDCB->fTXContinueOnXoff != lpDCB->fTXContinueOnXoff) ||
987 (pCurDCB->fOutX != lpDCB->fOutX) ||
988 (pCurDCB->fInX != lpDCB->fInX) ||
989 (pCurDCB->fErrorChar != lpDCB->fErrorChar) ||
990 (pCurDCB->fNull != lpDCB->fNull) ||
991 (pCurDCB->fRtsControl != lpDCB->fRtsControl) ||
992 (pCurDCB->fAbortOnError != lpDCB->fAbortOnError) ||
993 (pCurDCB->XonChar != lpDCB->XonChar) ||
994 (pCurDCB->XoffChar != lpDCB->XoffChar) ||
995 (pCurDCB->ErrorChar != lpDCB->ErrorChar))
996 {
997 dprintf(("SetCommState: change flags cts %d dsr %d dtr %d dsr %d tx %d out %d in %d ferror %d null %d rts %d abort %d xon %d xoff %d error %d", lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,lpDCB->fDtrControl,lpDCB->fDsrSensitivity,lpDCB->fDsrSensitivity,lpDCB->fTXContinueOnXoff,lpDCB->fOutX, lpDCB->fInX,lpDCB->fErrorChar,lpDCB->fNull,lpDCB->fRtsControl,lpDCB->fAbortOnError,lpDCB->XonChar,lpDCB->XoffChar,lpDCB->ErrorChar));
998 SetOS2DCB( pHMHandleData,
999 lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,
1000 lpDCB->fDtrControl, lpDCB->fDsrSensitivity,
1001 lpDCB->fTXContinueOnXoff, lpDCB->fOutX,
1002 lpDCB->fInX, lpDCB->fErrorChar,
1003 lpDCB->fNull, lpDCB->fRtsControl,
1004 lpDCB->fAbortOnError, lpDCB->XonChar,
1005 lpDCB->XoffChar,lpDCB->ErrorChar);
1006 }
1007 }
1008
1009 return(rc==0);
1010}
1011//******************************************************************************
1012//******************************************************************************
1013BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData,
1014 LPDCB lpdcb)
1015{
1016 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1017
1018 dprintf(("HMDeviceCommClass::GetCommState %x", lpdcb));
1019
1020 if(lpdcb == NULL) {
1021 ::SetLastError(ERROR_INVALID_PARAMETER);
1022 return FALSE;
1023 }
1024
1025 memcpy(lpdcb,&pDevData->CommCfg.dcb,sizeof(DCB));
1026 return(TRUE);
1027}
1028//******************************************************************************
1029//******************************************************************************
1030BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData,
1031 LPDWORD lpModemStat )
1032{
1033 APIRET rc;
1034 ULONG ulLen;
1035 USHORT COMErr;
1036 UCHAR ucStatus;
1037
1038 dprintf(("HMDeviceCommClass::GetCommModemStatus %x", lpModemStat));
1039 if(lpModemStat == NULL) {
1040 ::SetLastError(ERROR_INVALID_PARAMETER);
1041 return FALSE;
1042 }
1043
1044 ulLen = sizeof(CHAR);
1045
1046 ulLen = 1;
1047 *lpModemStat = 0;
1048
1049 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1050 IOCTL_ASYNC,
1051 ASYNC_GETMODEMINPUT,
1052 0,0,0,
1053 &ucStatus,ulLen,&ulLen);
1054 if(!rc)
1055 {
1056 *lpModemStat |= (ucStatus & 0x10)? MS_CTS_ON:0;
1057 *lpModemStat |= (ucStatus & 0x20)? MS_DSR_ON:0;
1058 *lpModemStat |= (ucStatus & 0x40)? MS_RING_ON:0;
1059 *lpModemStat |= (ucStatus & 0x80)? MS_RLSD_ON:0;
1060 }
1061
1062 dprintf2(("HMDeviceCommClass::GetCommModemStatus -> %s %x rc=%d", DebugModemStatus(*lpModemStat), *lpModemStat, rc));
1063 return(rc==0);
1064}
1065//******************************************************************************
1066//******************************************************************************
1067BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1068 LPCOMMTIMEOUTS lpctmo)
1069{
1070 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1071
1072 dprintf(("HMDeviceCommClass::GetCommTimeouts %x stub", lpctmo));
1073
1074 if(lpctmo == NULL) {
1075 ::SetLastError(ERROR_INVALID_PARAMETER);
1076 return FALSE;
1077 }
1078
1079 memcpy( lpctmo,
1080 &pDevData->CommTOuts,
1081 sizeof(COMMTIMEOUTS));
1082 return(TRUE);
1083}
1084//******************************************************************************
1085//******************************************************************************
1086BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1087 LPCOMMTIMEOUTS lpctmo)
1088{
1089 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1090 DCBINFO os2dcb;
1091 ULONG ulLen;
1092 APIRET rc;
1093 UCHAR fbTimeOut;
1094
1095 if(lpctmo == NULL) {
1096 dprintf(("!WARNING! HMDeviceCommClass::SetCommTimeouts %x -> invalid parameter", lpctmo));
1097 ::SetLastError(ERROR_INVALID_PARAMETER);
1098 return FALSE;
1099 }
1100
1101 dprintf(("HMDeviceCommClass::SetCommTimeouts\n"
1102 " ReadIntervalTimeout : 0x%x\n"
1103 " ReadTotalTimeoutMultiplier : %d\n"
1104 " ReadTotalTimeoutConstant : %d\n"
1105 " WriteTotalTimeoutMultiplier : %d\n"
1106 " WriteTotalTimeoutConstant : %d\n",
1107 lpctmo->ReadIntervalTimeout,
1108 lpctmo->ReadTotalTimeoutMultiplier,
1109 lpctmo->ReadTotalTimeoutConstant,
1110 lpctmo->WriteTotalTimeoutMultiplier,
1111 lpctmo->WriteTotalTimeoutConstant
1112 ));
1113
1114 memcpy( &pDevData->CommTOuts,
1115 lpctmo,
1116 sizeof(COMMTIMEOUTS));
1117
1118 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1119
1120 fbTimeOut = 0x02; //normal processing (wait until timout or buffer full)
1121 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1122 {
1123 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1124 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1125 fbTimeOut = 0x05; //no wait
1126 else
1127 fbTimeOut = 0x04; //wait for something
1128 }
1129 else
1130 {
1131 DWORD dwTimeout;
1132 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1133 if(dwTimeout)
1134 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1135
1136 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1137 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1138 }
1139 if( (0==pDevData->CommTOuts.WriteTotalTimeoutMultiplier) &&
1140 (0==pDevData->CommTOuts.WriteTotalTimeoutConstant))
1141 {//no timeout used for writing
1142 os2dcb.fbTimeOut |= 1; //write infinite timeout
1143 }
1144
1145 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF8) | fbTimeOut;
1146
1147 dprintf((" New DCB:\n"
1148 " WriteTimeout : %d\n"
1149 " ReadTimeout : %d\n"
1150 " CtlHandshake : 0x%x\n"
1151 " FlowReplace : 0x%x\n"
1152 " Timeout : 0x%x\n"
1153 " Error replacement Char : 0x%x\n"
1154 " Break replacement Char : 0x%x\n"
1155 " XON Char : 0x%x\n"
1156 " XOFF Char : 0x%x\n",
1157 os2dcb.usWriteTimeout,
1158 os2dcb.usReadTimeout,
1159 os2dcb.fbCtlHndShake,
1160 os2dcb.fbFlowReplace,
1161 os2dcb.fbTimeOut,
1162 os2dcb.bErrorReplacementChar,
1163 os2dcb.bBreakReplacementChar,
1164 os2dcb.bXONChar,
1165 os2dcb.bXOFFChar));
1166
1167 ulLen = sizeof(DCBINFO);
1168 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1169 IOCTL_ASYNC,
1170 ASYNC_SETDCBINFO,
1171 &os2dcb,ulLen,&ulLen,
1172 NULL,0,NULL);
1173 dprintf(("IOCRL returned %d",rc));
1174 return(0==rc);
1175}
1176//******************************************************************************
1177//******************************************************************************
1178BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData,
1179 CHAR cChar )
1180{
1181 APIRET rc;
1182 ULONG ulLen;
1183 USHORT COMErr;
1184
1185 dprintf(("HMDeviceCommClass::TransmitCommChar"));
1186 ulLen = sizeof(CHAR);
1187
1188 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1189 IOCTL_ASYNC,
1190 ASYNC_TRANSMITIMM,
1191 &cChar,ulLen,&ulLen,
1192 NULL,0,NULL);
1193
1194 return(rc==0);
1195}
1196//******************************************************************************
1197//******************************************************************************
1198BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData )
1199{
1200 APIRET rc;
1201 ULONG ulLen;
1202 USHORT COMErr;
1203
1204 dprintf(("HMDeviceCommClass::SetCommBreak"));
1205 ulLen = sizeof(USHORT);
1206
1207 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1208 IOCTL_ASYNC,
1209 ASYNC_SETBREAKON,
1210 0,0,0,
1211 &COMErr,2,&ulLen);
1212
1213 return(rc==0);
1214}
1215//******************************************************************************
1216//******************************************************************************
1217BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData)
1218{
1219 APIRET rc;
1220 ULONG ulLen;
1221 USHORT COMErr;
1222
1223 dprintf(("HMDeviceCommClass::ClearCommBreak"));
1224 ulLen = sizeof(USHORT);
1225
1226 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1227 IOCTL_ASYNC,
1228 ASYNC_SETBREAKOFF,
1229 0,0,0,
1230 &COMErr,2,&ulLen);
1231
1232 return(rc==0);
1233}
1234//******************************************************************************
1235//******************************************************************************
1236BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
1237 LPCOMMCONFIG lpCC,
1238 DWORD dwSize )
1239{
1240 dprintf(("HMDeviceCommClass::SetCommConfig NOT IMPLEMENTED"));
1241
1242 return(TRUE);
1243}
1244//******************************************************************************
1245//******************************************************************************
1246BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
1247 LPCOMMCONFIG lpCC,
1248 LPDWORD lpdwSize )
1249{
1250 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1251
1252 dprintf(("HMDeviceCommClass::GetCommConfig"));
1253
1254 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1255 *lpdwSize< sizeof(COMMCONFIG) )
1256 {
1257 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1258 *lpdwSize= sizeof(COMMCONFIG);
1259 return FALSE;
1260 }
1261
1262 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1263 {
1264 ::SetLastError(ERROR_INVALID_HANDLE);
1265 return FALSE;
1266 }
1267
1268 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1269 *lpdwSize = sizeof(COMMCONFIG);
1270 return(TRUE);
1271}
1272//******************************************************************************
1273//******************************************************************************
1274BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData,
1275 UINT dwFunc )
1276{
1277 APIRET rc;
1278 ULONG ulDLen,ulPLen;
1279 USHORT COMErr;
1280 MODEMSTATUS mdm;
1281
1282 dprintf(("HMDeviceCommClass::EscapeCommFunction %x", dwFunc));
1283
1284 ulDLen = sizeof(USHORT);
1285 ulPLen = sizeof(MODEMSTATUS);
1286 switch(dwFunc)
1287 {
1288 case CLRDTR:
1289 mdm.fbModemOn = 0x00;
1290 mdm.fbModemOff = 0XFE;
1291 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1292 IOCTL_ASYNC,
1293 ASYNC_SETMODEMCTRL,
1294 &mdm,ulPLen,&ulPLen,
1295 &COMErr,ulDLen,&ulDLen);
1296 dprintf(("CLRDTR rc = %d Comerror = 0x%x",rc,COMErr));
1297 rc = COMErr;
1298 if(rc==0)
1299 {
1300 BYTE bModem;
1301 ulDLen = sizeof(BYTE);
1302 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1303 IOCTL_ASYNC,
1304 ASYNC_GETMODEMOUTPUT,
1305 NULL,0,NULL,
1306 &bModem,ulDLen,&ulDLen);
1307 dprintf(("Check DTR rc = %d Flags = 0x%x",rc,bModem));
1308 rc = bModem & 0x01;
1309 }
1310 break;
1311 case CLRRTS:
1312 mdm.fbModemOn = 0x00;
1313 mdm.fbModemOff = 0XFD;
1314 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1315 IOCTL_ASYNC,
1316 ASYNC_SETMODEMCTRL,
1317 &mdm,ulPLen,&ulPLen,
1318 &COMErr,ulDLen,&ulDLen);
1319 dprintf(("CLRRTS: rc = %d, Comm error %x", rc, COMErr));
1320 break;
1321 case SETDTR:
1322 mdm.fbModemOn = 0x01;
1323 mdm.fbModemOff = 0XFF;
1324 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1325 IOCTL_ASYNC,
1326 ASYNC_SETMODEMCTRL,
1327 &mdm,ulPLen,&ulPLen,
1328 &COMErr,ulDLen,&ulDLen);
1329 dprintf(("SETDTR: rc = %d, Comm error %x", rc, COMErr));
1330 break;
1331 case SETRTS:
1332 mdm.fbModemOn = 0x02;
1333 mdm.fbModemOff = 0XFF;
1334 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1335 IOCTL_ASYNC,
1336 ASYNC_SETMODEMCTRL,
1337 &mdm,ulPLen,&ulPLen,
1338 &COMErr,ulDLen,&ulDLen);
1339 dprintf(("SETRTS: rc = %d, Comm error %x", rc, COMErr));
1340 break;
1341 case SETXOFF:
1342 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1343 IOCTL_ASYNC,
1344 ASYNC_STOPTRANSMIT,
1345 0,0,0,
1346 0,0,0);
1347 dprintf(("SETXOFF: rc = %d", rc));
1348 break;
1349 case SETXON:
1350 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1351 IOCTL_ASYNC,
1352 ASYNC_STARTTRANSMIT,
1353 0,0,0,
1354 0,0,0);
1355 dprintf(("SETXON: rc = %d", rc));
1356 break;
1357 default:
1358 dprintf(("!ERROR!: EscapeCommFunction: unknown function"));
1359 ::SetLastError(ERROR_INVALID_PARAMETER);
1360 return(FALSE);
1361 }
1362
1363 return(rc==0);
1364}
1365//******************************************************************************
1366//******************************************************************************
1367BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1368 LPCOMMCONFIG lpCC,
1369 DWORD dwSize)
1370{
1371 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1372 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1373 {
1374 ::SetLastError(ERROR_INVALID_HANDLE);
1375 return FALSE;
1376 }
1377
1378 dprintf(("SetDefaultCommConfig %x %d", lpCC, dwSize));
1379 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
1380 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
1381
1382 return(TRUE);
1383}
1384//******************************************************************************
1385//******************************************************************************
1386BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1387 LPCOMMCONFIG lpCC,
1388 LPDWORD lpdwSize)
1389{
1390 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1391
1392 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1393 *lpdwSize< sizeof(COMMCONFIG) )
1394 {
1395 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1396 *lpdwSize= sizeof(COMMCONFIG);
1397 return FALSE;
1398 }
1399
1400 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1401 {
1402 ::SetLastError(ERROR_INVALID_HANDLE);
1403 return FALSE;
1404 }
1405 dprintf(("GetDefaultCommConfig %x %x", lpCC, lpdwSize));
1406
1407 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1408 *lpdwSize = sizeof(COMMCONFIG);
1409 return(TRUE);
1410}
1411//******************************************************************************
1412//******************************************************************************
1413APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData,
1414 UCHAR ucSize,
1415 UCHAR ucParity,
1416 UCHAR ucStop)
1417{
1418 APIRET rc;
1419 ULONG ulLen;
1420 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1421 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1422 struct
1423 {
1424 UCHAR ucSize;
1425 UCHAR ucParity;
1426 UCHAR ucStop;
1427 UCHAR ucPadding;
1428 }Param;
1429
1430 ulLen = 3;
1431 Param.ucSize = ucSize;
1432 Param.ucParity = ucParity;
1433 Param.ucStop = ucStop;
1434
1435 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1436 IOCTL_ASYNC,
1437 ASYNC_SETLINECTRL,
1438 &Param,ulLen,&ulLen,
1439 NULL,0,NULL);
1440
1441 if(0==rc)
1442 {
1443 pCurDCB->ByteSize = ucSize;
1444 pCurDCB->Parity = ucParity;
1445 pCurDCB->StopBits = ucStop;
1446 }
1447 else {
1448 dprintf(("!ERROR! SetLine: OSLibDosDevIOCtl failed with rc %d", rc));
1449 }
1450 return rc;
1451}
1452//******************************************************************************
1453//******************************************************************************
1454APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData,
1455 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow,
1456 UCHAR ucDtrControl, BOOL fDsrSensitivity,
1457 BOOL fTXContinueOnXoff, BOOL fOutX,
1458 BOOL fInX, BOOL fErrorChar,
1459 BOOL fNull, UCHAR ucRtsControl,
1460 BOOL fAbortOnError, BYTE XonChar,
1461 BYTE XoffChar,BYTE ErrorChar)
1462{
1463 APIRET rc;
1464 ULONG ulLen;
1465 DCBINFO os2dcb;
1466 UCHAR fbTimeOut;
1467 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1468 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1469
1470 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1471 os2dcb.fbCtlHndShake = (ucDtrControl & 0x03) |
1472 (fOutxCtsFlow?0x08:0x00) |
1473 (fOutxDsrFlow?0x10:0x00) |
1474 // No DCD support in Win32 ?!
1475 (fDsrSensitivity?0x40:0x00);
1476 os2dcb.fbFlowReplace = (fOutX?0x01:0x00) |
1477 (fInX?0x02:0x00) |
1478 (fErrorChar?0x04:0x00)|
1479 (fNull?0x08:0x00)|
1480 (fTXContinueOnXoff?0x02:0x00)| // Not sure if thats the right flag to test
1481 (ucRtsControl<<6);
1482
1483 fbTimeOut = 0x02;
1484 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1485 {
1486 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1487 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1488 fbTimeOut = 0x05;
1489 else
1490 fbTimeOut = 0x04;
1491 }
1492 else
1493 {
1494 DWORD dwTimeout;
1495 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1496 if(dwTimeout)
1497 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1498 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1499 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1500 }
1501 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF9) | fbTimeOut;
1502 os2dcb.bErrorReplacementChar = ErrorChar;
1503 os2dcb.bXONChar = XonChar;
1504 os2dcb.bXOFFChar = XoffChar;
1505 ulLen = sizeof(DCBINFO);
1506 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1507 IOCTL_ASYNC,
1508 ASYNC_SETDCBINFO,
1509 &os2dcb,ulLen,&ulLen,
1510 NULL,0,NULL);
1511
1512 if(0==rc)
1513 {
1514 memcpy(&pDevData->dcbOS2,&os2dcb,sizeof(DCBINFO));
1515 pCurDCB->fOutxCtsFlow = fOutxCtsFlow;
1516 pCurDCB->fOutxDsrFlow = fOutxDsrFlow;
1517 pCurDCB->fDtrControl = ucDtrControl;
1518 pCurDCB->fDsrSensitivity = fDsrSensitivity;
1519 pCurDCB->fTXContinueOnXoff = fTXContinueOnXoff;
1520 pCurDCB->fOutX = fOutX;
1521 pCurDCB->fInX = fInX;
1522 pCurDCB->fErrorChar = fErrorChar;
1523 pCurDCB->fNull = fNull;
1524 pCurDCB->fRtsControl = ucRtsControl;
1525 pCurDCB->fAbortOnError = fAbortOnError;
1526 pCurDCB->XonChar = XonChar;
1527 pCurDCB->XoffChar = XoffChar;
1528 pCurDCB->ErrorChar = ErrorChar;
1529 }
1530
1531 return rc;
1532
1533}
1534//******************************************************************************
1535//******************************************************************************
1536APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData,
1537 DWORD dwNewBaud)
1538{
1539 APIRET rc;
1540 ULONG ulLen;
1541 EXTBAUDSET SetBaud;
1542 EXTBAUDGET GetBaud;
1543 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1544
1545 ulLen = sizeof(SetBaud);
1546 SetBaud.ulBaud = dwNewBaud;
1547 SetBaud.ucFrac = 0;
1548 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1549 IOCTL_ASYNC,
1550 ASYNC_EXTSETBAUDRATE,
1551 &SetBaud,ulLen,&ulLen,
1552 NULL,0,NULL);
1553 if(0==rc)
1554 {
1555 ulLen = sizeof(GetBaud);
1556 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1557 IOCTL_ASYNC,
1558 ASYNC_EXTGETBAUDRATE,
1559 NULL,0,NULL,
1560 &GetBaud,ulLen,&ulLen);
1561 if(0==rc)
1562 {
1563 if(dwNewBaud != GetBaud.ulCurrBaud) {
1564 dprintf(("!WARNING! dwNewBaud (%d) != GetBaud.ulCurrBaud (%d)", dwNewBaud, GetBaud.ulCurrBaud));
1565 rc = 1; // ToDo set a proper Errorhandling
1566 }
1567 else
1568 {
1569 pDevData->CommCfg.dcb.BaudRate = dwNewBaud;
1570 }
1571 }
1572 else {
1573 dprintf(("!WARNING! SetBaud: (get) OSLibDosDevIOCtl failed with rc %d", rc));
1574 }
1575 }
1576 else {
1577 dprintf(("!WARNING! SetBaud: (set) OSLibDosDevIOCtl failed with rc %d", rc));
1578 }
1579 return rc;
1580}
1581//******************************************************************************
1582//******************************************************************************
1583void HMDeviceCommClass::CloseOverlappedIOHandlers()
1584{
1585 for(int i=0;i<MAX_COMPORTS;i++) {
1586 if(handler[i]) {
1587 handler[i]->Release(TRUE);
1588 handler[i] = NULL;
1589 }
1590 }
1591}
1592#ifdef DEBUG
1593//******************************************************************************
1594//******************************************************************************
1595static char *DebugCommEvent(DWORD dwEvents)
1596{
1597 static char szCommEvents[128];
1598
1599 szCommEvents[0] = 0;
1600
1601 if(dwEvents & EV_RXCHAR) {
1602 strcat(szCommEvents, "EV_RXCHAR ");
1603 }
1604 if(dwEvents & EV_TXEMPTY) {
1605 strcat(szCommEvents, "EV_TXEMPTY ");
1606 }
1607 if(dwEvents & EV_CTS) {
1608 strcat(szCommEvents, "EV_CTS ");
1609 }
1610 if(dwEvents & EV_DSR) {
1611 strcat(szCommEvents, "EV_DSR ");
1612 }
1613 if(dwEvents & EV_RLSD) {
1614 strcat(szCommEvents, "EV_RLSD ");
1615 }
1616 if(dwEvents & EV_BREAK) {
1617 strcat(szCommEvents, "EV_BREAK ");
1618 }
1619 if(dwEvents & EV_ERR) {
1620 strcat(szCommEvents, "EV_ERR ");
1621 }
1622 if(dwEvents & EV_RING) {
1623 strcat(szCommEvents, "EV_RING ");
1624 }
1625 return szCommEvents;
1626}
1627//******************************************************************************
1628//******************************************************************************
1629static char *DebugModemStatus(DWORD dwModemStatus)
1630{
1631 static char szModemStatus[128];
1632
1633 szModemStatus[0] = 0;
1634
1635 if(dwModemStatus & MS_CTS_ON) {
1636 strcat(szModemStatus, "MS_CTS_ON ");
1637 }
1638 if(dwModemStatus & MS_DSR_ON) {
1639 strcat(szModemStatus, "MS_DSR_ON ");
1640 }
1641 if(dwModemStatus & MS_RING_ON) {
1642 strcat(szModemStatus, "MS_RING_ON ");
1643 }
1644 if(dwModemStatus & MS_RLSD_ON) {
1645 strcat(szModemStatus, "MS_RLSD_ON ");
1646 }
1647 return szModemStatus;
1648}
1649#endif
1650//******************************************************************************
1651//******************************************************************************
1652OverlappedIOHandler *HMDeviceCommClass::handler[MAX_COMPORTS] = {NULL};
1653
Note: See TracBrowser for help on using the repository browser.