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

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

preliminary changes for new overlapped io framework

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