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

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

If bytes present in COM device buffer, read them directly; even for overlapped IO calls.

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