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

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

comm updates

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