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

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

overlapped io updates/fixes

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