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

Last change on this file since 7596 was 7596, checked in by sandervl, 24 years ago

Overlapped IO fix (poll)

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