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

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

overlapped io, com, thread & process updates

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