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

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

com fixes

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