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

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

com fixes

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