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

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

Overlapped IO bugfixes

File size: 55.8 KB
Line 
1/* $Id: hmcomm.cpp,v 1.35 2002-06-11 12:51:43 sandervl Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 COM device access class
7 *
8 * 1999 Achim Hasenmueller <achimha@innotek.de>
9 * 2001 Sander van Leeuwen <sandervl@xs4all.nl>
10 *
11 *
12 */
13
14
15
16#include <os2win.h>
17#include <string.h>
18#include <handlemanager.h>
19#include "handlenames.h"
20#include <heapstring.h>
21#include "hmcomm.h"
22#include "oslibdos.h"
23
24#define DBG_LOCALLOG DBG_hmcomm
25#include "dbglocal.h"
26
27//#define TESTING_COMM
28#ifdef TESTING_COMM
29#undef dprintf
30#define dprintf(a) WriteLog a
31#undef dprintf2
32#define dprintf2(a) WriteLog a
33#endif
34
35BAUDTABLEENTRY BaudTable[] =
36{
37 {75,BAUD_075},
38 {110,BAUD_110},
39 {134,BAUD_134_5},
40 {150,BAUD_150},
41 {300,BAUD_300},
42 {600,BAUD_600},
43 {1200,BAUD_1200},
44 {1800,BAUD_1800},
45 {2400,BAUD_2400},
46 {4800,BAUD_4800},
47 {7200,BAUD_7200},
48 {9600,BAUD_9600},
49 {14400,BAUD_14400},
50 {19200,BAUD_19200},
51 {38400,BAUD_38400},
52 {56000,BAUD_56K},
53 {57600,BAUD_57600},
54 {115200,BAUD_115200},
55 {128000,BAUD_128K}
56};
57
58#define BaudTableSize (sizeof(BaudTable)/sizeof(BAUDTABLEENTRY))
59
60static DWORD CommReadIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut);
61static DWORD CommWriteIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut);
62static DWORD CommPollIOHandler(LPASYNCIOREQUEST lpRequest, DWORD *lpdwResult, DWORD *lpdwTimeOut);
63
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 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
569 return pDevData->iohandler->ReadFile(pHMHandleData->hWin32Handle, lpBuffer, nNumberOfBytesToRead,
570 lpNumberOfBytesRead, lpOverlapped, lpCompletionRoutine, (DWORD)pDevData);
571 }
572
573#ifdef DEBUG
574 RXQUEUE qInfo;
575 ULONG ulLen = sizeof(qInfo);
576 ULONG rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
577 IOCTL_ASYNC,
578 ASYNC_GETINQUECOUNT,
579 0,0,0,
580 &qInfo,ulLen,&ulLen);
581 dprintf(("ASYNC_GETINQUECOUNT -> qInfo.cch %d (queue size %d) rc %d", qInfo.cch, qInfo.cb, rc));
582#endif
583
584 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
585 &ulBytesRead);
586
587 if(lpNumberOfBytesRead) {
588 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0;
589 dprintf2(("KERNEL32:HMDeviceCommClass::ReadFile %d bytes read", *lpNumberOfBytesRead));
590 }
591 if(ret == FALSE) {
592 dprintf(("!ERROR!: ReadFile failed with rc %d", GetLastError()));
593 }
594#ifdef DEBUG
595 else {
596 dprintf2(("%d Bytes read:", ulBytesRead));
597 for(int i=0;i<min(ulBytesRead, 16);i++) {
598 dprintf2(("%x %c", ((char *)lpBuffer)[i], ((char *)lpBuffer)[i]));
599 }
600 }
601#endif
602 return ret;
603}
604/*****************************************************************************
605 * Name : DWORD HMDeviceHandler::SetupComm
606 * Purpose : set com port parameters (queue)
607 * Variables :
608 * Result :
609 * Remark :
610 * Status :
611 *
612 * Author : Achim Hasenmueller
613 *****************************************************************************/
614
615BOOL HMDeviceCommClass::SetupComm( PHMHANDLEDATA pHMHandleData,
616 DWORD dwInQueue,
617 DWORD dwOutQueue)
618{
619 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
620
621 dprintf(("HMDeviceCommClass::SetupComm "));
622 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
623 {
624 ::SetLastError(ERROR_INVALID_HANDLE);
625 return FALSE;
626 }
627 pDevData->dwInBuffer = dwInQueue;
628 pDevData->dwOutBuffer = dwOutQueue;
629
630 return(TRUE);
631}
632//******************************************************************************
633//******************************************************************************
634BOOL HMDeviceCommClass::WaitCommEvent( PHMHANDLEDATA pHMHandleData,
635 LPDWORD lpfdwEvtMask,
636 LPOVERLAPPED lpo)
637{
638 APIRET rc;
639 ULONG ulLen;
640 USHORT COMEvt;
641 DWORD dwEvent,dwMask;
642
643 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
644
645 dprintf(("HMDeviceCommClass::WaitCommEvent %x %x %x", pHMHandleData->hHMHandle, lpfdwEvtMask, lpo));
646
647 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo) {
648 dprintf(("!WARNING! pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo"));
649 ::SetLastError(ERROR_INVALID_PARAMETER);
650 return FALSE;
651 }
652
653 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
654 {
655 return pDevData->iohandler->WaitForEvent(pHMHandleData->hWin32Handle, pDevData->dwEventMask, lpfdwEvtMask,
656 lpo, NULL, (DWORD)pDevData);
657 }
658
659 ulLen = sizeof(CHAR);
660
661 dwEvent = 0;
662 rc = 0;
663 ulLen = sizeof(COMEvt);
664 dwMask = pDevData->dwEventMask;
665 while( (0==rc) &&
666 !(dwEvent & dwMask) &&
667 (dwMask ==pDevData->dwEventMask) ) // Exit if the Mask gets changed
668 {
669 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
670 IOCTL_ASYNC,
671 ASYNC_GETCOMMEVENT,
672 0,0,0,
673 &COMEvt,ulLen,&ulLen);
674 if(!rc)
675 {
676 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
677 //dwEvent |= (COMEvt&0x0002)? 0:0;
678 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
679 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
680 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
681 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD?
682 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
683 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
684 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
685 if((dwEvent & dwMask)) break;
686 }
687 else break;
688
689 DosSleep(TIMEOUT_COMM);
690 }
691 if(dwMask == pDevData->dwEventMask) {
692 *lpfdwEvtMask = (rc==0) ? (dwEvent & dwMask) : 0;
693 dprintf(("WaitCommEvent returned %x", *lpfdwEvtMask));
694 }
695 else *lpfdwEvtMask = 0;
696
697 ::SetLastError(rc);
698 return (rc==0);
699}
700/*****************************************************************************
701 * Name : DWORD HMDeviceCommClass::CancelIo
702 * Purpose : cancel pending IO operation
703 * Variables :
704 * Result :
705 * Remark :
706 * Status :
707 *
708 * Author : SvL
709 *****************************************************************************/
710BOOL HMDeviceCommClass::CancelIo(PHMHANDLEDATA pHMHandleData)
711{
712 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
713
714 dprintf(("HMDeviceCommClass::CancelIo"));
715 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
716 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
717 return FALSE;
718 }
719
720 return pDevData->iohandler->CancelIo(pHMHandleData->hWin32Handle);
721}
722/*****************************************************************************
723 * Name : DWORD HMDeviceFileClass::GetOverlappedResult
724 * Purpose : asynchronus I/O
725 * Parameters: PHMHANDLEDATA pHMHandleData
726 * LPOVERLAPPED arg2
727 * LPDWORD arg3
728 * BOOL arg4
729 * Variables :
730 * Result : API returncode
731 * Remark :
732 * Status :
733 *
734 * Author : SvL
735 *****************************************************************************/
736BOOL HMDeviceCommClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData,
737 LPOVERLAPPED lpOverlapped,
738 LPDWORD lpcbTransfer,
739 BOOL fWait)
740{
741 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
742
743 dprintf(("KERNEL32-HMDeviceCommClass: HMDeviceCommClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh)",
744 pHMHandleData->hHMHandle, lpOverlapped, lpcbTransfer, fWait));
745
746 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
747 dprintf(("!WARNING!: GetOverlappedResult called for a handle that wasn't opened with FILE_FLAG_OVERLAPPED"));
748 return TRUE; //NT4, SP6 doesn't fail
749 }
750
751 if(pDevData == NULL) {
752 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
753 return FALSE;
754 }
755 if(!lpOverlapped) {
756 ::SetLastError(ERROR_INVALID_PARAMETER);
757 return FALSE;
758 }
759 return pDevData->iohandler->GetOverlappedResult(pHMHandleData->hWin32Handle, lpOverlapped, lpcbTransfer, fWait);
760}
761//******************************************************************************
762//******************************************************************************
763BOOL HMDeviceCommClass::GetCommProperties(PHMHANDLEDATA pHMHandleData,
764 LPCOMMPROP lpcmmp)
765{
766 EXTBAUDGET BaudInfo;
767 APIRET rc;
768 ULONG ulLen;
769 USHORT COMErr;
770 int i;
771 dprintf(("HMDeviceCommClass::GetCommProperties"));
772
773 ulLen = sizeof(EXTBAUDGET);
774 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
775 IOCTL_ASYNC,
776 ASYNC_EXTGETBAUDRATE,
777 0,0,0,
778 &BaudInfo,ulLen,&ulLen);
779 memset(lpcmmp,0,sizeof(COMMPROP));
780 lpcmmp->wPacketLength = sizeof(COMMPROP);
781 lpcmmp->wPacketVersion = 1; //???
782 lpcmmp->dwServiceMask = SP_SERIALCOMM;
783 for(i=0;i<BaudTableSize && BaudInfo.ulMaxBaud <= BaudTable[i].dwBaudRate;i++);
784 lpcmmp->dwMaxBaud = BaudTable[i].dwBaudFlag;
785 lpcmmp->dwProvSubType = PST_RS232;
786 lpcmmp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK |
787 PCF_RTSCTS | PCF_SETXCHAR |
788 PCF_XONXOFF;
789 lpcmmp->dwSettableParams = SP_BAUD | SP_DATABITS |
790 SP_HANDSHAKEING | SP_PARITY |
791 SP_PARITY_CHECK | SP_STOPBIT;
792 lpcmmp->dwSettableBaud = 0;
793 for(i=0;i<BaudTableSize;i++)
794 {
795 if ( (BaudTable[i].dwBaudRate>=BaudInfo.ulMinBaud) &&
796 (BaudTable[i].dwBaudRate<=BaudInfo.ulMaxBaud) )
797 lpcmmp->dwSettableBaud |= BaudTable[i].dwBaudFlag;
798 }
799 lpcmmp->dwSettableBaud |= BAUD_USER;
800 lpcmmp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
801 lpcmmp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
802 PARITY_NONE | PARITY_ODD | PARITY_EVEN |
803 PARITY_MARK | PARITY_SPACE;
804 return(rc==0);
805}
806//******************************************************************************
807//******************************************************************************
808BOOL HMDeviceCommClass::GetCommMask( PHMHANDLEDATA pHMHandleData,
809 LPDWORD lpfdwEvtMask)
810{
811 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
812
813 dprintf(("HMDeviceCommClass::GetCommMask"));
814
815 *lpfdwEvtMask = pDevData->dwEventMask;
816 return(TRUE);
817}
818//******************************************************************************
819//******************************************************************************
820BOOL HMDeviceCommClass::SetCommMask( PHMHANDLEDATA pHMHandleData,
821 DWORD fdwEvtMask)
822{
823 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
824 dprintf(("HMDeviceCommClass::SetCommMask %x", fdwEvtMask));
825
826 if(fdwEvtMask & (EV_RLSD|EV_RXFLAG)) {
827 dprintf(("!WARNING! SetCommMask: unsupported flags EV_RLSD and/or EV_RXFLAG!!"));
828 }
829
830 pDevData->dwEventMask = fdwEvtMask & ~(EV_RLSD|EV_RXFLAG); // Clear the 2 not supported Flags.
831 return(TRUE);
832}
833//******************************************************************************
834//******************************************************************************
835BOOL HMDeviceCommClass::PurgeComm( PHMHANDLEDATA pHMHandleData,
836 DWORD fdwAction)
837{
838 ULONG ulParLen, ulDataLen, rc = ERROR_SUCCESS;
839 BYTE par = 0;
840 WORD data = 0;
841
842 dprintf(("HMDeviceCommClass::PurgeComm (flags 0x%x) partly implemented",fdwAction));
843 // ToDo: find a way to stop the current transmision didn't find
844 // any clue how to in Control Program Guide and reference
845
846 ulParLen = sizeof(par);
847 ulDataLen = sizeof(data);
848 if(fdwAction & PURGE_TXCLEAR) {
849 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
850 IOCTL_GENERAL,
851 DEV_FLUSHOUTPUT,
852 &par,ulParLen,&ulParLen,
853 &data,ulDataLen,&ulDataLen);
854 }
855 if(fdwAction & PURGE_RXCLEAR) {
856 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
857 IOCTL_GENERAL,
858 DEV_FLUSHINPUT,
859 &par,ulParLen,&ulParLen,
860 &data,ulDataLen,&ulDataLen);
861 }
862 if(rc) {
863 dprintf(("!WARNING! OSLibDosDevIOCtl failed with rc %d", rc));
864 }
865 return (rc == ERROR_SUCCESS);
866}
867//******************************************************************************
868//******************************************************************************
869BOOL HMDeviceCommClass::ClearCommError( PHMHANDLEDATA pHMHandleData,
870 LPDWORD lpdwErrors,
871 LPCOMSTAT lpcst)
872{
873 APIRET rc;
874 ULONG ulLen;
875 USHORT COMErr;
876
877 dprintf(("HMDeviceCommClass::ClearCommError"));
878 ulLen = sizeof(USHORT);
879
880 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
881 IOCTL_ASYNC,
882 ASYNC_GETCOMMERROR,
883 0,0,0,
884 &COMErr,2,&ulLen);
885 *lpdwErrors = 0;
886 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
887 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
888 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
889 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
890
891 if(lpcst)
892 {
893 UCHAR ucStatus;
894 RXQUEUE qInfo;
895 ulLen = 1;
896 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
897 IOCTL_ASYNC,
898 ASYNC_GETCOMMSTATUS,
899 0,0,0,
900 &ucStatus,ulLen,&ulLen);
901 if(!rc)
902 {
903 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
904 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
905 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
906 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
907 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
908 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
909 lpcst->fTxim = ((ucStatus & 0x40)>0);
910
911 ulLen = sizeof(qInfo);
912 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
913 IOCTL_ASYNC,
914 ASYNC_GETINQUECOUNT,
915 0,0,0,
916 &qInfo,ulLen,&ulLen);
917 if(!rc)
918 {
919 lpcst->cbInQue = qInfo.cch;
920 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
921 IOCTL_ASYNC,
922 ASYNC_GETOUTQUECOUNT,
923 0,0,0,
924 &qInfo,ulLen,&ulLen);
925 if(!rc)
926 lpcst->cbOutQue = qInfo.cch;
927 }
928 }
929 }
930
931 return(rc==0);
932}
933//******************************************************************************
934//******************************************************************************
935BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData,
936 LPDCB lpDCB)
937{
938 APIRET rc;
939 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
940 DCB *pCurDCB = &pDevData->CommCfg.dcb;
941 dprintf(("HMDeviceCommClass::SetCommState"));
942
943 rc = 0;
944 if(pCurDCB->BaudRate != lpDCB->BaudRate) {
945 dprintf(("SetCommState: change baud rate from %d to %d", pCurDCB->BaudRate, lpDCB->BaudRate));
946 rc = SetBaud( pHMHandleData,
947 lpDCB->BaudRate);
948 }
949
950 if(!rc)
951 {
952 if( (pCurDCB->ByteSize != lpDCB->ByteSize) ||
953 (pCurDCB->Parity != lpDCB->Parity) ||
954 (pCurDCB->StopBits != lpDCB->StopBits))
955 {
956 dprintf(("SetCommState: change line %d %d %d", lpDCB->ByteSize, lpDCB->Parity, lpDCB->StopBits));
957 rc = SetLine( pHMHandleData,
958 lpDCB->ByteSize,
959 lpDCB->Parity,
960 lpDCB->StopBits);
961 }
962 }
963
964 if(!rc)
965 {
966 if( (pCurDCB->fOutxCtsFlow != lpDCB->fOutxCtsFlow) ||
967 (pCurDCB->fOutxDsrFlow != lpDCB->fOutxDsrFlow) ||
968 (pCurDCB->fDtrControl != lpDCB->fDtrControl) ||
969 (pCurDCB->fDsrSensitivity != lpDCB->fDsrSensitivity) ||
970 (pCurDCB->fTXContinueOnXoff != lpDCB->fTXContinueOnXoff) ||
971 (pCurDCB->fOutX != lpDCB->fOutX) ||
972 (pCurDCB->fInX != lpDCB->fInX) ||
973 (pCurDCB->fErrorChar != lpDCB->fErrorChar) ||
974 (pCurDCB->fNull != lpDCB->fNull) ||
975 (pCurDCB->fRtsControl != lpDCB->fRtsControl) ||
976 (pCurDCB->fAbortOnError != lpDCB->fAbortOnError) ||
977 (pCurDCB->XonChar != lpDCB->XonChar) ||
978 (pCurDCB->XoffChar != lpDCB->XoffChar) ||
979 (pCurDCB->ErrorChar != lpDCB->ErrorChar))
980 {
981 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));
982 SetOS2DCB( pHMHandleData,
983 lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,
984 lpDCB->fDtrControl, lpDCB->fDsrSensitivity,
985 lpDCB->fTXContinueOnXoff, lpDCB->fOutX,
986 lpDCB->fInX, lpDCB->fErrorChar,
987 lpDCB->fNull, lpDCB->fRtsControl,
988 lpDCB->fAbortOnError, lpDCB->XonChar,
989 lpDCB->XoffChar,lpDCB->ErrorChar);
990 }
991 }
992
993 return(rc==0);
994}
995//******************************************************************************
996//******************************************************************************
997BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData,
998 LPDCB lpdcb)
999{
1000 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1001
1002 dprintf(("HMDeviceCommClass::GetCommState %x", lpdcb));
1003
1004 if(lpdcb == NULL) {
1005 ::SetLastError(ERROR_INVALID_PARAMETER);
1006 return FALSE;
1007 }
1008
1009 memcpy(lpdcb,&pDevData->CommCfg.dcb,sizeof(DCB));
1010 return(TRUE);
1011}
1012//******************************************************************************
1013//******************************************************************************
1014BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData,
1015 LPDWORD lpModemStat )
1016{
1017 APIRET rc;
1018 ULONG ulLen;
1019 USHORT COMErr;
1020 UCHAR ucStatus;
1021
1022 dprintf(("HMDeviceCommClass::GetCommModemStatus %x", lpModemStat));
1023 if(lpModemStat == NULL) {
1024 ::SetLastError(ERROR_INVALID_PARAMETER);
1025 return FALSE;
1026 }
1027
1028 ulLen = sizeof(CHAR);
1029
1030 ulLen = 1;
1031 *lpModemStat = 0;
1032
1033 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1034 IOCTL_ASYNC,
1035 ASYNC_GETMODEMINPUT,
1036 0,0,0,
1037 &ucStatus,ulLen,&ulLen);
1038 if(!rc)
1039 {
1040 *lpModemStat |= (ucStatus & 0x10)? MS_CTS_ON:0;
1041 *lpModemStat |= (ucStatus & 0x20)? MS_DSR_ON:0;
1042 *lpModemStat |= (ucStatus & 0x40)? MS_RING_ON:0;
1043 //*lpModemStat |= (ucStatus & 0x80)? MS_RSLD_ON:0;
1044 }
1045
1046 dprintf2(("HMDeviceCommClass::GetCommModemStatus -> %x rc=%d", *lpModemStat, rc));
1047 return(rc==0);
1048}
1049//******************************************************************************
1050//******************************************************************************
1051BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1052 LPCOMMTIMEOUTS lpctmo)
1053{
1054 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1055
1056 dprintf(("HMDeviceCommClass::GetCommTimeouts %x stub", lpctmo));
1057
1058 if(lpctmo == NULL) {
1059 ::SetLastError(ERROR_INVALID_PARAMETER);
1060 return FALSE;
1061 }
1062
1063 memcpy( lpctmo,
1064 &pDevData->CommTOuts,
1065 sizeof(COMMTIMEOUTS));
1066 return(TRUE);
1067}
1068//******************************************************************************
1069//******************************************************************************
1070BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1071 LPCOMMTIMEOUTS lpctmo)
1072{
1073 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1074 DCBINFO os2dcb;
1075 ULONG ulLen;
1076 APIRET rc;
1077 UCHAR fbTimeOut;
1078
1079 if(lpctmo == NULL) {
1080 dprintf(("!WARNING! HMDeviceCommClass::SetCommTimeouts %x -> invalid parameter", lpctmo));
1081 ::SetLastError(ERROR_INVALID_PARAMETER);
1082 return FALSE;
1083 }
1084
1085 dprintf(("HMDeviceCommClass::SetCommTimeouts\n"
1086 " ReadIntervalTimeout : 0x%x\n"
1087 " ReadTotalTimeoutMultiplier : %d\n"
1088 " ReadTotalTimeoutConstant : %d\n"
1089 " WriteTotalTimeoutMultiplier : %d\n"
1090 " WriteTotalTimeoutConstant : %d\n",
1091 lpctmo->ReadIntervalTimeout,
1092 lpctmo->ReadTotalTimeoutMultiplier,
1093 lpctmo->ReadTotalTimeoutConstant,
1094 lpctmo->WriteTotalTimeoutMultiplier,
1095 lpctmo->WriteTotalTimeoutConstant
1096 ));
1097
1098 memcpy( &pDevData->CommTOuts,
1099 lpctmo,
1100 sizeof(COMMTIMEOUTS));
1101
1102 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1103
1104 fbTimeOut = 0x02; //normal processing (wait until timout or buffer full)
1105 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1106 {
1107 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1108 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1109 fbTimeOut = 0x05; //no wait
1110 else
1111 fbTimeOut = 0x04; //wait for something
1112 }
1113 else
1114 {
1115 DWORD dwTimeout;
1116 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1117 if(dwTimeout)
1118 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1119
1120 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1121 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1122 }
1123 if( (0==pDevData->CommTOuts.WriteTotalTimeoutMultiplier) &&
1124 (0==pDevData->CommTOuts.WriteTotalTimeoutConstant))
1125 {//no timeout used for writing
1126 os2dcb.fbTimeOut |= 1; //write infinite timeout
1127 }
1128
1129 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF8) | fbTimeOut;
1130
1131 dprintf((" New DCB:\n"
1132 " WriteTimeout : %d\n"
1133 " ReadTimeout : %d\n"
1134 " CtlHandshake : 0x%x\n"
1135 " FlowReplace : 0x%x\n"
1136 " Timeout : 0x%x\n"
1137 " Error replacement Char : 0x%x\n"
1138 " Break replacement Char : 0x%x\n"
1139 " XON Char : 0x%x\n"
1140 " XOFF Char : 0x%x\n",
1141 os2dcb.usWriteTimeout,
1142 os2dcb.usReadTimeout,
1143 os2dcb.fbCtlHndShake,
1144 os2dcb.fbFlowReplace,
1145 os2dcb.fbTimeOut,
1146 os2dcb.bErrorReplacementChar,
1147 os2dcb.bBreakReplacementChar,
1148 os2dcb.bXONChar,
1149 os2dcb.bXOFFChar));
1150
1151 ulLen = sizeof(DCBINFO);
1152 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1153 IOCTL_ASYNC,
1154 ASYNC_SETDCBINFO,
1155 &os2dcb,ulLen,&ulLen,
1156 NULL,0,NULL);
1157 dprintf(("IOCRL returned %d",rc));
1158 return(0==rc);
1159}
1160//******************************************************************************
1161//******************************************************************************
1162BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData,
1163 CHAR cChar )
1164{
1165 APIRET rc;
1166 ULONG ulLen;
1167 USHORT COMErr;
1168
1169 dprintf(("HMDeviceCommClass::TransmitCommChar"));
1170 ulLen = sizeof(CHAR);
1171
1172 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1173 IOCTL_ASYNC,
1174 ASYNC_TRANSMITIMM,
1175 &cChar,ulLen,&ulLen,
1176 NULL,0,NULL);
1177
1178 return(rc==0);
1179}
1180//******************************************************************************
1181//******************************************************************************
1182BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData )
1183{
1184 APIRET rc;
1185 ULONG ulLen;
1186 USHORT COMErr;
1187
1188 dprintf(("HMDeviceCommClass::SetCommBreak"));
1189 ulLen = sizeof(USHORT);
1190
1191 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1192 IOCTL_ASYNC,
1193 ASYNC_SETBREAKON,
1194 0,0,0,
1195 &COMErr,2,&ulLen);
1196
1197 return(rc==0);
1198}
1199//******************************************************************************
1200//******************************************************************************
1201BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData)
1202{
1203 APIRET rc;
1204 ULONG ulLen;
1205 USHORT COMErr;
1206
1207 dprintf(("HMDeviceCommClass::ClearCommBreak"));
1208 ulLen = sizeof(USHORT);
1209
1210 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1211 IOCTL_ASYNC,
1212 ASYNC_SETBREAKOFF,
1213 0,0,0,
1214 &COMErr,2,&ulLen);
1215
1216 return(rc==0);
1217}
1218//******************************************************************************
1219//******************************************************************************
1220BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
1221 LPCOMMCONFIG lpCC,
1222 DWORD dwSize )
1223{
1224 dprintf(("HMDeviceCommClass::SetCommConfig NOT IMPLEMENTED"));
1225
1226 return(TRUE);
1227}
1228//******************************************************************************
1229//******************************************************************************
1230BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
1231 LPCOMMCONFIG lpCC,
1232 LPDWORD lpdwSize )
1233{
1234 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1235
1236 dprintf(("HMDeviceCommClass::GetCommConfig"));
1237
1238 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1239 *lpdwSize< sizeof(COMMCONFIG) )
1240 {
1241 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1242 *lpdwSize= sizeof(COMMCONFIG);
1243 return FALSE;
1244 }
1245
1246 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1247 {
1248 ::SetLastError(ERROR_INVALID_HANDLE);
1249 return FALSE;
1250 }
1251
1252 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1253 *lpdwSize = sizeof(COMMCONFIG);
1254 return(TRUE);
1255}
1256//******************************************************************************
1257//******************************************************************************
1258BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData,
1259 UINT dwFunc )
1260{
1261 APIRET rc;
1262 ULONG ulDLen,ulPLen;
1263 USHORT COMErr;
1264 MODEMSTATUS mdm;
1265
1266 dprintf(("HMDeviceCommClass::EscapeCommFunction %x", dwFunc));
1267
1268 ulDLen = sizeof(USHORT);
1269 ulPLen = sizeof(MODEMSTATUS);
1270 switch(dwFunc)
1271 {
1272 case CLRDTR:
1273 mdm.fbModemOn = 0x00;
1274 mdm.fbModemOff = 0XFE;
1275 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1276 IOCTL_ASYNC,
1277 ASYNC_SETMODEMCTRL,
1278 &mdm,ulPLen,&ulPLen,
1279 &COMErr,ulDLen,&ulDLen);
1280 dprintf(("CLRDTR rc = %d Comerror = 0x%x",rc,COMErr));
1281 rc = COMErr;
1282 if(rc==0)
1283 {
1284 BYTE bModem;
1285 ulDLen = sizeof(BYTE);
1286 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1287 IOCTL_ASYNC,
1288 ASYNC_GETMODEMOUTPUT,
1289 NULL,0,NULL,
1290 &bModem,ulDLen,&ulDLen);
1291 dprintf(("Check DTR rc = %d Flags = 0x%x",rc,bModem));
1292 rc = bModem & 0x01;
1293 }
1294 break;
1295 case CLRRTS:
1296 mdm.fbModemOn = 0x00;
1297 mdm.fbModemOff = 0XFD;
1298 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1299 IOCTL_ASYNC,
1300 ASYNC_SETMODEMCTRL,
1301 &mdm,ulPLen,&ulPLen,
1302 &COMErr,ulDLen,&ulDLen);
1303 dprintf(("CLRRTS: rc = %d, Comm error %x", rc, COMErr));
1304 break;
1305 case SETDTR:
1306 mdm.fbModemOn = 0x01;
1307 mdm.fbModemOff = 0XFF;
1308 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1309 IOCTL_ASYNC,
1310 ASYNC_SETMODEMCTRL,
1311 &mdm,ulPLen,&ulPLen,
1312 &COMErr,ulDLen,&ulDLen);
1313 dprintf(("SETDTR: rc = %d, Comm error %x", rc, COMErr));
1314 break;
1315 case SETRTS:
1316 mdm.fbModemOn = 0x02;
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(("SETRTS: rc = %d, Comm error %x", rc, COMErr));
1324 break;
1325 case SETXOFF:
1326 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1327 IOCTL_ASYNC,
1328 ASYNC_STOPTRANSMIT,
1329 0,0,0,
1330 0,0,0);
1331 dprintf(("SETXOFF: rc = %d", rc));
1332 break;
1333 case SETXON:
1334 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1335 IOCTL_ASYNC,
1336 ASYNC_STARTTRANSMIT,
1337 0,0,0,
1338 0,0,0);
1339 dprintf(("SETXON: rc = %d", rc));
1340 break;
1341 default:
1342 dprintf(("!ERROR!: EscapeCommFunction: unknown function"));
1343 ::SetLastError(ERROR_INVALID_PARAMETER);
1344 return(FALSE);
1345 }
1346
1347 return(rc==0);
1348}
1349//******************************************************************************
1350//******************************************************************************
1351BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1352 LPCOMMCONFIG lpCC,
1353 DWORD dwSize)
1354{
1355 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1356 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1357 {
1358 ::SetLastError(ERROR_INVALID_HANDLE);
1359 return FALSE;
1360 }
1361
1362 dprintf(("SetDefaultCommConfig %x %d", lpCC, dwSize));
1363 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
1364 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
1365
1366 return(TRUE);
1367}
1368//******************************************************************************
1369//******************************************************************************
1370BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1371 LPCOMMCONFIG lpCC,
1372 LPDWORD lpdwSize)
1373{
1374 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1375
1376 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1377 *lpdwSize< sizeof(COMMCONFIG) )
1378 {
1379 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1380 *lpdwSize= sizeof(COMMCONFIG);
1381 return FALSE;
1382 }
1383
1384 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1385 {
1386 ::SetLastError(ERROR_INVALID_HANDLE);
1387 return FALSE;
1388 }
1389 dprintf(("GetDefaultCommConfig %x %x", lpCC, lpdwSize));
1390
1391 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1392 *lpdwSize = sizeof(COMMCONFIG);
1393 return(TRUE);
1394}
1395//******************************************************************************
1396//******************************************************************************
1397APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData,
1398 UCHAR ucSize,
1399 UCHAR ucParity,
1400 UCHAR ucStop)
1401{
1402 APIRET rc;
1403 ULONG ulLen;
1404 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1405 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1406 struct
1407 {
1408 UCHAR ucSize;
1409 UCHAR ucParity;
1410 UCHAR ucStop;
1411 UCHAR ucPadding;
1412 }Param;
1413
1414 ulLen = 3;
1415 Param.ucSize = ucSize;
1416 Param.ucParity = ucParity;
1417 Param.ucStop = ucStop;
1418
1419 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1420 IOCTL_ASYNC,
1421 ASYNC_SETLINECTRL,
1422 &Param,ulLen,&ulLen,
1423 NULL,0,NULL);
1424
1425 if(0==rc)
1426 {
1427 pCurDCB->ByteSize = ucSize;
1428 pCurDCB->Parity = ucParity;
1429 pCurDCB->StopBits = ucStop;
1430 }
1431 else {
1432 dprintf(("!ERROR! SetLine: OSLibDosDevIOCtl failed with rc %d", rc));
1433 }
1434 return rc;
1435}
1436//******************************************************************************
1437//******************************************************************************
1438APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData,
1439 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow,
1440 UCHAR ucDtrControl, BOOL fDsrSensitivity,
1441 BOOL fTXContinueOnXoff, BOOL fOutX,
1442 BOOL fInX, BOOL fErrorChar,
1443 BOOL fNull, UCHAR ucRtsControl,
1444 BOOL fAbortOnError, BYTE XonChar,
1445 BYTE XoffChar,BYTE ErrorChar)
1446{
1447 APIRET rc;
1448 ULONG ulLen;
1449 DCBINFO os2dcb;
1450 UCHAR fbTimeOut;
1451 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1452 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1453
1454 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1455 os2dcb.fbCtlHndShake = (ucDtrControl & 0x03) |
1456 (fOutxCtsFlow?0x08:0x00) |
1457 (fOutxDsrFlow?0x10:0x00) |
1458 // No DCD support in Win32 ?!
1459 (fDsrSensitivity?0x40:0x00);
1460 os2dcb.fbFlowReplace = (fOutX?0x01:0x00) |
1461 (fInX?0x02:0x00) |
1462 (fErrorChar?0x04:0x00)|
1463 (fNull?0x08:0x00)|
1464 (fTXContinueOnXoff?0x02:0x00)| // Not sure if thats the right flag to test
1465 (ucRtsControl<<6);
1466
1467 fbTimeOut = 0x02;
1468 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1469 {
1470 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1471 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1472 fbTimeOut = 0x05;
1473 else
1474 fbTimeOut = 0x04;
1475 }
1476 else
1477 {
1478 DWORD dwTimeout;
1479 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1480 if(dwTimeout)
1481 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1482 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1483 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1484 }
1485 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF9) | fbTimeOut;
1486 os2dcb.bErrorReplacementChar = ErrorChar;
1487 os2dcb.bXONChar = XonChar;
1488 os2dcb.bXOFFChar = XoffChar;
1489 ulLen = sizeof(DCBINFO);
1490 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1491 IOCTL_ASYNC,
1492 ASYNC_SETDCBINFO,
1493 &os2dcb,ulLen,&ulLen,
1494 NULL,0,NULL);
1495
1496 if(0==rc)
1497 {
1498 memcpy(&pDevData->dcbOS2,&os2dcb,sizeof(DCBINFO));
1499 pCurDCB->fOutxCtsFlow = fOutxCtsFlow;
1500 pCurDCB->fOutxDsrFlow = fOutxDsrFlow;
1501 pCurDCB->fDtrControl = ucDtrControl;
1502 pCurDCB->fDsrSensitivity = fDsrSensitivity;
1503 pCurDCB->fTXContinueOnXoff = fTXContinueOnXoff;
1504 pCurDCB->fOutX = fOutX;
1505 pCurDCB->fInX = fInX;
1506 pCurDCB->fErrorChar = fErrorChar;
1507 pCurDCB->fNull = fNull;
1508 pCurDCB->fRtsControl = ucRtsControl;
1509 pCurDCB->fAbortOnError = fAbortOnError;
1510 pCurDCB->XonChar = XonChar;
1511 pCurDCB->XoffChar = XoffChar;
1512 pCurDCB->ErrorChar = ErrorChar;
1513 }
1514
1515 return rc;
1516
1517}
1518//******************************************************************************
1519//******************************************************************************
1520APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData,
1521 DWORD dwNewBaud)
1522{
1523 APIRET rc;
1524 ULONG ulLen;
1525 EXTBAUDSET SetBaud;
1526 EXTBAUDGET GetBaud;
1527 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1528
1529 ulLen = sizeof(SetBaud);
1530 SetBaud.ulBaud = dwNewBaud;
1531 SetBaud.ucFrac = 0;
1532 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1533 IOCTL_ASYNC,
1534 ASYNC_EXTSETBAUDRATE,
1535 &SetBaud,ulLen,&ulLen,
1536 NULL,0,NULL);
1537 if(0==rc)
1538 {
1539 ulLen = sizeof(GetBaud);
1540 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1541 IOCTL_ASYNC,
1542 ASYNC_EXTGETBAUDRATE,
1543 NULL,0,NULL,
1544 &GetBaud,ulLen,&ulLen);
1545 if(0==rc)
1546 {
1547 if(dwNewBaud != GetBaud.ulCurrBaud) {
1548 dprintf(("!WARNING! dwNewBaud (%d) != GetBaud.ulCurrBaud (%d)", dwNewBaud, GetBaud.ulCurrBaud));
1549 rc = 1; // ToDo set a proper Errorhandling
1550 }
1551 else
1552 {
1553 pDevData->CommCfg.dcb.BaudRate = dwNewBaud;
1554 }
1555 }
1556 else {
1557 dprintf(("!WARNING! SetBaud: (get) OSLibDosDevIOCtl failed with rc %d", rc));
1558 }
1559 }
1560 else {
1561 dprintf(("!WARNING! SetBaud: (set) OSLibDosDevIOCtl failed with rc %d", rc));
1562 }
1563 return rc;
1564}
1565//******************************************************************************
1566//******************************************************************************
1567void HMDeviceCommClass::CloseOverlappedIOHandlers()
1568{
1569 for(int i=0;i<MAX_COMPORTS;i++) {
1570 if(handler[i]) {
1571 delete handler[i];
1572 handler[i] = NULL;
1573 }
1574 }
1575}
1576//******************************************************************************
1577//******************************************************************************
1578OverlappedIOHandler *HMDeviceCommClass::handler[MAX_COMPORTS] = {NULL};
1579
Note: See TracBrowser for help on using the repository browser.