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

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

overlappedio, com & lpt updates

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