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

Last change on this file since 10109 was 10109, checked in by sandervl, 22 years ago

ClearCommError: lpdwError is allowed to be NULL

File size: 58.1 KB
Line 
1/* $Id: hmcomm.cpp,v 1.39 2003-05-23 13:53:43 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, dwError = 0;
891 USHORT COMErr;
892
893 if(lpdwErrors == NULL)
894 lpdwErrors = &dwError;
895
896 dprintf(("HMDeviceCommClass::ClearCommError"));
897 ulLen = sizeof(USHORT);
898
899 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
900 IOCTL_ASYNC,
901 ASYNC_GETCOMMERROR,
902 0,0,0,
903 &COMErr,2,&ulLen);
904 *lpdwErrors = 0;
905 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
906 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
907 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
908 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
909
910 if(lpcst)
911 {
912 UCHAR ucStatus;
913 RXQUEUE qInfo;
914 ulLen = 1;
915 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
916 IOCTL_ASYNC,
917 ASYNC_GETCOMMSTATUS,
918 0,0,0,
919 &ucStatus,ulLen,&ulLen);
920 if(!rc)
921 {
922 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
923 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
924 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
925 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
926 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
927 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
928 lpcst->fTxim = ((ucStatus & 0x40)>0);
929
930 ulLen = sizeof(qInfo);
931 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
932 IOCTL_ASYNC,
933 ASYNC_GETINQUECOUNT,
934 0,0,0,
935 &qInfo,ulLen,&ulLen);
936 if(!rc)
937 {
938 lpcst->cbInQue = qInfo.cch;
939 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
940 IOCTL_ASYNC,
941 ASYNC_GETOUTQUECOUNT,
942 0,0,0,
943 &qInfo,ulLen,&ulLen);
944 if(!rc)
945 lpcst->cbOutQue = qInfo.cch;
946 }
947 }
948 }
949
950 return(rc==0);
951}
952//******************************************************************************
953//******************************************************************************
954BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData,
955 LPDCB lpDCB)
956{
957 APIRET rc;
958 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
959 DCB *pCurDCB = &pDevData->CommCfg.dcb;
960 dprintf(("HMDeviceCommClass::SetCommState"));
961
962 rc = 0;
963 if(pCurDCB->BaudRate != lpDCB->BaudRate) {
964 dprintf(("SetCommState: change baud rate from %d to %d", pCurDCB->BaudRate, lpDCB->BaudRate));
965 rc = SetBaud( pHMHandleData,
966 lpDCB->BaudRate);
967 }
968
969 if(!rc)
970 {
971 if( (pCurDCB->ByteSize != lpDCB->ByteSize) ||
972 (pCurDCB->Parity != lpDCB->Parity) ||
973 (pCurDCB->StopBits != lpDCB->StopBits))
974 {
975 dprintf(("SetCommState: change line %d %d %d", lpDCB->ByteSize, lpDCB->Parity, lpDCB->StopBits));
976 rc = SetLine( pHMHandleData,
977 lpDCB->ByteSize,
978 lpDCB->Parity,
979 lpDCB->StopBits);
980 }
981 }
982
983 if(!rc)
984 {
985 if( (pCurDCB->fOutxCtsFlow != lpDCB->fOutxCtsFlow) ||
986 (pCurDCB->fOutxDsrFlow != lpDCB->fOutxDsrFlow) ||
987 (pCurDCB->fDtrControl != lpDCB->fDtrControl) ||
988 (pCurDCB->fDsrSensitivity != lpDCB->fDsrSensitivity) ||
989 (pCurDCB->fTXContinueOnXoff != lpDCB->fTXContinueOnXoff) ||
990 (pCurDCB->fOutX != lpDCB->fOutX) ||
991 (pCurDCB->fInX != lpDCB->fInX) ||
992 (pCurDCB->fErrorChar != lpDCB->fErrorChar) ||
993 (pCurDCB->fNull != lpDCB->fNull) ||
994 (pCurDCB->fRtsControl != lpDCB->fRtsControl) ||
995 (pCurDCB->fAbortOnError != lpDCB->fAbortOnError) ||
996 (pCurDCB->XonChar != lpDCB->XonChar) ||
997 (pCurDCB->XoffChar != lpDCB->XoffChar) ||
998 (pCurDCB->ErrorChar != lpDCB->ErrorChar))
999 {
1000 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));
1001 SetOS2DCB( pHMHandleData,
1002 lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,
1003 lpDCB->fDtrControl, lpDCB->fDsrSensitivity,
1004 lpDCB->fTXContinueOnXoff, lpDCB->fOutX,
1005 lpDCB->fInX, lpDCB->fErrorChar,
1006 lpDCB->fNull, lpDCB->fRtsControl,
1007 lpDCB->fAbortOnError, lpDCB->XonChar,
1008 lpDCB->XoffChar,lpDCB->ErrorChar);
1009 }
1010 }
1011
1012 return(rc==0);
1013}
1014//******************************************************************************
1015//******************************************************************************
1016BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData,
1017 LPDCB lpdcb)
1018{
1019 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1020
1021 dprintf(("HMDeviceCommClass::GetCommState %x", lpdcb));
1022
1023 if(lpdcb == NULL) {
1024 ::SetLastError(ERROR_INVALID_PARAMETER);
1025 return FALSE;
1026 }
1027
1028 memcpy(lpdcb,&pDevData->CommCfg.dcb,sizeof(DCB));
1029 return(TRUE);
1030}
1031//******************************************************************************
1032//******************************************************************************
1033BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData,
1034 LPDWORD lpModemStat )
1035{
1036 APIRET rc;
1037 ULONG ulLen;
1038 USHORT COMErr;
1039 UCHAR ucStatus;
1040
1041 dprintf(("HMDeviceCommClass::GetCommModemStatus %x", lpModemStat));
1042 if(lpModemStat == NULL) {
1043 ::SetLastError(ERROR_INVALID_PARAMETER);
1044 return FALSE;
1045 }
1046
1047 ulLen = sizeof(CHAR);
1048
1049 ulLen = 1;
1050 *lpModemStat = 0;
1051
1052 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1053 IOCTL_ASYNC,
1054 ASYNC_GETMODEMINPUT,
1055 0,0,0,
1056 &ucStatus,ulLen,&ulLen);
1057 if(!rc)
1058 {
1059 *lpModemStat |= (ucStatus & 0x10)? MS_CTS_ON:0;
1060 *lpModemStat |= (ucStatus & 0x20)? MS_DSR_ON:0;
1061 *lpModemStat |= (ucStatus & 0x40)? MS_RING_ON:0;
1062 *lpModemStat |= (ucStatus & 0x80)? MS_RLSD_ON:0;
1063 }
1064
1065 dprintf2(("HMDeviceCommClass::GetCommModemStatus -> %s %x rc=%d", DebugModemStatus(*lpModemStat), *lpModemStat, rc));
1066 return(rc==0);
1067}
1068//******************************************************************************
1069//******************************************************************************
1070BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1071 LPCOMMTIMEOUTS lpctmo)
1072{
1073 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1074
1075 dprintf(("HMDeviceCommClass::GetCommTimeouts %x stub", lpctmo));
1076
1077 if(lpctmo == NULL) {
1078 ::SetLastError(ERROR_INVALID_PARAMETER);
1079 return FALSE;
1080 }
1081
1082 memcpy( lpctmo,
1083 &pDevData->CommTOuts,
1084 sizeof(COMMTIMEOUTS));
1085 return(TRUE);
1086}
1087//******************************************************************************
1088//******************************************************************************
1089BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1090 LPCOMMTIMEOUTS lpctmo)
1091{
1092 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1093 DCBINFO os2dcb;
1094 ULONG ulLen;
1095 APIRET rc;
1096 UCHAR fbTimeOut;
1097
1098 if(lpctmo == NULL) {
1099 dprintf(("!WARNING! HMDeviceCommClass::SetCommTimeouts %x -> invalid parameter", lpctmo));
1100 ::SetLastError(ERROR_INVALID_PARAMETER);
1101 return FALSE;
1102 }
1103
1104 dprintf(("HMDeviceCommClass::SetCommTimeouts\n"
1105 " ReadIntervalTimeout : 0x%x\n"
1106 " ReadTotalTimeoutMultiplier : %d\n"
1107 " ReadTotalTimeoutConstant : %d\n"
1108 " WriteTotalTimeoutMultiplier : %d\n"
1109 " WriteTotalTimeoutConstant : %d\n",
1110 lpctmo->ReadIntervalTimeout,
1111 lpctmo->ReadTotalTimeoutMultiplier,
1112 lpctmo->ReadTotalTimeoutConstant,
1113 lpctmo->WriteTotalTimeoutMultiplier,
1114 lpctmo->WriteTotalTimeoutConstant
1115 ));
1116
1117 memcpy( &pDevData->CommTOuts,
1118 lpctmo,
1119 sizeof(COMMTIMEOUTS));
1120
1121 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1122
1123 fbTimeOut = 0x02; //normal processing (wait until timout or buffer full)
1124 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1125 {
1126 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1127 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1128 fbTimeOut = 0x05; //no wait
1129 else
1130 fbTimeOut = 0x04; //wait for something
1131 }
1132 else
1133 {
1134 DWORD dwTimeout;
1135 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1136 if(dwTimeout)
1137 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1138
1139 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1140 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1141 }
1142 if( (0==pDevData->CommTOuts.WriteTotalTimeoutMultiplier) &&
1143 (0==pDevData->CommTOuts.WriteTotalTimeoutConstant))
1144 {//no timeout used for writing
1145 os2dcb.fbTimeOut |= 1; //write infinite timeout
1146 }
1147
1148 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF8) | fbTimeOut;
1149
1150 dprintf((" New DCB:\n"
1151 " WriteTimeout : %d\n"
1152 " ReadTimeout : %d\n"
1153 " CtlHandshake : 0x%x\n"
1154 " FlowReplace : 0x%x\n"
1155 " Timeout : 0x%x\n"
1156 " Error replacement Char : 0x%x\n"
1157 " Break replacement Char : 0x%x\n"
1158 " XON Char : 0x%x\n"
1159 " XOFF Char : 0x%x\n",
1160 os2dcb.usWriteTimeout,
1161 os2dcb.usReadTimeout,
1162 os2dcb.fbCtlHndShake,
1163 os2dcb.fbFlowReplace,
1164 os2dcb.fbTimeOut,
1165 os2dcb.bErrorReplacementChar,
1166 os2dcb.bBreakReplacementChar,
1167 os2dcb.bXONChar,
1168 os2dcb.bXOFFChar));
1169
1170 ulLen = sizeof(DCBINFO);
1171 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1172 IOCTL_ASYNC,
1173 ASYNC_SETDCBINFO,
1174 &os2dcb,ulLen,&ulLen,
1175 NULL,0,NULL);
1176 dprintf(("IOCRL returned %d",rc));
1177 return(0==rc);
1178}
1179//******************************************************************************
1180//******************************************************************************
1181BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData,
1182 CHAR cChar )
1183{
1184 APIRET rc;
1185 ULONG ulLen;
1186 USHORT COMErr;
1187
1188 dprintf(("HMDeviceCommClass::TransmitCommChar"));
1189 ulLen = sizeof(CHAR);
1190
1191 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1192 IOCTL_ASYNC,
1193 ASYNC_TRANSMITIMM,
1194 &cChar,ulLen,&ulLen,
1195 NULL,0,NULL);
1196
1197 return(rc==0);
1198}
1199//******************************************************************************
1200//******************************************************************************
1201BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData )
1202{
1203 APIRET rc;
1204 ULONG ulLen;
1205 USHORT COMErr;
1206
1207 dprintf(("HMDeviceCommClass::SetCommBreak"));
1208 ulLen = sizeof(USHORT);
1209
1210 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1211 IOCTL_ASYNC,
1212 ASYNC_SETBREAKON,
1213 0,0,0,
1214 &COMErr,2,&ulLen);
1215
1216 return(rc==0);
1217}
1218//******************************************************************************
1219//******************************************************************************
1220BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData)
1221{
1222 APIRET rc;
1223 ULONG ulLen;
1224 USHORT COMErr;
1225
1226 dprintf(("HMDeviceCommClass::ClearCommBreak"));
1227 ulLen = sizeof(USHORT);
1228
1229 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1230 IOCTL_ASYNC,
1231 ASYNC_SETBREAKOFF,
1232 0,0,0,
1233 &COMErr,2,&ulLen);
1234
1235 return(rc==0);
1236}
1237//******************************************************************************
1238//******************************************************************************
1239BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
1240 LPCOMMCONFIG lpCC,
1241 DWORD dwSize )
1242{
1243 dprintf(("HMDeviceCommClass::SetCommConfig NOT IMPLEMENTED"));
1244
1245 return(TRUE);
1246}
1247//******************************************************************************
1248//******************************************************************************
1249BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
1250 LPCOMMCONFIG lpCC,
1251 LPDWORD lpdwSize )
1252{
1253 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1254
1255 dprintf(("HMDeviceCommClass::GetCommConfig"));
1256
1257 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1258 *lpdwSize< sizeof(COMMCONFIG) )
1259 {
1260 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1261 *lpdwSize= sizeof(COMMCONFIG);
1262 return FALSE;
1263 }
1264
1265 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1266 {
1267 ::SetLastError(ERROR_INVALID_HANDLE);
1268 return FALSE;
1269 }
1270
1271 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1272 *lpdwSize = sizeof(COMMCONFIG);
1273 return(TRUE);
1274}
1275//******************************************************************************
1276//******************************************************************************
1277BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData,
1278 UINT dwFunc )
1279{
1280 APIRET rc;
1281 ULONG ulDLen,ulPLen;
1282 USHORT COMErr;
1283 MODEMSTATUS mdm;
1284
1285 dprintf(("HMDeviceCommClass::EscapeCommFunction %x", dwFunc));
1286
1287 ulDLen = sizeof(USHORT);
1288 ulPLen = sizeof(MODEMSTATUS);
1289 switch(dwFunc)
1290 {
1291 case CLRDTR:
1292 mdm.fbModemOn = 0x00;
1293 mdm.fbModemOff = 0XFE;
1294 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1295 IOCTL_ASYNC,
1296 ASYNC_SETMODEMCTRL,
1297 &mdm,ulPLen,&ulPLen,
1298 &COMErr,ulDLen,&ulDLen);
1299 dprintf(("CLRDTR rc = %d Comerror = 0x%x",rc,COMErr));
1300 rc = COMErr;
1301 if(rc==0)
1302 {
1303 BYTE bModem;
1304 ulDLen = sizeof(BYTE);
1305 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1306 IOCTL_ASYNC,
1307 ASYNC_GETMODEMOUTPUT,
1308 NULL,0,NULL,
1309 &bModem,ulDLen,&ulDLen);
1310 dprintf(("Check DTR rc = %d Flags = 0x%x",rc,bModem));
1311 rc = bModem & 0x01;
1312 }
1313 break;
1314 case CLRRTS:
1315 mdm.fbModemOn = 0x00;
1316 mdm.fbModemOff = 0XFD;
1317 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1318 IOCTL_ASYNC,
1319 ASYNC_SETMODEMCTRL,
1320 &mdm,ulPLen,&ulPLen,
1321 &COMErr,ulDLen,&ulDLen);
1322 dprintf(("CLRRTS: rc = %d, Comm error %x", rc, COMErr));
1323 break;
1324 case SETDTR:
1325 mdm.fbModemOn = 0x01;
1326 mdm.fbModemOff = 0XFF;
1327 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1328 IOCTL_ASYNC,
1329 ASYNC_SETMODEMCTRL,
1330 &mdm,ulPLen,&ulPLen,
1331 &COMErr,ulDLen,&ulDLen);
1332 dprintf(("SETDTR: rc = %d, Comm error %x", rc, COMErr));
1333 break;
1334 case SETRTS:
1335 mdm.fbModemOn = 0x02;
1336 mdm.fbModemOff = 0XFF;
1337 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1338 IOCTL_ASYNC,
1339 ASYNC_SETMODEMCTRL,
1340 &mdm,ulPLen,&ulPLen,
1341 &COMErr,ulDLen,&ulDLen);
1342 dprintf(("SETRTS: rc = %d, Comm error %x", rc, COMErr));
1343 break;
1344 case SETXOFF:
1345 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1346 IOCTL_ASYNC,
1347 ASYNC_STOPTRANSMIT,
1348 0,0,0,
1349 0,0,0);
1350 dprintf(("SETXOFF: rc = %d", rc));
1351 break;
1352 case SETXON:
1353 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1354 IOCTL_ASYNC,
1355 ASYNC_STARTTRANSMIT,
1356 0,0,0,
1357 0,0,0);
1358 dprintf(("SETXON: rc = %d", rc));
1359 break;
1360 default:
1361 dprintf(("!ERROR!: EscapeCommFunction: unknown function"));
1362 ::SetLastError(ERROR_INVALID_PARAMETER);
1363 return(FALSE);
1364 }
1365
1366 return(rc==0);
1367}
1368//******************************************************************************
1369//******************************************************************************
1370BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1371 LPCOMMCONFIG lpCC,
1372 DWORD dwSize)
1373{
1374 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1375 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1376 {
1377 ::SetLastError(ERROR_INVALID_HANDLE);
1378 return FALSE;
1379 }
1380
1381 dprintf(("SetDefaultCommConfig %x %d", lpCC, dwSize));
1382 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
1383 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
1384
1385 return(TRUE);
1386}
1387//******************************************************************************
1388//******************************************************************************
1389BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1390 LPCOMMCONFIG lpCC,
1391 LPDWORD lpdwSize)
1392{
1393 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1394
1395 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1396 *lpdwSize< sizeof(COMMCONFIG) )
1397 {
1398 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1399 *lpdwSize= sizeof(COMMCONFIG);
1400 return FALSE;
1401 }
1402
1403 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1404 {
1405 ::SetLastError(ERROR_INVALID_HANDLE);
1406 return FALSE;
1407 }
1408 dprintf(("GetDefaultCommConfig %x %x", lpCC, lpdwSize));
1409
1410 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1411 *lpdwSize = sizeof(COMMCONFIG);
1412 return(TRUE);
1413}
1414//******************************************************************************
1415//******************************************************************************
1416APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData,
1417 UCHAR ucSize,
1418 UCHAR ucParity,
1419 UCHAR ucStop)
1420{
1421 APIRET rc;
1422 ULONG ulLen;
1423 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1424 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1425 struct
1426 {
1427 UCHAR ucSize;
1428 UCHAR ucParity;
1429 UCHAR ucStop;
1430 UCHAR ucPadding;
1431 }Param;
1432
1433 ulLen = 3;
1434 Param.ucSize = ucSize;
1435 Param.ucParity = ucParity;
1436 Param.ucStop = ucStop;
1437
1438 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1439 IOCTL_ASYNC,
1440 ASYNC_SETLINECTRL,
1441 &Param,ulLen,&ulLen,
1442 NULL,0,NULL);
1443
1444 if(0==rc)
1445 {
1446 pCurDCB->ByteSize = ucSize;
1447 pCurDCB->Parity = ucParity;
1448 pCurDCB->StopBits = ucStop;
1449 }
1450 else {
1451 dprintf(("!ERROR! SetLine: OSLibDosDevIOCtl failed with rc %d", rc));
1452 }
1453 return rc;
1454}
1455//******************************************************************************
1456//******************************************************************************
1457APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData,
1458 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow,
1459 UCHAR ucDtrControl, BOOL fDsrSensitivity,
1460 BOOL fTXContinueOnXoff, BOOL fOutX,
1461 BOOL fInX, BOOL fErrorChar,
1462 BOOL fNull, UCHAR ucRtsControl,
1463 BOOL fAbortOnError, BYTE XonChar,
1464 BYTE XoffChar,BYTE ErrorChar)
1465{
1466 APIRET rc;
1467 ULONG ulLen;
1468 DCBINFO os2dcb;
1469 UCHAR fbTimeOut;
1470 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1471 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1472
1473 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1474 os2dcb.fbCtlHndShake = (ucDtrControl & 0x03) |
1475 (fOutxCtsFlow?0x08:0x00) |
1476 (fOutxDsrFlow?0x10:0x00) |
1477 // No DCD support in Win32 ?!
1478 (fDsrSensitivity?0x40:0x00);
1479 os2dcb.fbFlowReplace = (fOutX?0x01:0x00) |
1480 (fInX?0x02:0x00) |
1481 (fErrorChar?0x04:0x00)|
1482 (fNull?0x08:0x00)|
1483 (fTXContinueOnXoff?0x02:0x00)| // Not sure if thats the right flag to test
1484 (ucRtsControl<<6);
1485
1486 fbTimeOut = 0x02;
1487 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1488 {
1489 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1490 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1491 fbTimeOut = 0x05;
1492 else
1493 fbTimeOut = 0x04;
1494 }
1495 else
1496 {
1497 DWORD dwTimeout;
1498 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1499 if(dwTimeout)
1500 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1501 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1502 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1503 }
1504 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF9) | fbTimeOut;
1505 os2dcb.bErrorReplacementChar = ErrorChar;
1506 os2dcb.bXONChar = XonChar;
1507 os2dcb.bXOFFChar = XoffChar;
1508 ulLen = sizeof(DCBINFO);
1509 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1510 IOCTL_ASYNC,
1511 ASYNC_SETDCBINFO,
1512 &os2dcb,ulLen,&ulLen,
1513 NULL,0,NULL);
1514
1515 if(0==rc)
1516 {
1517 memcpy(&pDevData->dcbOS2,&os2dcb,sizeof(DCBINFO));
1518 pCurDCB->fOutxCtsFlow = fOutxCtsFlow;
1519 pCurDCB->fOutxDsrFlow = fOutxDsrFlow;
1520 pCurDCB->fDtrControl = ucDtrControl;
1521 pCurDCB->fDsrSensitivity = fDsrSensitivity;
1522 pCurDCB->fTXContinueOnXoff = fTXContinueOnXoff;
1523 pCurDCB->fOutX = fOutX;
1524 pCurDCB->fInX = fInX;
1525 pCurDCB->fErrorChar = fErrorChar;
1526 pCurDCB->fNull = fNull;
1527 pCurDCB->fRtsControl = ucRtsControl;
1528 pCurDCB->fAbortOnError = fAbortOnError;
1529 pCurDCB->XonChar = XonChar;
1530 pCurDCB->XoffChar = XoffChar;
1531 pCurDCB->ErrorChar = ErrorChar;
1532 }
1533
1534 return rc;
1535
1536}
1537//******************************************************************************
1538//******************************************************************************
1539APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData,
1540 DWORD dwNewBaud)
1541{
1542 APIRET rc;
1543 ULONG ulLen;
1544 EXTBAUDSET SetBaud;
1545 EXTBAUDGET GetBaud;
1546 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1547
1548 ulLen = sizeof(SetBaud);
1549 SetBaud.ulBaud = dwNewBaud;
1550 SetBaud.ucFrac = 0;
1551 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1552 IOCTL_ASYNC,
1553 ASYNC_EXTSETBAUDRATE,
1554 &SetBaud,ulLen,&ulLen,
1555 NULL,0,NULL);
1556 if(0==rc)
1557 {
1558 ulLen = sizeof(GetBaud);
1559 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1560 IOCTL_ASYNC,
1561 ASYNC_EXTGETBAUDRATE,
1562 NULL,0,NULL,
1563 &GetBaud,ulLen,&ulLen);
1564 if(0==rc)
1565 {
1566 if(dwNewBaud != GetBaud.ulCurrBaud) {
1567 dprintf(("!WARNING! dwNewBaud (%d) != GetBaud.ulCurrBaud (%d)", dwNewBaud, GetBaud.ulCurrBaud));
1568 rc = 1; // ToDo set a proper Errorhandling
1569 }
1570 else
1571 {
1572 pDevData->CommCfg.dcb.BaudRate = dwNewBaud;
1573 }
1574 }
1575 else {
1576 dprintf(("!WARNING! SetBaud: (get) OSLibDosDevIOCtl failed with rc %d", rc));
1577 }
1578 }
1579 else {
1580 dprintf(("!WARNING! SetBaud: (set) OSLibDosDevIOCtl failed with rc %d", rc));
1581 }
1582 return rc;
1583}
1584//******************************************************************************
1585//******************************************************************************
1586void HMDeviceCommClass::CloseOverlappedIOHandlers()
1587{
1588 for(int i=0;i<MAX_COMPORTS;i++) {
1589 if(handler[i]) {
1590 handler[i]->Release(TRUE);
1591 handler[i] = NULL;
1592 }
1593 }
1594}
1595#ifdef DEBUG
1596//******************************************************************************
1597//******************************************************************************
1598static char *DebugCommEvent(DWORD dwEvents)
1599{
1600 static char szCommEvents[128];
1601
1602 szCommEvents[0] = 0;
1603
1604 if(dwEvents & EV_RXCHAR) {
1605 strcat(szCommEvents, "EV_RXCHAR ");
1606 }
1607 if(dwEvents & EV_TXEMPTY) {
1608 strcat(szCommEvents, "EV_TXEMPTY ");
1609 }
1610 if(dwEvents & EV_CTS) {
1611 strcat(szCommEvents, "EV_CTS ");
1612 }
1613 if(dwEvents & EV_DSR) {
1614 strcat(szCommEvents, "EV_DSR ");
1615 }
1616 if(dwEvents & EV_RLSD) {
1617 strcat(szCommEvents, "EV_RLSD ");
1618 }
1619 if(dwEvents & EV_BREAK) {
1620 strcat(szCommEvents, "EV_BREAK ");
1621 }
1622 if(dwEvents & EV_ERR) {
1623 strcat(szCommEvents, "EV_ERR ");
1624 }
1625 if(dwEvents & EV_RING) {
1626 strcat(szCommEvents, "EV_RING ");
1627 }
1628 return szCommEvents;
1629}
1630//******************************************************************************
1631//******************************************************************************
1632static char *DebugModemStatus(DWORD dwModemStatus)
1633{
1634 static char szModemStatus[128];
1635
1636 szModemStatus[0] = 0;
1637
1638 if(dwModemStatus & MS_CTS_ON) {
1639 strcat(szModemStatus, "MS_CTS_ON ");
1640 }
1641 if(dwModemStatus & MS_DSR_ON) {
1642 strcat(szModemStatus, "MS_DSR_ON ");
1643 }
1644 if(dwModemStatus & MS_RING_ON) {
1645 strcat(szModemStatus, "MS_RING_ON ");
1646 }
1647 if(dwModemStatus & MS_RLSD_ON) {
1648 strcat(szModemStatus, "MS_RLSD_ON ");
1649 }
1650 return szModemStatus;
1651}
1652#endif
1653//******************************************************************************
1654//******************************************************************************
1655OverlappedIOHandler *HMDeviceCommClass::handler[MAX_COMPORTS] = {NULL};
1656
Note: See TracBrowser for help on using the repository browser.