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

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

disk fix

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