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

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

overlapped io updates

File size: 48.9 KB
Line 
1/* $Id: hmcomm.cpp,v 1.27 2001-12-05 18:06:00 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 * TODO: Overlapped IO only supports one request at a time
12 * TODO: Overlapped IO not thread safe
13 *
14 */
15
16
17
18#include <os2win.h>
19#include <string.h>
20#include <handlemanager.h>
21#include "handlenames.h"
22#include <heapstring.h>
23#include "hmdevice.h"
24#include "hmcomm.h"
25#include "oslibdos.h"
26
27#define DBG_LOCALLOG DBG_hmcomm
28#include "dbglocal.h"
29
30//#define TESTING_COMM
31#ifdef TESTING_COMM
32#undef dprintf
33#define dprintf(a) WriteLog a
34#undef dprintf2
35#define dprintf2(a) WriteLog a
36#endif
37
38BAUDTABLEENTRY BaudTable[] =
39{
40 {75,BAUD_075},
41 {110,BAUD_110},
42 {134,BAUD_134_5},
43 {150,BAUD_150},
44 {300,BAUD_300},
45 {600,BAUD_600},
46 {1200,BAUD_1200},
47 {1800,BAUD_1800},
48 {2400,BAUD_2400},
49 {4800,BAUD_4800},
50 {7200,BAUD_7200},
51 {9600,BAUD_9600},
52 {14400,BAUD_14400},
53 {19200,BAUD_19200},
54 {38400,BAUD_38400},
55 {56000,BAUD_56K},
56 {57600,BAUD_57600},
57 {115200,BAUD_115200},
58 {128000,BAUD_128K}
59};
60
61#define BaudTableSize (sizeof(BaudTable)/sizeof(BAUDTABLEENTRY))
62
63//******************************************************************************
64//******************************************************************************
65static VOID *CreateDevData()
66{
67 PHMDEVCOMDATA pData;
68 pData = new HMDEVCOMDATA();
69 if(NULL!=pData)
70 {
71 memset(pData,0,sizeof(HMDEVCOMDATA));
72 pData->ulMagic = MAGIC_COM;
73 pData->CommCfg.dwSize = sizeof(COMMCONFIG);
74 pData->CommCfg.wVersion = 1;
75 pData->CommCfg.dwProviderSubType = PST_RS232;
76 pData->CommCfg.dcb.DCBlength = sizeof(DCB);
77 pData->CommCfg.dcb.BaudRate = CBR_1200;
78 pData->CommCfg.dcb.ByteSize = 8;
79 pData->CommCfg.dcb.Parity = NOPARITY;
80 pData->CommCfg.dcb.StopBits = ONESTOPBIT;
81 pData->dwInBuffer = 16;
82 pData->dwOutBuffer = 16;
83 }
84 return pData;
85}
86//******************************************************************************
87//******************************************************************************
88HMDeviceCommClass::HMDeviceCommClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName)
89{
90 VOID *pData;
91 dprintf(("HMDeviceCommClass: Register COM1 to COM8 with Handle Manager\n"));
92 pData = CreateDevData();
93 if(pData!= NULL)
94 HMDeviceRegisterEx("COM1", this, pData);
95
96 // add symbolic links to the "real name" of the device
97 {
98 // @@@PH what's the long device name: SerialPortx ?
99 // HandleNamesAddSymbolicLink("\\Device\\ParallelPort3", "COM3");
100 // Note: \\.\COMx: is invalid (NT4SP6)
101
102 PSZ pszCOM = strdup("\\\\.\\COMx");
103 for (char ch = '1'; ch <= '9'; ch++)
104 {
105 pszCOM[7] = ch;
106 HandleNamesAddSymbolicLink(pszCOM, pszCOM+4);
107 }
108 free(pszCOM);
109
110 // add "AUX" device
111 HandleNamesAddSymbolicLink("AUX", "COM1");
112 HandleNamesAddSymbolicLink("AUX:", "COM1");
113 HandleNamesAddSymbolicLink("\\\\.\\AUX", "COM1");
114 }
115}
116
117/*****************************************************************************
118 * Name : HMDeviceCommClass::FindDevice
119 * Purpose : Checks if lpDeviceName belongs to this device class
120 * Parameters: LPCSTR lpClassDevName
121 * LPCSTR lpDeviceName
122 * int namelength
123 * Variables :
124 * Result : checks if name is COMx or COMx: (x=1..8)
125 * Remark :
126 * Status :
127 *
128 * Author : SvL
129 *****************************************************************************/
130BOOL HMDeviceCommClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
131{
132 dprintf2(("HMDeviceCommClass::FindDevice %s %s", lpClassDevName, lpDeviceName));
133
134 //first 3 letters 'COM'?
135 if(lstrncmpiA(lpDeviceName, lpClassDevName, 3) != 0) {
136 return FALSE;
137 }
138
139 if(namelength == 5 && lpDeviceName[4] != ':') {
140 return FALSE;
141 }
142 switch(lpDeviceName[3]) {
143 case '1':
144 case '2':
145 case '3':
146 case '4':
147 case '5':
148 case '6':
149 case '7':
150 case '8':
151 return TRUE; //we support up to COM8
152 }
153 return FALSE;
154}
155//******************************************************************************
156//******************************************************************************
157DWORD HMDeviceCommClass::CreateFile(LPCSTR lpFileName,
158 PHMHANDLEDATA pHMHandleData,
159 PVOID lpSecurityAttributes,
160 PHMHANDLEDATA pHMHandleDataTemplate)
161{
162 char comname[6];
163 DWORD ret = ERROR_SUCCESS;
164
165 dprintf(("HMComm: Serial communication port %s open request\n", lpFileName));
166
167 if(strlen(lpFileName) > 5) {
168 lpFileName += 4; //skip prefix
169 }
170
171 pHMHandleData->hHMHandle = 0;
172
173 strcpy(comname, lpFileName);
174 comname[4] = 0; //get rid of : (if present) (eg COM1:)
175
176 //AH: TODO parse Win32 security handles
177 ULONG oldmode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
178 pHMHandleData->hHMHandle = OSLibDosOpen(comname,
179 OSLIB_ACCESS_READWRITE |
180 OSLIB_ACCESS_SHAREDENYREAD |
181 OSLIB_ACCESS_SHAREDENYWRITE);
182 ::SetErrorMode(oldmode);
183 if (pHMHandleData->hHMHandle != 0)
184 {
185 ULONG ulLen;
186 APIRET rc;
187 pHMHandleData->lpHandlerData = new HMDEVCOMDATA();
188 // Init The handle instance with the default default device config
189 memcpy( pHMHandleData->lpHandlerData,
190 pHMHandleData->lpDeviceData,
191 sizeof(HMDEVCOMDATA));
192
193 ulLen = sizeof(DCBINFO);
194
195 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
196 IOCTL_ASYNC,
197 ASYNC_GETDCBINFO,
198 0,0,0,
199 &((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2,ulLen,&ulLen);
200 dprintf(("DCB Of %s :\n"
201 " WriteTimeout : %d\n"
202 " ReadTimeout : %d\n"
203 " CtlHandshake : 0x%x\n"
204 " FlowReplace : 0x%x\n"
205 " Timeout : 0x%x\n"
206 " Error replacement Char : 0x%x\n"
207 " Break replacement Char : 0x%x\n"
208 " XON Char : 0x%x\n"
209 " XOFF Char : 0x%x\n",
210 comname,
211 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.usWriteTimeout,
212 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.usReadTimeout,
213 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbCtlHndShake,
214 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbFlowReplace,
215 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.fbTimeOut,
216 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bErrorReplacementChar,
217 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bBreakReplacementChar,
218 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bXONChar,
219 ((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2.bXOFFChar));
220
221 if(rc)
222 {
223 OSLibDosClose(pHMHandleData->hHMHandle);
224 delete pHMHandleData->lpHandlerData;
225 return rc;
226 }
227 rc = SetBaud(pHMHandleData,9600);
228 dprintf(("Init Baud to 9600 rc = %d",rc));
229 rc = SetLine(pHMHandleData,8,0,0);
230 dprintf(("Set Line to 8/N/1 rc = %d",rc));
231
232 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
233 {
234 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
235 DWORD dwThreadId;
236
237 }
238 return ERROR_SUCCESS;
239 }
240 else
241 return ERROR_ACCESS_DENIED;
242
243
244fail:
245
246 delete pHMHandleData->lpHandlerData;
247 OSLibDosClose(pHMHandleData->hHMHandle);
248 return ret;
249}
250/*****************************************************************************
251 * Name : DWORD HMDeviceCommClass::GetFileType
252 * Purpose : determine the handle type
253 * Parameters: PHMHANDLEDATA pHMHandleData
254 * Variables :
255 * Result : API returncode
256 * Remark :
257 * Status :
258 *
259 * Author : SvL
260 *****************************************************************************/
261
262DWORD HMDeviceCommClass::GetFileType(PHMHANDLEDATA pHMHandleData)
263{
264 dprintf(("KERNEL32: HMDeviceCommClass::GetFileType %s(%08x)\n",
265 lpHMDeviceName,
266 pHMHandleData));
267
268 return FILE_TYPE_CHAR;
269}
270//******************************************************************************
271//******************************************************************************
272BOOL HMDeviceCommClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
273{
274 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
275 dprintf(("HMComm: Serial communication port close request"));
276
277 if(pDevData && pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
278 {
279 DebugInt3();
280 }
281 delete pHMHandleData->lpHandlerData;
282 return OSLibDosClose(pHMHandleData->hHMHandle);
283}
284/*****************************************************************************
285 * Name : BOOL HMDeviceCommClass::WriteFile
286 * Purpose : write data to handle / device
287 * Parameters: PHMHANDLEDATA pHMHandleData,
288 * LPCVOID lpBuffer,
289 * DWORD nNumberOfBytesToWrite,
290 * LPDWORD lpNumberOfBytesWritten,
291 * LPOVERLAPPED lpOverlapped
292 * Variables :
293 * Result : Boolean
294 * Remark :
295 * Status :
296 *
297 * Author : SvL
298 *****************************************************************************/
299BOOL HMDeviceCommClass::WriteFile(PHMHANDLEDATA pHMHandleData,
300 LPCVOID lpBuffer,
301 DWORD nNumberOfBytesToWrite,
302 LPDWORD lpNumberOfBytesWritten,
303 LPOVERLAPPED lpOverlapped,
304 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
305{
306 dprintf(("KERNEL32:HMDeviceCommClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
307 lpHMDeviceName,
308 pHMHandleData->hHMHandle,
309 lpBuffer,
310 nNumberOfBytesToWrite,
311 lpNumberOfBytesWritten,
312 lpOverlapped));
313
314 BOOL ret;
315 ULONG ulBytesWritten;
316
317 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
318 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
319 ::SetLastError(ERROR_INVALID_PARAMETER);
320 return FALSE;
321 }
322 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
323 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
324 }
325 if(lpCompletionRoutine) {
326 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
327 }
328
329//testestestest
330 dprintf2(("Bytes to write:"));
331 for(int i=0;i<nNumberOfBytesToWrite;i++) {
332 dprintf2(("%x %c", ((char *)lpBuffer)[i], ((char *)lpBuffer)[i]));
333 }
334//testestestset
335
336 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite,
337 &ulBytesWritten);
338
339 if(lpNumberOfBytesWritten) {
340 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0;
341 dprintf2(("KERNEL32:HMDeviceCommClass::WriteFile %d byte(s) written", *lpNumberOfBytesWritten));
342 }
343 if(ret == FALSE) {
344 dprintf(("!ERROR!: WriteFile failed with rc %d", GetLastError()));
345 }
346
347 return ret;
348}
349/*****************************************************************************
350 * Name : BOOL HMDeviceCommClass::ReadFile
351 * Purpose : read data from handle / device
352 * Parameters: PHMHANDLEDATA pHMHandleData,
353 * LPCVOID lpBuffer,
354 * DWORD nNumberOfBytesToRead,
355 * LPDWORD lpNumberOfBytesRead,
356 * LPOVERLAPPED lpOverlapped
357 * Variables :
358 * Result : Boolean
359 * Remark :
360 * Status :
361 *
362 * Author : SvL
363 *****************************************************************************/
364
365BOOL HMDeviceCommClass::ReadFile(PHMHANDLEDATA pHMHandleData,
366 LPCVOID lpBuffer,
367 DWORD nNumberOfBytesToRead,
368 LPDWORD lpNumberOfBytesRead,
369 LPOVERLAPPED lpOverlapped,
370 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
371{
372 dprintf(("KERNEL32:HMDeviceCommClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
373 lpHMDeviceName,
374 pHMHandleData->hHMHandle,
375 lpBuffer,
376 nNumberOfBytesToRead,
377 lpNumberOfBytesRead,
378 lpOverlapped));
379
380 BOOL ret;
381 ULONG ulBytesRead;
382
383 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
384 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
385 ::SetLastError(ERROR_INVALID_PARAMETER);
386 return FALSE;
387 }
388 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
389 dprintf(("!WARNING!: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
390 }
391
392 if(lpCompletionRoutine) {
393 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
394 }
395
396 RXQUEUE qInfo;
397 ULONG ulLen = sizeof(qInfo);
398 ULONG rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
399 IOCTL_ASYNC,
400 ASYNC_GETINQUECOUNT,
401 0,0,0,
402 &qInfo,ulLen,&ulLen);
403 dprintf(("ASYNC_GETINQUECOUNT -> qInfo.cch %d (queue size %d) rc %d", qInfo.cch, qInfo.cb, rc));
404
405 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
406 &ulBytesRead);
407
408 if(lpNumberOfBytesRead) {
409 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0;
410 dprintf2(("KERNEL32:HMDeviceCommClass::ReadFile %d bytes read", *lpNumberOfBytesRead));
411 }
412 if(ret == FALSE) {
413 dprintf(("!ERROR!: ReadFile failed with rc %d", GetLastError()));
414 }
415 else {
416//testestestest
417 dprintf2(("%d Bytes read:", ulBytesRead));
418 for(int i=0;i<ulBytesRead;i++) {
419 dprintf2(("%x %c", ((char *)lpBuffer)[i], ((char *)lpBuffer)[i]));
420 }
421//testestestset
422 }
423 return ret;
424}
425
426/*****************************************************************************
427 * Name : DWORD HMDeviceHandler::SetupComm
428 * Purpose : set com port parameters (queue)
429 * Variables :
430 * Result :
431 * Remark :
432 * Status :
433 *
434 * Author : Achim Hasenmueller
435 *****************************************************************************/
436
437BOOL HMDeviceCommClass::SetupComm( PHMHANDLEDATA pHMHandleData,
438 DWORD dwInQueue,
439 DWORD dwOutQueue)
440{
441 dprintf(("HMDeviceCommClass::SetupComm "));
442 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
443 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
444 {
445 ::SetLastError(ERROR_INVALID_HANDLE);
446 return FALSE;
447 }
448 pDevData->dwInBuffer = dwInQueue;
449 pDevData->dwOutBuffer = dwOutQueue;
450
451 return(TRUE);
452}
453//******************************************************************************
454#define TIMEOUT_COMM 50
455//******************************************************************************
456BOOL HMDeviceCommClass::WaitCommEvent( PHMHANDLEDATA pHMHandleData,
457 LPDWORD lpfdwEvtMask,
458 LPOVERLAPPED lpo)
459{
460 APIRET rc;
461 ULONG ulLen;
462 USHORT COMEvt;
463 DWORD dwEvent,dwMask;
464
465 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
466
467 dprintf(("HMDeviceCommClass::WaitCommEvent %x %x %x", pHMHandleData->hHMHandle, lpfdwEvtMask, lpo));
468
469 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo) {
470 dprintf(("!WARNING! pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo"));
471 ::SetLastError(ERROR_INVALID_PARAMETER);
472 return FALSE;
473 }
474
475 ulLen = sizeof(CHAR);
476
477 dwEvent = 0;
478 rc = 0;
479 ulLen = sizeof(COMEvt);
480 dwMask = pDevData->dwEventMask;
481 while( (0==rc) &&
482 !(dwEvent & dwMask) &&
483 (dwMask ==pDevData->dwEventMask) ) // Exit if the Mask gets changed
484 {
485 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
486 IOCTL_ASYNC,
487 ASYNC_GETCOMMEVENT,
488 0,0,0,
489 &COMEvt,ulLen,&ulLen);
490 if(!rc)
491 {
492 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
493 //dwEvent |= (COMEvt&0x0002)? 0:0;
494 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
495 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
496 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
497 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD?
498 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
499 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
500 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
501 if((dwEvent & dwMask)) break;
502 }
503 else break;
504
505 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
506 {
507 memcpy(&pDevData->overlapped, lpo, sizeof(pDevData->overlapped));
508 pDevData->overlapped.Internal = 0;
509 pDevData->overlapped.InternalHigh = 0;
510 pDevData->overlapped.Offset = 0;
511 pDevData->overlapped.OffsetHigh = 0;
512 //We're also supposed to write the result to the address supplied
513 //by this call
514 pDevData->lpfdwEvtMask = lpfdwEvtMask;
515 //Set app event semaphore to non-signalled state
516 ::ResetEvent(lpo->hEvent);
517
518 ::SetLastError(ERROR_IO_PENDING);
519 return FALSE;
520 }
521 DosSleep(TIMEOUT_COMM);
522 }
523 if(dwMask == pDevData->dwEventMask) {
524 *lpfdwEvtMask = (rc==0) ? (dwEvent & dwMask) : 0;
525 dprintf(("WaitCommEvent returned %x", *lpfdwEvtMask));
526 }
527 else *lpfdwEvtMask = 0;
528
529 ::SetLastError(rc);
530 return (rc==0);
531}
532/*****************************************************************************
533 * Name : DWORD HMDeviceCommClass::CancelIo
534 * Purpose : cancel pending IO operation
535 * Variables :
536 * Result :
537 * Remark :
538 * Status :
539 *
540 * Author : SvL
541 *****************************************************************************/
542BOOL HMDeviceCommClass::CancelIo(PHMHANDLEDATA pHMHandleData)
543{
544 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
545
546 dprintf(("HMDeviceCommClass::CancelIo"));
547 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
548 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
549 return FALSE;
550 }
551
552 //signal serial thread to cancel pending IO operation
553 pDevData->fCancelIo = TRUE;
554// ::SetEvent(pDevData->hEventSem);
555
556 ::SetLastError(ERROR_SUCCESS);
557 return(TRUE);
558}
559/*****************************************************************************
560 * Name : DWORD HMDeviceFileClass::GetOverlappedResult
561 * Purpose : asynchronus I/O
562 * Parameters: PHMHANDLEDATA pHMHandleData
563 * LPOVERLAPPED arg2
564 * LPDWORD arg3
565 * BOOL arg4
566 * Variables :
567 * Result : API returncode
568 * Remark :
569 * Status :
570 *
571 * Author : SvL
572 *****************************************************************************/
573BOOL HMDeviceCommClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData,
574 LPOVERLAPPED lpoOverlapped,
575 LPDWORD lpcbTransfer,
576 BOOL fWait)
577{
578 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
579
580 dprintf(("KERNEL32-WARNING: HMDeviceCommClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh) partly implemented",
581 pHMHandleData->hHMHandle,
582 lpoOverlapped,
583 lpcbTransfer,
584 fWait));
585
586 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
587 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
588 return FALSE;
589 }
590 if(!lpoOverlapped) {
591 ::SetLastError(ERROR_INVALID_PARAMETER);
592 return FALSE;
593 }
594 if(lpoOverlapped->hEvent != pDevData->overlapped.hEvent) {
595 dprintf(("!WARNING!: GetOverlappedResult called for unknown operation"));
596 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
597 return FALSE;
598 }
599 if(pDevData->overlapped.Internal) {
600 lpoOverlapped->Internal = pDevData->overlapped.Internal;
601 pDevData->overlapped.Internal = 0; //not entirely safe
602 pDevData->dwLastError = 0;
603 ::SetLastError(pDevData->dwLastError);
604 return lpoOverlapped->Internal;
605 }
606 if(fWait) {
607 ::WaitForSingleObject(pDevData->overlapped.hEvent, INFINITE);
608 ::ResetEvent(pDevData->overlapped.hEvent);
609 lpoOverlapped->Internal = pDevData->overlapped.Internal;
610 pDevData->overlapped.Internal = 0; //not entirely safe
611 ::SetLastError(ERROR_SUCCESS);
612 return lpoOverlapped->Internal;
613 }
614 else {
615 ::SetLastError(ERROR_IO_PENDING);
616 return FALSE;
617 }
618}
619//******************************************************************************
620//******************************************************************************
621BOOL HMDeviceCommClass::GetCommProperties( PHMHANDLEDATA pHMHandleData,
622 LPCOMMPROP lpcmmp)
623{
624 EXTBAUDGET BaudInfo;
625 APIRET rc;
626 ULONG ulLen;
627 USHORT COMErr;
628 int i;
629 dprintf(("HMDeviceCommClass::GetCommProperties"));
630
631 ulLen = sizeof(EXTBAUDGET);
632 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
633 IOCTL_ASYNC,
634 ASYNC_EXTGETBAUDRATE,
635 0,0,0,
636 &BaudInfo,ulLen,&ulLen);
637 memset(lpcmmp,0,sizeof(COMMPROP));
638 lpcmmp->wPacketLength = sizeof(COMMPROP);
639 lpcmmp->wPacketVersion = 1; //???
640 lpcmmp->dwServiceMask = SP_SERIALCOMM;
641 for(i=0;i<BaudTableSize && BaudInfo.ulMaxBaud <= BaudTable[i].dwBaudRate;i++);
642 lpcmmp->dwMaxBaud = BaudTable[i].dwBaudFlag;
643 lpcmmp->dwProvSubType = PST_RS232;
644 lpcmmp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK |
645 PCF_RTSCTS | PCF_SETXCHAR |
646 PCF_XONXOFF;
647 lpcmmp->dwSettableParams = SP_BAUD | SP_DATABITS |
648 SP_HANDSHAKEING | SP_PARITY |
649 SP_PARITY_CHECK | SP_STOPBIT;
650 lpcmmp->dwSettableBaud = 0;
651 for(i=0;i<BaudTableSize;i++)
652 {
653 if ( (BaudTable[i].dwBaudRate>=BaudInfo.ulMinBaud) &&
654 (BaudTable[i].dwBaudRate<=BaudInfo.ulMaxBaud) )
655 lpcmmp->dwSettableBaud |= BaudTable[i].dwBaudFlag;
656 }
657 lpcmmp->dwSettableBaud |= BAUD_USER;
658 lpcmmp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
659 lpcmmp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
660 PARITY_NONE | PARITY_ODD | PARITY_EVEN |
661 PARITY_MARK | PARITY_SPACE;
662 return(rc==0);
663}
664//******************************************************************************
665//******************************************************************************
666BOOL HMDeviceCommClass::GetCommMask( PHMHANDLEDATA pHMHandleData,
667 LPDWORD lpfdwEvtMask)
668{
669 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
670
671 dprintf(("HMDeviceCommClass::GetCommMask"));
672
673 *lpfdwEvtMask = pDevData->dwEventMask;
674 return(TRUE);
675}
676//******************************************************************************
677//******************************************************************************
678BOOL HMDeviceCommClass::SetCommMask( PHMHANDLEDATA pHMHandleData,
679 DWORD fdwEvtMask)
680{
681 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
682 dprintf(("HMDeviceCommClass::SetCommMask %x", fdwEvtMask));
683
684 if(fdwEvtMask & (EV_RLSD|EV_RXFLAG)) {
685 dprintf(("!WARNING! SetCommMask: unsupported flags EV_RLSD and/or EV_RXFLAG!!"));
686 }
687
688 pDevData->dwEventMask = fdwEvtMask & ~(EV_RLSD|EV_RXFLAG); // Clear the 2 not supported Flags.
689 return(TRUE);
690}
691//******************************************************************************
692//******************************************************************************
693BOOL HMDeviceCommClass::PurgeComm( PHMHANDLEDATA pHMHandleData,
694 DWORD fdwAction)
695{
696 ULONG ulParLen, ulDataLen, rc = ERROR_SUCCESS;
697 BYTE par = 0;
698 WORD data = 0;
699
700 dprintf(("HMDeviceCommClass::PurgeComm (flags 0x%x) partly implemented",fdwAction));
701 // ToDo: find a way to stop the current transmision didn't find
702 // any clue how to in Control Program Guide and reference
703
704 ulParLen = sizeof(par);
705 ulDataLen = sizeof(data);
706 if(fdwAction & PURGE_TXCLEAR) {
707 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
708 IOCTL_GENERAL,
709 DEV_FLUSHOUTPUT,
710 &par,ulParLen,&ulParLen,
711 &data,ulDataLen,&ulDataLen);
712 }
713 if(fdwAction & PURGE_RXCLEAR) {
714 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
715 IOCTL_GENERAL,
716 DEV_FLUSHINPUT,
717 &par,ulParLen,&ulParLen,
718 &data,ulDataLen,&ulDataLen);
719 }
720 if(rc) {
721 dprintf(("!WARNING! OSLibDosDevIOCtl failed with rc %d", rc));
722 }
723 return (rc == ERROR_SUCCESS);
724}
725//******************************************************************************
726//******************************************************************************
727BOOL HMDeviceCommClass::ClearCommError( PHMHANDLEDATA pHMHandleData,
728 LPDWORD lpdwErrors,
729 LPCOMSTAT lpcst)
730{
731 APIRET rc;
732 ULONG ulLen;
733 USHORT COMErr;
734
735 dprintf(("HMDeviceCommClass::ClearCommError"));
736 ulLen = sizeof(USHORT);
737
738 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
739 IOCTL_ASYNC,
740 ASYNC_GETCOMMERROR,
741 0,0,0,
742 &COMErr,2,&ulLen);
743 *lpdwErrors = 0;
744 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
745 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
746 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
747 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
748
749 if(lpcst)
750 {
751 UCHAR ucStatus;
752 RXQUEUE qInfo;
753 ulLen = 1;
754 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
755 IOCTL_ASYNC,
756 ASYNC_GETCOMMSTATUS,
757 0,0,0,
758 &ucStatus,ulLen,&ulLen);
759 if(!rc)
760 {
761 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
762 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
763 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
764 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
765 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
766 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
767 lpcst->fTxim = ((ucStatus & 0x40)>0);
768
769 ulLen = sizeof(qInfo);
770 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
771 IOCTL_ASYNC,
772 ASYNC_GETINQUECOUNT,
773 0,0,0,
774 &qInfo,ulLen,&ulLen);
775 if(!rc)
776 {
777 lpcst->cbInQue = qInfo.cch;
778 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
779 IOCTL_ASYNC,
780 ASYNC_GETOUTQUECOUNT,
781 0,0,0,
782 &qInfo,ulLen,&ulLen);
783 if(!rc)
784 lpcst->cbOutQue = qInfo.cch;
785 }
786 }
787 }
788
789 return(rc==0);
790}
791//******************************************************************************
792//******************************************************************************
793BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData,
794 LPDCB lpDCB)
795{
796 APIRET rc;
797 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
798 DCB *pCurDCB = &pDevData->CommCfg.dcb;
799 dprintf(("HMDeviceCommClass::SetCommState"));
800
801 rc = 0;
802 if(pCurDCB->BaudRate != lpDCB->BaudRate) {
803 dprintf(("SetCommState: change baud rate from %d to %d", pCurDCB->BaudRate, lpDCB->BaudRate));
804 rc = SetBaud( pHMHandleData,
805 lpDCB->BaudRate);
806 }
807
808 if(!rc)
809 {
810 if( (pCurDCB->ByteSize != lpDCB->ByteSize) ||
811 (pCurDCB->Parity != lpDCB->Parity) ||
812 (pCurDCB->StopBits != lpDCB->StopBits))
813 {
814 dprintf(("SetCommState: change line %d %d %d", lpDCB->ByteSize, lpDCB->Parity, lpDCB->StopBits));
815 rc = SetLine( pHMHandleData,
816 lpDCB->ByteSize,
817 lpDCB->Parity,
818 lpDCB->StopBits);
819 }
820 }
821
822 if(!rc)
823 {
824 if( (pCurDCB->fOutxCtsFlow != lpDCB->fOutxCtsFlow) ||
825 (pCurDCB->fOutxDsrFlow != lpDCB->fOutxDsrFlow) ||
826 (pCurDCB->fDtrControl != lpDCB->fDtrControl) ||
827 (pCurDCB->fDsrSensitivity != lpDCB->fDsrSensitivity) ||
828 (pCurDCB->fTXContinueOnXoff != lpDCB->fTXContinueOnXoff) ||
829 (pCurDCB->fOutX != lpDCB->fOutX) ||
830 (pCurDCB->fInX != lpDCB->fInX) ||
831 (pCurDCB->fErrorChar != lpDCB->fErrorChar) ||
832 (pCurDCB->fNull != lpDCB->fNull) ||
833 (pCurDCB->fRtsControl != lpDCB->fRtsControl) ||
834 (pCurDCB->fAbortOnError != lpDCB->fAbortOnError) ||
835 (pCurDCB->XonChar != lpDCB->XonChar) ||
836 (pCurDCB->XoffChar != lpDCB->XoffChar) ||
837 (pCurDCB->ErrorChar != lpDCB->ErrorChar))
838 {
839 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));
840 SetOS2DCB( pHMHandleData,
841 lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,
842 lpDCB->fDtrControl, lpDCB->fDsrSensitivity,
843 lpDCB->fTXContinueOnXoff, lpDCB->fOutX,
844 lpDCB->fInX, lpDCB->fErrorChar,
845 lpDCB->fNull, lpDCB->fRtsControl,
846 lpDCB->fAbortOnError, lpDCB->XonChar,
847 lpDCB->XoffChar,lpDCB->ErrorChar);
848 }
849 }
850
851 return(rc==0);
852}
853//******************************************************************************
854//******************************************************************************
855BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData,
856 LPDCB lpdcb)
857{
858 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
859
860 dprintf(("HMDeviceCommClass::GetCommState %x", lpdcb));
861
862 if(lpdcb == NULL) {
863 ::SetLastError(ERROR_INVALID_PARAMETER);
864 return FALSE;
865 }
866
867 memcpy(lpdcb,&pDevData->CommCfg.dcb,sizeof(DCB));
868 return(TRUE);
869}
870//******************************************************************************
871//******************************************************************************
872BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData,
873 LPDWORD lpModemStat )
874{
875 APIRET rc;
876 ULONG ulLen;
877 USHORT COMErr;
878 UCHAR ucStatus;
879
880 dprintf(("HMDeviceCommClass::GetCommModemStatus %x", lpModemStat));
881 if(lpModemStat == NULL) {
882 ::SetLastError(ERROR_INVALID_PARAMETER);
883 return FALSE;
884 }
885
886 ulLen = sizeof(CHAR);
887
888 ulLen = 1;
889 *lpModemStat = 0;
890
891 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
892 IOCTL_ASYNC,
893 ASYNC_GETMODEMINPUT,
894 0,0,0,
895 &ucStatus,ulLen,&ulLen);
896 if(!rc)
897 {
898 *lpModemStat |= (ucStatus & 0x10)? MS_CTS_ON:0;
899 *lpModemStat |= (ucStatus & 0x20)? MS_DSR_ON:0;
900 *lpModemStat |= (ucStatus & 0x40)? MS_RING_ON:0;
901 //*lpModemStat |= (ucStatus & 0x80)? MS_RSLD_ON:0;
902 }
903
904 dprintf2(("HMDeviceCommClass::GetCommModemStatus -> %x rc=%d", *lpModemStat, rc));
905 return(rc==0);
906}
907//******************************************************************************
908//******************************************************************************
909BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData,
910 LPCOMMTIMEOUTS lpctmo)
911{
912 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
913
914 dprintf(("HMDeviceCommClass::GetCommTimeouts %x stub", lpctmo));
915
916 if(lpctmo == NULL) {
917 ::SetLastError(ERROR_INVALID_PARAMETER);
918 return FALSE;
919 }
920
921 memcpy( lpctmo,
922 &pDevData->CommTOuts,
923 sizeof(COMMTIMEOUTS));
924 return(TRUE);
925}
926//******************************************************************************
927//******************************************************************************
928BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData,
929 LPCOMMTIMEOUTS lpctmo)
930{
931 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
932 DCBINFO os2dcb;
933 ULONG ulLen;
934 APIRET rc;
935 UCHAR fbTimeOut;
936
937 if(lpctmo == NULL) {
938 dprintf(("!WARNING! HMDeviceCommClass::SetCommTimeouts %x -> invalid parameter", lpctmo));
939 ::SetLastError(ERROR_INVALID_PARAMETER);
940 return FALSE;
941 }
942
943 dprintf(("HMDeviceCommClass::SetCommTimeouts\n"
944 " ReadIntervalTimeout : 0x%x\n"
945 " ReadTotalTimeoutMultiplier : %d\n"
946 " ReadTotalTimeoutConstant : %d\n"
947 " WriteTotalTimeoutMultiplier : %d\n"
948 " WriteTotalTimeoutConstant : %d\n",
949 lpctmo->ReadIntervalTimeout,
950 lpctmo->ReadTotalTimeoutMultiplier,
951 lpctmo->ReadTotalTimeoutConstant,
952 lpctmo->WriteTotalTimeoutMultiplier,
953 lpctmo->WriteTotalTimeoutConstant
954 ));
955
956 memcpy( &pDevData->CommTOuts,
957 lpctmo,
958 sizeof(COMMTIMEOUTS));
959
960 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
961
962 fbTimeOut = 0x02; //normal processing (wait until timout or buffer full)
963 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
964 {
965 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
966 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
967 fbTimeOut = 0x05; //no wait
968 else
969 fbTimeOut = 0x04; //wait for something
970 }
971 else
972 {
973 DWORD dwTimeout;
974 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
975 if(dwTimeout)
976 dwTimeout--; // 0=10 ms unit is 10ms or .01s
977
978 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
979 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
980 }
981 if( (0==pDevData->CommTOuts.WriteTotalTimeoutMultiplier) &&
982 (0==pDevData->CommTOuts.WriteTotalTimeoutConstant))
983 {//no timeout used for writing
984 os2dcb.fbTimeOut |= 1; //write infinite timeout
985 }
986
987 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF8) | fbTimeOut;
988
989 dprintf((" New DCB:\n"
990 " WriteTimeout : %d\n"
991 " ReadTimeout : %d\n"
992 " CtlHandshake : 0x%x\n"
993 " FlowReplace : 0x%x\n"
994 " Timeout : 0x%x\n"
995 " Error replacement Char : 0x%x\n"
996 " Break replacement Char : 0x%x\n"
997 " XON Char : 0x%x\n"
998 " XOFF Char : 0x%x\n",
999 os2dcb.usWriteTimeout,
1000 os2dcb.usReadTimeout,
1001 os2dcb.fbCtlHndShake,
1002 os2dcb.fbFlowReplace,
1003 os2dcb.fbTimeOut,
1004 os2dcb.bErrorReplacementChar,
1005 os2dcb.bBreakReplacementChar,
1006 os2dcb.bXONChar,
1007 os2dcb.bXOFFChar));
1008
1009 ulLen = sizeof(DCBINFO);
1010 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1011 IOCTL_ASYNC,
1012 ASYNC_SETDCBINFO,
1013 &os2dcb,ulLen,&ulLen,
1014 NULL,0,NULL);
1015 dprintf(("IOCRL returned %d",rc));
1016 return(0==rc);
1017}
1018//******************************************************************************
1019//******************************************************************************
1020BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData,
1021 CHAR cChar )
1022{
1023 APIRET rc;
1024 ULONG ulLen;
1025 USHORT COMErr;
1026
1027 dprintf(("HMDeviceCommClass::TransmitCommChar"));
1028 ulLen = sizeof(CHAR);
1029
1030 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1031 IOCTL_ASYNC,
1032 ASYNC_TRANSMITIMM,
1033 &cChar,ulLen,&ulLen,
1034 NULL,0,NULL);
1035
1036 return(rc==0);
1037}
1038//******************************************************************************
1039//******************************************************************************
1040BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData )
1041{
1042 APIRET rc;
1043 ULONG ulLen;
1044 USHORT COMErr;
1045
1046 dprintf(("HMDeviceCommClass::SetCommBreak"));
1047 ulLen = sizeof(USHORT);
1048
1049 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1050 IOCTL_ASYNC,
1051 ASYNC_SETBREAKON,
1052 0,0,0,
1053 &COMErr,2,&ulLen);
1054
1055 return(rc==0);
1056}
1057//******************************************************************************
1058//******************************************************************************
1059BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData)
1060{
1061 APIRET rc;
1062 ULONG ulLen;
1063 USHORT COMErr;
1064
1065 dprintf(("HMDeviceCommClass::ClearCommBreak"));
1066 ulLen = sizeof(USHORT);
1067
1068 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1069 IOCTL_ASYNC,
1070 ASYNC_SETBREAKOFF,
1071 0,0,0,
1072 &COMErr,2,&ulLen);
1073
1074 return(rc==0);
1075}
1076//******************************************************************************
1077//******************************************************************************
1078BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
1079 LPCOMMCONFIG lpCC,
1080 DWORD dwSize )
1081{
1082 dprintf(("HMDeviceCommClass::SetCommConfig NOT IMPLEMENTED"));
1083
1084 return(TRUE);
1085}
1086//******************************************************************************
1087//******************************************************************************
1088BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
1089 LPCOMMCONFIG lpCC,
1090 LPDWORD lpdwSize )
1091{
1092 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1093
1094 dprintf(("HMDeviceCommClass::GetCommConfig"));
1095
1096 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1097 *lpdwSize< sizeof(COMMCONFIG) )
1098 {
1099 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1100 *lpdwSize= sizeof(COMMCONFIG);
1101 return FALSE;
1102 }
1103
1104 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1105 {
1106 ::SetLastError(ERROR_INVALID_HANDLE);
1107 return FALSE;
1108 }
1109
1110 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1111 *lpdwSize = sizeof(COMMCONFIG);
1112 return(TRUE);
1113}
1114//******************************************************************************
1115//******************************************************************************
1116BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData,
1117 UINT dwFunc )
1118{
1119 APIRET rc;
1120 ULONG ulDLen,ulPLen;
1121 USHORT COMErr;
1122 MODEMSTATUS mdm;
1123
1124 dprintf(("HMDeviceCommClass::EscapeCommFunction %x", dwFunc));
1125
1126 ulDLen = sizeof(USHORT);
1127 ulPLen = sizeof(MODEMSTATUS);
1128 switch(dwFunc)
1129 {
1130 case CLRDTR:
1131 mdm.fbModemOn = 0x00;
1132 mdm.fbModemOff = 0XFE;
1133 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1134 IOCTL_ASYNC,
1135 ASYNC_SETMODEMCTRL,
1136 &mdm,ulPLen,&ulPLen,
1137 &COMErr,ulDLen,&ulDLen);
1138 dprintf(("CLRDTR rc = %d Comerror = 0x%x",rc,COMErr));
1139 rc = COMErr;
1140 if(rc==0)
1141 {
1142 BYTE bModem;
1143 ulDLen = sizeof(BYTE);
1144 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1145 IOCTL_ASYNC,
1146 ASYNC_GETMODEMOUTPUT,
1147 NULL,0,NULL,
1148 &bModem,ulDLen,&ulDLen);
1149 dprintf(("Check DTR rc = %d Flags = 0x%x",rc,bModem));
1150 rc = bModem & 0x01;
1151 }
1152 break;
1153 case CLRRTS:
1154 mdm.fbModemOn = 0x00;
1155 mdm.fbModemOff = 0XFD;
1156 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1157 IOCTL_ASYNC,
1158 ASYNC_SETMODEMCTRL,
1159 &mdm,ulPLen,&ulPLen,
1160 &COMErr,ulDLen,&ulDLen);
1161 dprintf(("CLRRTS: rc = %d, Comm error %x", rc, COMErr));
1162 break;
1163 case SETDTR:
1164 mdm.fbModemOn = 0x01;
1165 mdm.fbModemOff = 0XFF;
1166 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1167 IOCTL_ASYNC,
1168 ASYNC_SETMODEMCTRL,
1169 &mdm,ulPLen,&ulPLen,
1170 &COMErr,ulDLen,&ulDLen);
1171 dprintf(("SETDTR: rc = %d, Comm error %x", rc, COMErr));
1172 break;
1173 case SETRTS:
1174 mdm.fbModemOn = 0x02;
1175 mdm.fbModemOff = 0XFF;
1176 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1177 IOCTL_ASYNC,
1178 ASYNC_SETMODEMCTRL,
1179 &mdm,ulPLen,&ulPLen,
1180 &COMErr,ulDLen,&ulDLen);
1181 dprintf(("SETRTS: rc = %d, Comm error %x", rc, COMErr));
1182 break;
1183 case SETXOFF:
1184 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1185 IOCTL_ASYNC,
1186 ASYNC_STOPTRANSMIT,
1187 0,0,0,
1188 0,0,0);
1189 dprintf(("SETXOFF: rc = %d", rc));
1190 break;
1191 case SETXON:
1192 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1193 IOCTL_ASYNC,
1194 ASYNC_STARTTRANSMIT,
1195 0,0,0,
1196 0,0,0);
1197 dprintf(("SETXON: rc = %d", rc));
1198 break;
1199 default:
1200 dprintf(("!ERROR!: EscapeCommFunction: unknown function"));
1201 ::SetLastError(ERROR_INVALID_PARAMETER);
1202 return(FALSE);
1203 }
1204
1205 return(rc==0);
1206}
1207//******************************************************************************
1208//******************************************************************************
1209BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1210 LPCOMMCONFIG lpCC,
1211 DWORD dwSize)
1212{
1213 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1214 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1215 {
1216 ::SetLastError(ERROR_INVALID_HANDLE);
1217 return FALSE;
1218 }
1219
1220 dprintf(("SetDefaultCommConfig %x %d", lpCC, dwSize));
1221 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
1222 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
1223
1224 return(TRUE);
1225}
1226//******************************************************************************
1227//******************************************************************************
1228BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1229 LPCOMMCONFIG lpCC,
1230 LPDWORD lpdwSize)
1231{
1232 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1233
1234 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1235 *lpdwSize< sizeof(COMMCONFIG) )
1236 {
1237 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1238 *lpdwSize= sizeof(COMMCONFIG);
1239 return FALSE;
1240 }
1241
1242 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1243 {
1244 ::SetLastError(ERROR_INVALID_HANDLE);
1245 return FALSE;
1246 }
1247 dprintf(("GetDefaultCommConfig %x %x", lpCC, lpdwSize));
1248
1249 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1250 *lpdwSize = sizeof(COMMCONFIG);
1251 return(TRUE);
1252}
1253//******************************************************************************
1254//******************************************************************************
1255APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData,
1256 UCHAR ucSize,
1257 UCHAR ucParity,
1258 UCHAR ucStop)
1259{
1260 APIRET rc;
1261 ULONG ulLen;
1262 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1263 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1264 struct
1265 {
1266 UCHAR ucSize;
1267 UCHAR ucParity;
1268 UCHAR ucStop;
1269 UCHAR ucPadding;
1270 }Param;
1271
1272 ulLen = 3;
1273 Param.ucSize = ucSize;
1274 Param.ucParity = ucParity;
1275 Param.ucStop = ucStop;
1276
1277 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1278 IOCTL_ASYNC,
1279 ASYNC_SETLINECTRL,
1280 &Param,ulLen,&ulLen,
1281 NULL,0,NULL);
1282
1283 if(0==rc)
1284 {
1285 pCurDCB->ByteSize = ucSize;
1286 pCurDCB->Parity = ucParity;
1287 pCurDCB->StopBits = ucStop;
1288 }
1289 else {
1290 dprintf(("!ERROR! SetLine: OSLibDosDevIOCtl failed with rc %d", rc));
1291 }
1292 return rc;
1293}
1294//******************************************************************************
1295//******************************************************************************
1296APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData,
1297 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow,
1298 UCHAR ucDtrControl, BOOL fDsrSensitivity,
1299 BOOL fTXContinueOnXoff, BOOL fOutX,
1300 BOOL fInX, BOOL fErrorChar,
1301 BOOL fNull, UCHAR ucRtsControl,
1302 BOOL fAbortOnError, BYTE XonChar,
1303 BYTE XoffChar,BYTE ErrorChar)
1304{
1305 APIRET rc;
1306 ULONG ulLen;
1307 DCBINFO os2dcb;
1308 UCHAR fbTimeOut;
1309 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1310 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1311
1312 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1313 os2dcb.fbCtlHndShake = (ucDtrControl & 0x03) |
1314 (fOutxCtsFlow?0x08:0x00) |
1315 (fOutxDsrFlow?0x10:0x00) |
1316 // No DCD support in Win32 ?!
1317 (fDsrSensitivity?0x40:0x00);
1318 os2dcb.fbFlowReplace = (fOutX?0x01:0x00) |
1319 (fInX?0x02:0x00) |
1320 (fErrorChar?0x04:0x00)|
1321 (fNull?0x08:0x00)|
1322 (fTXContinueOnXoff?0x02:0x00)| // Not sure if thats the right flag to test
1323 (ucRtsControl<<6);
1324
1325 fbTimeOut = 0x02;
1326 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1327 {
1328 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1329 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1330 fbTimeOut = 0x05;
1331 else
1332 fbTimeOut = 0x04;
1333 }
1334 else
1335 {
1336 DWORD dwTimeout;
1337 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1338 if(dwTimeout)
1339 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1340 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1341 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1342 }
1343 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF9) | fbTimeOut;
1344 os2dcb.bErrorReplacementChar = ErrorChar;
1345 os2dcb.bXONChar = XonChar;
1346 os2dcb.bXOFFChar = XoffChar;
1347 ulLen = sizeof(DCBINFO);
1348 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1349 IOCTL_ASYNC,
1350 ASYNC_SETDCBINFO,
1351 &os2dcb,ulLen,&ulLen,
1352 NULL,0,NULL);
1353
1354 if(0==rc)
1355 {
1356 memcpy(&pDevData->dcbOS2,&os2dcb,sizeof(DCBINFO));
1357 pCurDCB->fOutxCtsFlow = fOutxCtsFlow;
1358 pCurDCB->fOutxDsrFlow = fOutxDsrFlow;
1359 pCurDCB->fDtrControl = ucDtrControl;
1360 pCurDCB->fDsrSensitivity = fDsrSensitivity;
1361 pCurDCB->fTXContinueOnXoff = fTXContinueOnXoff;
1362 pCurDCB->fOutX = fOutX;
1363 pCurDCB->fInX = fInX;
1364 pCurDCB->fErrorChar = fErrorChar;
1365 pCurDCB->fNull = fNull;
1366 pCurDCB->fRtsControl = ucRtsControl;
1367 pCurDCB->fAbortOnError = fAbortOnError;
1368 pCurDCB->XonChar = XonChar;
1369 pCurDCB->XoffChar = XoffChar;
1370 pCurDCB->ErrorChar = ErrorChar;
1371 }
1372
1373 return rc;
1374
1375}
1376//******************************************************************************
1377//******************************************************************************
1378APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData,
1379 DWORD dwNewBaud)
1380{
1381 APIRET rc;
1382 ULONG ulLen;
1383 EXTBAUDSET SetBaud;
1384 EXTBAUDGET GetBaud;
1385 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1386
1387 ulLen = sizeof(SetBaud);
1388 SetBaud.ulBaud = dwNewBaud;
1389 SetBaud.ucFrac = 0;
1390 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1391 IOCTL_ASYNC,
1392 ASYNC_EXTSETBAUDRATE,
1393 &SetBaud,ulLen,&ulLen,
1394 NULL,0,NULL);
1395 if(0==rc)
1396 {
1397 ulLen = sizeof(GetBaud);
1398 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1399 IOCTL_ASYNC,
1400 ASYNC_EXTGETBAUDRATE,
1401 NULL,0,NULL,
1402 &GetBaud,ulLen,&ulLen);
1403 if(0==rc)
1404 {
1405 if(dwNewBaud != GetBaud.ulCurrBaud) {
1406 dprintf(("!WARNING! dwNewBaud (%d) != GetBaud.ulCurrBaud (%d)", dwNewBaud, GetBaud.ulCurrBaud));
1407 rc = 1; // ToDo set a proper Errorhandling
1408 }
1409 else
1410 {
1411 pDevData->CommCfg.dcb.BaudRate = dwNewBaud;
1412 }
1413 }
1414 else {
1415 dprintf(("!WARNING! SetBaud: (get) OSLibDosDevIOCtl failed with rc %d", rc));
1416 }
1417 }
1418 else {
1419 dprintf(("!WARNING! SetBaud: (set) OSLibDosDevIOCtl failed with rc %d", rc));
1420 }
1421 return rc;
1422}
1423//******************************************************************************
1424//******************************************************************************
1425
1426
Note: See TracBrowser for help on using the repository browser.