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

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

updates

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