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

Last change on this file since 7474 was 7474, checked in by phaller, 24 years ago

Fixes in HandleManager and Device Handlers

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