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

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

Com overlapped IO changes for reference counts

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