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

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

minor update

File size: 57.4 KB
Line 
1/* $Id: hmcomm.cpp,v 1.23 2001-12-01 19:26:40 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//testestestest
315 dprintf(("Bytes to write:"));
316 for(int i=0;i<nNumberOfBytesToWrite;i++) {
317 dprintf(("%x %c", ((char *)lpBuffer)[i], ((char *)lpBuffer)[i]));
318 }
319//testestestset
320
321 ret = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite,
322 &ulBytesWritten);
323
324 if(lpNumberOfBytesWritten) {
325 *lpNumberOfBytesWritten = (ret) ? ulBytesWritten : 0;
326 dprintf2(("KERNEL32:HMDeviceCommClass::WriteFile %d byte(s) written", *lpNumberOfBytesWritten));
327 }
328 if(ret == FALSE) {
329 dprintf(("!ERROR!: WriteFile failed with rc %d", GetLastError()));
330 }
331
332 return ret;
333}
334/*****************************************************************************
335 * Name : BOOL WriteFileEx
336 * Purpose : The WriteFileEx function writes data to a file. It is designed
337 * solely for asynchronous operation, unlike WriteFile, which is
338 * designed for both synchronous and asynchronous operation.
339 * WriteFileEx reports its completion status asynchronously,
340 * calling a specified completion routine when writing is completed
341 * and the calling thread is in an alertable wait state.
342 * Parameters: HANDLE hFile handle of file to write
343 * LPVOID lpBuffer address of buffer
344 * DWORD nNumberOfBytesToRead number of bytes to write
345 * LPOVERLAPPED lpOverlapped address of offset
346 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
347 * Variables :
348 * Result : TRUE / FALSE
349 * Remark :
350 * Status : UNTESTED STUB
351 *
352 * Author : SvL
353 *****************************************************************************/
354
355BOOL HMDeviceCommClass::WriteFileEx(PHMHANDLEDATA pHMHandleData,
356 LPVOID lpBuffer,
357 DWORD nNumberOfBytesToWrite,
358 LPOVERLAPPED lpOverlapped,
359 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
360{
361 dprintf(("!ERROR!: WriteFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
362 lpHMDeviceName,
363 pHMHandleData->hHMHandle,
364 lpBuffer,
365 nNumberOfBytesToWrite,
366 lpOverlapped,
367 lpCompletionRoutine));
368
369 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
370 dprintf(("!WARNING!: Handle not created with FILE_FLAG_OVERLAPPED!"));
371 ::SetLastError(ERROR_ACCESS_DENIED); //todo: right error?
372 return FALSE;
373 }
374
375 ::SetLastError(ERROR_INVALID_FUNCTION);
376 return FALSE;
377}
378/*****************************************************************************
379 * Name : BOOL HMDeviceCommClass::ReadFile
380 * Purpose : read data from handle / device
381 * Parameters: PHMHANDLEDATA pHMHandleData,
382 * LPCVOID lpBuffer,
383 * DWORD nNumberOfBytesToRead,
384 * LPDWORD lpNumberOfBytesRead,
385 * LPOVERLAPPED lpOverlapped
386 * Variables :
387 * Result : Boolean
388 * Remark :
389 * Status :
390 *
391 * Author : SvL
392 *****************************************************************************/
393
394BOOL HMDeviceCommClass::ReadFile(PHMHANDLEDATA pHMHandleData,
395 LPCVOID lpBuffer,
396 DWORD nNumberOfBytesToRead,
397 LPDWORD lpNumberOfBytesRead,
398 LPOVERLAPPED lpOverlapped)
399{
400 dprintf(("KERNEL32:HMDeviceCommClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
401 lpHMDeviceName,
402 pHMHandleData->hHMHandle,
403 lpBuffer,
404 nNumberOfBytesToRead,
405 lpNumberOfBytesRead,
406 lpOverlapped));
407
408 BOOL ret;
409 ULONG ulBytesRead;
410
411 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
412 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
413 ::SetLastError(ERROR_INVALID_PARAMETER);
414 return FALSE;
415 }
416 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
417 dprintf(("!WARNING!: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
418 }
419
420 RXQUEUE qInfo;
421 ULONG ulLen = sizeof(qInfo);
422 ULONG rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
423 IOCTL_ASYNC,
424 ASYNC_GETINQUECOUNT,
425 0,0,0,
426 &qInfo,ulLen,&ulLen);
427 dprintf(("ASYNC_GETINQUECOUNT -> qInfo.cch %d (queue size %d) rc %d", qInfo.cch, qInfo.cb, rc));
428
429 ret = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
430 &ulBytesRead);
431
432 if(lpNumberOfBytesRead) {
433 *lpNumberOfBytesRead = (ret) ? ulBytesRead : 0;
434 dprintf2(("KERNEL32:HMDeviceCommClass::ReadFile %d bytes read", *lpNumberOfBytesRead));
435 }
436 if(ret == FALSE) {
437 dprintf(("!ERROR!: ReadFile failed with rc %d", GetLastError()));
438 }
439 else {
440//testestestest
441 dprintf(("Bytes read:"));
442 for(int i=0;i<ulBytesRead;i++) {
443 dprintf(("%x %c", ((char *)lpBuffer)[i], ((char *)lpBuffer)[i]));
444 }
445//testestestset
446 }
447 return ret;
448}
449
450/*****************************************************************************
451 * Name : BOOL ReadFileEx
452 * Purpose : The ReadFileEx function reads data from a file asynchronously.
453 * It is designed solely for asynchronous operation, unlike the
454 * ReadFile function, which is designed for both synchronous and
455 * asynchronous operation. ReadFileEx lets an application perform
456 * other processing during a file read operation.
457 * The ReadFileEx function reports its completion status asynchronously,
458 * calling a specified completion routine when reading is completed
459 * and the calling thread is in an alertable wait state.
460 * Parameters: HANDLE hFile handle of file to read
461 * LPVOID lpBuffer address of buffer
462 * DWORD nNumberOfBytesToRead number of bytes to read
463 * LPOVERLAPPED lpOverlapped address of offset
464 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
465 * Variables :
466 * Result : TRUE / FALSE
467 * Remark :
468 * Status : UNTESTED STUB
469 *
470 * Author : SvL
471 *****************************************************************************/
472BOOL HMDeviceCommClass::ReadFileEx(PHMHANDLEDATA pHMHandleData,
473 LPVOID lpBuffer,
474 DWORD nNumberOfBytesToRead,
475 LPOVERLAPPED lpOverlapped,
476 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
477{
478 dprintf(("!ERROR!: ReadFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
479 lpHMDeviceName,
480 pHMHandleData->hHMHandle,
481 lpBuffer,
482 nNumberOfBytesToRead,
483 lpOverlapped,
484 lpCompletionRoutine));
485
486 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
487 dprintf(("!WARNING!: Handle not created with FILE_FLAG_OVERLAPPED!"));
488 ::SetLastError(ERROR_ACCESS_DENIED); //todo: right error?
489 return FALSE;
490 }
491
492 ::SetLastError(ERROR_INVALID_FUNCTION);
493 return FALSE;
494}
495/*****************************************************************************
496 * Name : DWORD HMDeviceHandler::SetupComm
497 * Purpose : set com port parameters (queue)
498 * Variables :
499 * Result :
500 * Remark :
501 * Status :
502 *
503 * Author : Achim Hasenmueller
504 *****************************************************************************/
505
506BOOL HMDeviceCommClass::SetupComm( PHMHANDLEDATA pHMHandleData,
507 DWORD dwInQueue,
508 DWORD dwOutQueue)
509{
510 dprintf(("HMDeviceCommClass::SetupComm "));
511 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
512 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
513 {
514 ::SetLastError(ERROR_INVALID_HANDLE);
515 return FALSE;
516 }
517 pDevData->dwInBuffer = dwInQueue;
518 pDevData->dwOutBuffer = dwOutQueue;
519
520 return(TRUE);
521}
522//******************************************************************************
523#define TIMEOUT_COMM 50
524//******************************************************************************
525DWORD CALLBACK SerialCommThread(LPVOID lpThreadParam)
526{
527 HANDLE hComm = (HANDLE)lpThreadParam;
528 PHMHANDLEDATA pHMHandleData;
529 PHMDEVCOMDATA pDevData;
530 DWORD ret;
531 APIRET rc;
532 ULONG ulLen;
533 USHORT COMEvt;
534 DWORD dwEvent,dwMask;
535
536 pHMHandleData = HMQueryHandleData(hComm);
537 if(!pHMHandleData) {
538 dprintf(("!ERROR!: Invalid handle -> aborting"));
539 return 0;
540 }
541
542 pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
543 if(!pDevData) {
544 dprintf(("!ERROR! SerialCommThread !pDevData"));
545 DebugInt3();
546 return 0;
547 }
548 HANDLE hEvent = pDevData->hEventSem;
549 HANDLE hCommOS2 = pHMHandleData->hHMHandle;
550 if(!hCommOS2 || !hEvent) {
551 dprintf(("!ERROR! SerialCommThread !hCommOS2 || !hEvent"));
552 DebugInt3();
553 return 0;
554 }
555 dprintf(("SerialCommThread %x entered", hComm));
556
557 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
558 while(TRUE)
559 {
560 //validate handle
561 pHMHandleData = HMQueryHandleData(hComm);
562 if(!pHMHandleData) {
563 dprintf(("!ERROR!: Invalid handle -> aborting"));
564 return 0;
565 }
566 if(pDevData->fClosing) {
567 dprintf(("Cleaning up async comm thread"));
568 SetEvent(hEvent); //signal to CloseHandle that we're done
569 return 0;
570 }
571
572 //Wait for the app to call WaitCommEvent
573 dprintf(("SerialCommThread: wait for WaitCommEvent"));
574 ret = WaitForSingleObject(hEvent, INFINITE);
575 ResetEvent(hEvent);
576 dprintf(("SerialCommThread: wait for WaitCommEvent done %x", ret));
577
578 //validate handle first
579 pHMHandleData = HMQueryHandleData(hComm);
580 if(!pHMHandleData) {
581 dprintf(("!ERROR!: Invalid handle -> aborting"));
582 return 0;
583 }
584
585 if(pDevData->fClosing) {
586 dprintf(("Cleaning up async comm thread"));
587 SetEvent(hEvent); //signal to CloseHandle that we're done
588 return 0;
589 }
590
591 HANDLE hOverlappedEvent = pDevData->overlapped.hEvent;
592 if(!hOverlappedEvent) {
593 DebugInt3();
594 return 0;
595 }
596
597 ulLen = sizeof(CHAR);
598 dwEvent = 0;
599 rc = 0;
600 ulLen = sizeof(COMEvt);
601 dwMask = pDevData->dwEventMask;
602
603 while( (0==rc) &&
604 !(dwEvent & dwMask) &&
605 (dwMask == pDevData->dwEventMask) &&
606 !(pDevData->fCancelIo) && !(pDevData->fClosing) ) // Exit if the Mask gets changed
607 {
608 rc = OSLibDosDevIOCtl(hCommOS2,
609 IOCTL_ASYNC,
610 ASYNC_GETCOMMEVENT,
611 0,0,0,
612 &COMEvt,ulLen,&ulLen);
613 if(!rc)
614 {
615 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
616 //dwEvent |= (COMEvt&0x0002)? 0:0;
617 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
618 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
619 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
620 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD?
621 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
622 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
623 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
624 if((dwEvent & dwMask)) break;
625 }
626 else break;
627
628 //validate handle first
629 pHMHandleData = HMQueryHandleData(hComm);
630 if(!pHMHandleData) {
631 dprintf(("!ERROR!: Invalid handle -> aborting"));
632 return 0;
633 }
634
635 if(pDevData->fClosing) {
636 dprintf(("Cleaning up async comm thread"));
637 SetEvent(hEvent); //signal to CloseHandle that we're done
638 return 0;
639 }
640
641 DosSleep(TIMEOUT_COMM);
642 }
643 if(pDevData->fClosing) {
644 dprintf(("Cleaning up async comm thread"));
645 SetEvent(hEvent); //signal to CloseHandle that we're done
646 return 0;
647 }
648 else
649 if(pDevData->fCancelIo) {
650 pDevData->overlapped.Internal = 0;
651 pDevData->dwLastError = ERROR_OPERATION_ABORTED;
652 if(pDevData->lpfdwEvtMask) *pDevData->lpfdwEvtMask = 0;
653 dprintf(("Overlapped: WaitCommEvent ERROR_OPERATION_ABORTED"));
654
655 //signal to app that a comm event has occurred
656 SetEvent(hOverlappedEvent);
657 }
658 else
659 if((dwEvent & dwMask) && (dwMask == pDevData->dwEventMask)) {
660 pDevData->overlapped.Internal |= (rc==0) ? (dwEvent & dwMask) : 0;
661 pDevData->dwLastError = rc;
662
663 //We're also supposed to write the result to the address supplied
664 //by the call to WaitCommEvent
665 if(pDevData->lpfdwEvtMask) *pDevData->lpfdwEvtMask = (rc==0) ? (dwEvent & dwMask) : 0;
666 dprintf(("Overlapped: WaitCommEvent returned %x", pDevData->overlapped.Internal));
667
668 //signal to app that a comm event has occurred
669 SetEvent(hOverlappedEvent);
670 }
671 }
672 return 0;
673}
674//******************************************************************************
675//******************************************************************************
676BOOL HMDeviceCommClass::WaitCommEvent( PHMHANDLEDATA pHMHandleData,
677 LPDWORD lpfdwEvtMask,
678 LPOVERLAPPED lpo)
679{
680 APIRET rc;
681 ULONG ulLen;
682 USHORT COMEvt;
683 DWORD dwEvent,dwMask;
684
685 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
686
687 dprintf(("HMDeviceCommClass::WaitCommEvent %x %x %x", pHMHandleData->hHMHandle, lpfdwEvtMask, lpo));
688
689 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo) {
690 dprintf(("!WARNING! pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpo"));
691 ::SetLastError(ERROR_INVALID_PARAMETER);
692 return FALSE;
693 }
694
695 ulLen = sizeof(CHAR);
696
697 dwEvent = 0;
698 rc = 0;
699 ulLen = sizeof(COMEvt);
700 dwMask = pDevData->dwEventMask;
701 while( (0==rc) &&
702 !(dwEvent & dwMask) &&
703 (dwMask ==pDevData->dwEventMask) ) // Exit if the Mask gets changed
704 {
705 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
706 IOCTL_ASYNC,
707 ASYNC_GETCOMMEVENT,
708 0,0,0,
709 &COMEvt,ulLen,&ulLen);
710 if(!rc)
711 {
712 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
713 //dwEvent |= (COMEvt&0x0002)? 0:0;
714 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
715 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
716 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
717 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD?
718 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
719 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
720 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
721 if((dwEvent & dwMask)) break;
722 }
723 else break;
724
725 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)
726 {
727 memcpy(&pDevData->overlapped, lpo, sizeof(pDevData->overlapped));
728 pDevData->overlapped.Internal = 0;
729 pDevData->overlapped.InternalHigh = 0;
730 pDevData->overlapped.Offset = 0;
731 pDevData->overlapped.OffsetHigh = 0;
732 //We're also supposed to write the result to the address supplied
733 //by this call
734 pDevData->lpfdwEvtMask = lpfdwEvtMask;
735 //Set app event semaphore to non-signalled state
736 ::ResetEvent(lpo->hEvent);
737
738 //signal async comm thread to start polling comm status
739 ::SetEvent(pDevData->hEventSem);
740 ::SetLastError(ERROR_IO_PENDING);
741 return FALSE;
742 }
743 DosSleep(TIMEOUT_COMM);
744 }
745 if(dwMask == pDevData->dwEventMask) {
746 *lpfdwEvtMask = (rc==0) ? (dwEvent & dwMask) : 0;
747 dprintf(("WaitCommEvent returned %x", *lpfdwEvtMask));
748 }
749 else *lpfdwEvtMask = 0;
750
751 ::SetLastError(rc);
752 return (rc==0);
753}
754/*****************************************************************************
755 * Name : DWORD HMDeviceCommClass::CancelIo
756 * Purpose : cancel pending IO operation
757 * Variables :
758 * Result :
759 * Remark :
760 * Status :
761 *
762 * Author : SvL
763 *****************************************************************************/
764BOOL HMDeviceCommClass::CancelIo(PHMHANDLEDATA pHMHandleData)
765{
766 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
767
768 dprintf(("HMDeviceCommClass::CancelIo"));
769 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
770 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
771 return FALSE;
772 }
773
774 //signal serial thread to cancel pending IO operation
775 pDevData->fCancelIo = TRUE;
776 ::SetEvent(pDevData->hEventSem);
777
778 ::SetLastError(ERROR_SUCCESS);
779 return(TRUE);
780}
781/*****************************************************************************
782 * Name : DWORD HMDeviceFileClass::GetOverlappedResult
783 * Purpose : asynchronus I/O
784 * Parameters: PHMHANDLEDATA pHMHandleData
785 * LPOVERLAPPED arg2
786 * LPDWORD arg3
787 * BOOL arg4
788 * Variables :
789 * Result : API returncode
790 * Remark :
791 * Status :
792 *
793 * Author : SvL
794 *****************************************************************************/
795BOOL HMDeviceCommClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData,
796 LPOVERLAPPED lpoOverlapped,
797 LPDWORD lpcbTransfer,
798 BOOL fWait)
799{
800 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
801
802 dprintf(("KERNEL32-WARNING: HMDeviceCommClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh) partly implemented",
803 pHMHandleData->hHMHandle,
804 lpoOverlapped,
805 lpcbTransfer,
806 fWait));
807
808 if(pDevData == NULL || !(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED)) {
809 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
810 return FALSE;
811 }
812 if(!lpoOverlapped) {
813 ::SetLastError(ERROR_INVALID_PARAMETER);
814 return FALSE;
815 }
816 if(lpoOverlapped->hEvent != pDevData->overlapped.hEvent) {
817 dprintf(("!WARNING!: GetOverlappedResult called for unknown operation"));
818 ::SetLastError(ERROR_ACCESS_DENIED); //todo: wrong error?
819 return FALSE;
820 }
821 if(pDevData->overlapped.Internal) {
822 lpoOverlapped->Internal = pDevData->overlapped.Internal;
823 pDevData->overlapped.Internal = 0; //not entirely safe
824 pDevData->dwLastError = 0;
825 ::SetLastError(pDevData->dwLastError);
826 return lpoOverlapped->Internal;
827 }
828 if(fWait) {
829 ::WaitForSingleObject(pDevData->overlapped.hEvent, INFINITE);
830 ::ResetEvent(pDevData->overlapped.hEvent);
831 lpoOverlapped->Internal = pDevData->overlapped.Internal;
832 pDevData->overlapped.Internal = 0; //not entirely safe
833 ::SetLastError(ERROR_SUCCESS);
834 return lpoOverlapped->Internal;
835 }
836 else {
837 ::SetLastError(ERROR_IO_PENDING);
838 return FALSE;
839 }
840}
841//******************************************************************************
842//******************************************************************************
843BOOL HMDeviceCommClass::GetCommProperties( PHMHANDLEDATA pHMHandleData,
844 LPCOMMPROP lpcmmp)
845{
846 EXTBAUDGET BaudInfo;
847 APIRET rc;
848 ULONG ulLen;
849 USHORT COMErr;
850 int i;
851 dprintf(("HMDeviceCommClass::GetCommProperties"));
852
853 ulLen = sizeof(EXTBAUDGET);
854 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
855 IOCTL_ASYNC,
856 ASYNC_EXTGETBAUDRATE,
857 0,0,0,
858 &BaudInfo,ulLen,&ulLen);
859 memset(lpcmmp,0,sizeof(COMMPROP));
860 lpcmmp->wPacketLength = sizeof(COMMPROP);
861 lpcmmp->wPacketVersion = 1; //???
862 lpcmmp->dwServiceMask = SP_SERIALCOMM;
863 for(i=0;i<BaudTableSize && BaudInfo.ulMaxBaud <= BaudTable[i].dwBaudRate;i++);
864 lpcmmp->dwMaxBaud = BaudTable[i].dwBaudFlag;
865 lpcmmp->dwProvSubType = PST_RS232;
866 lpcmmp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK |
867 PCF_RTSCTS | PCF_SETXCHAR |
868 PCF_XONXOFF;
869 lpcmmp->dwSettableParams = SP_BAUD | SP_DATABITS |
870 SP_HANDSHAKEING | SP_PARITY |
871 SP_PARITY_CHECK | SP_STOPBIT;
872 lpcmmp->dwSettableBaud = 0;
873 for(i=0;i<BaudTableSize;i++)
874 {
875 if ( (BaudTable[i].dwBaudRate>=BaudInfo.ulMinBaud) &&
876 (BaudTable[i].dwBaudRate<=BaudInfo.ulMaxBaud) )
877 lpcmmp->dwSettableBaud |= BaudTable[i].dwBaudFlag;
878 }
879 lpcmmp->dwSettableBaud |= BAUD_USER;
880 lpcmmp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
881 lpcmmp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
882 PARITY_NONE | PARITY_ODD | PARITY_EVEN |
883 PARITY_MARK | PARITY_SPACE;
884 return(rc==0);
885}
886//******************************************************************************
887//******************************************************************************
888BOOL HMDeviceCommClass::GetCommMask( PHMHANDLEDATA pHMHandleData,
889 LPDWORD lpfdwEvtMask)
890{
891 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
892
893 dprintf(("HMDeviceCommClass::GetCommMask"));
894
895 *lpfdwEvtMask = pDevData->dwEventMask;
896 return(TRUE);
897}
898//******************************************************************************
899//******************************************************************************
900BOOL HMDeviceCommClass::SetCommMask( PHMHANDLEDATA pHMHandleData,
901 DWORD fdwEvtMask)
902{
903 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
904 dprintf(("HMDeviceCommClass::SetCommMask %x", fdwEvtMask));
905
906 if(fdwEvtMask & (EV_RLSD|EV_RXFLAG)) {
907 dprintf(("!WARNING! SetCommMask: unsupported flags EV_RLSD and/or EV_RXFLAG!!"));
908 }
909
910 pDevData->dwEventMask = fdwEvtMask & ~(EV_RLSD|EV_RXFLAG); // Clear the 2 not supported Flags.
911 return(TRUE);
912}
913//******************************************************************************
914//******************************************************************************
915BOOL HMDeviceCommClass::PurgeComm( PHMHANDLEDATA pHMHandleData,
916 DWORD fdwAction)
917{
918 ULONG ulParLen, ulDataLen, rc = ERROR_SUCCESS;
919 BYTE par = 0;
920 WORD data = 0;
921
922 dprintf(("HMDeviceCommClass::PurgeComm (flags 0x%x) partly implemented",fdwAction));
923 // ToDo: find a way to stop the current transmision didn't find
924 // any clue how to in Control Program Guide and reference
925
926 ulParLen = sizeof(par);
927 ulDataLen = sizeof(data);
928 if(fdwAction & PURGE_TXCLEAR) {
929 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
930 IOCTL_GENERAL,
931 DEV_FLUSHOUTPUT,
932 &par,ulParLen,&ulParLen,
933 &data,ulDataLen,&ulDataLen);
934 }
935 if(fdwAction & PURGE_RXCLEAR) {
936 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
937 IOCTL_GENERAL,
938 DEV_FLUSHINPUT,
939 &par,ulParLen,&ulParLen,
940 &data,ulDataLen,&ulDataLen);
941 }
942 if(rc) {
943 dprintf(("!WARNING! OSLibDosDevIOCtl failed with rc %d", rc));
944 }
945 return (rc == ERROR_SUCCESS);
946}
947//******************************************************************************
948//******************************************************************************
949BOOL HMDeviceCommClass::ClearCommError( PHMHANDLEDATA pHMHandleData,
950 LPDWORD lpdwErrors,
951 LPCOMSTAT lpcst)
952{
953 APIRET rc;
954 ULONG ulLen;
955 USHORT COMErr;
956
957 dprintf(("HMDeviceCommClass::ClearCommError"));
958 ulLen = sizeof(USHORT);
959
960 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
961 IOCTL_ASYNC,
962 ASYNC_GETCOMMERROR,
963 0,0,0,
964 &COMErr,2,&ulLen);
965 *lpdwErrors = 0;
966 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
967 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
968 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
969 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
970
971 if(lpcst)
972 {
973 UCHAR ucStatus;
974 RXQUEUE qInfo;
975 ulLen = 1;
976 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
977 IOCTL_ASYNC,
978 ASYNC_GETCOMMSTATUS,
979 0,0,0,
980 &ucStatus,ulLen,&ulLen);
981 if(!rc)
982 {
983 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
984 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
985 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
986 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
987 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
988 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
989 lpcst->fTxim = ((ucStatus & 0x40)>0);
990
991 ulLen = sizeof(qInfo);
992 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
993 IOCTL_ASYNC,
994 ASYNC_GETINQUECOUNT,
995 0,0,0,
996 &qInfo,ulLen,&ulLen);
997 if(!rc)
998 {
999 lpcst->cbInQue = qInfo.cch;
1000 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1001 IOCTL_ASYNC,
1002 ASYNC_GETOUTQUECOUNT,
1003 0,0,0,
1004 &qInfo,ulLen,&ulLen);
1005 if(!rc)
1006 lpcst->cbOutQue = qInfo.cch;
1007 }
1008 }
1009 }
1010
1011 return(rc==0);
1012}
1013//******************************************************************************
1014//******************************************************************************
1015BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData,
1016 LPDCB lpDCB)
1017{
1018 APIRET rc;
1019 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1020 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1021 dprintf(("HMDeviceCommClass::SetCommState"));
1022
1023 rc = 0;
1024 if(pCurDCB->BaudRate != lpDCB->BaudRate) {
1025 dprintf(("SetCommState: change baud rate from %d to %d", pCurDCB->BaudRate, lpDCB->BaudRate));
1026 rc = SetBaud( pHMHandleData,
1027 lpDCB->BaudRate);
1028 }
1029
1030 if(!rc)
1031 {
1032 if( (pCurDCB->ByteSize != lpDCB->ByteSize) ||
1033 (pCurDCB->Parity != lpDCB->Parity) ||
1034 (pCurDCB->StopBits != lpDCB->StopBits))
1035 {
1036 dprintf(("SetCommState: change line %d %d %d", lpDCB->ByteSize, lpDCB->Parity, lpDCB->StopBits));
1037 rc = SetLine( pHMHandleData,
1038 lpDCB->ByteSize,
1039 lpDCB->Parity,
1040 lpDCB->StopBits);
1041 }
1042 }
1043
1044 if(!rc)
1045 {
1046 if( (pCurDCB->fOutxCtsFlow != lpDCB->fOutxCtsFlow) ||
1047 (pCurDCB->fOutxDsrFlow != lpDCB->fOutxDsrFlow) ||
1048 (pCurDCB->fDtrControl != lpDCB->fDtrControl) ||
1049 (pCurDCB->fDsrSensitivity != lpDCB->fDsrSensitivity) ||
1050 (pCurDCB->fTXContinueOnXoff != lpDCB->fTXContinueOnXoff) ||
1051 (pCurDCB->fOutX != lpDCB->fOutX) ||
1052 (pCurDCB->fInX != lpDCB->fInX) ||
1053 (pCurDCB->fErrorChar != lpDCB->fErrorChar) ||
1054 (pCurDCB->fNull != lpDCB->fNull) ||
1055 (pCurDCB->fRtsControl != lpDCB->fRtsControl) ||
1056 (pCurDCB->fAbortOnError != lpDCB->fAbortOnError) ||
1057 (pCurDCB->XonChar != lpDCB->XonChar) ||
1058 (pCurDCB->XoffChar != lpDCB->XoffChar) ||
1059 (pCurDCB->ErrorChar != lpDCB->ErrorChar))
1060 {
1061 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));
1062 SetOS2DCB( pHMHandleData,
1063 lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,
1064 lpDCB->fDtrControl, lpDCB->fDsrSensitivity,
1065 lpDCB->fTXContinueOnXoff, lpDCB->fOutX,
1066 lpDCB->fInX, lpDCB->fErrorChar,
1067 lpDCB->fNull, lpDCB->fRtsControl,
1068 lpDCB->fAbortOnError, lpDCB->XonChar,
1069 lpDCB->XoffChar,lpDCB->ErrorChar);
1070 }
1071 }
1072
1073 return(rc==0);
1074}
1075//******************************************************************************
1076//******************************************************************************
1077BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData,
1078 LPDCB lpdcb)
1079{
1080 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1081
1082 dprintf(("HMDeviceCommClass::GetCommState %x", lpdcb));
1083
1084 if(lpdcb == NULL) {
1085 ::SetLastError(ERROR_INVALID_PARAMETER);
1086 return FALSE;
1087 }
1088
1089 memcpy(lpdcb,&pDevData->CommCfg.dcb,sizeof(DCB));
1090 return(TRUE);
1091}
1092//******************************************************************************
1093//******************************************************************************
1094BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData,
1095 LPDWORD lpModemStat )
1096{
1097 APIRET rc;
1098 ULONG ulLen;
1099 USHORT COMErr;
1100 UCHAR ucStatus;
1101
1102 dprintf(("HMDeviceCommClass::GetCommModemStatus %x", lpModemStat));
1103 if(lpModemStat == NULL) {
1104 ::SetLastError(ERROR_INVALID_PARAMETER);
1105 return FALSE;
1106 }
1107
1108 ulLen = sizeof(CHAR);
1109
1110 ulLen = 1;
1111 *lpModemStat = 0;
1112
1113 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1114 IOCTL_ASYNC,
1115 ASYNC_GETMODEMINPUT,
1116 0,0,0,
1117 &ucStatus,ulLen,&ulLen);
1118 if(!rc)
1119 {
1120 *lpModemStat |= (ucStatus & 0x10)? MS_CTS_ON:0;
1121 *lpModemStat |= (ucStatus & 0x20)? MS_DSR_ON:0;
1122 *lpModemStat |= (ucStatus & 0x40)? MS_RING_ON:0;
1123 //*lpModemStat |= (ucStatus & 0x80)? MS_RSLD_ON:0;
1124 }
1125
1126 dprintf2(("HMDeviceCommClass::GetCommModemStatus -> %x rc=%d", *lpModemStat, rc));
1127 return(rc==0);
1128}
1129//******************************************************************************
1130//******************************************************************************
1131BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1132 LPCOMMTIMEOUTS lpctmo)
1133{
1134 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1135
1136 dprintf(("HMDeviceCommClass::GetCommTimeouts %x stub", lpctmo));
1137
1138 if(lpctmo == NULL) {
1139 ::SetLastError(ERROR_INVALID_PARAMETER);
1140 return FALSE;
1141 }
1142
1143 memcpy( lpctmo,
1144 &pDevData->CommTOuts,
1145 sizeof(COMMTIMEOUTS));
1146 return(TRUE);
1147}
1148//******************************************************************************
1149//******************************************************************************
1150BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData,
1151 LPCOMMTIMEOUTS lpctmo)
1152{
1153 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1154 DCBINFO os2dcb;
1155 ULONG ulLen;
1156 APIRET rc;
1157 UCHAR fbTimeOut;
1158
1159 if(lpctmo == NULL) {
1160 dprintf(("!WARNING! HMDeviceCommClass::SetCommTimeouts %x -> invalid parameter", lpctmo));
1161 ::SetLastError(ERROR_INVALID_PARAMETER);
1162 return FALSE;
1163 }
1164
1165 dprintf(("HMDeviceCommClass::SetCommTimeouts\n"
1166 " ReadIntervalTimeout : 0x%x\n"
1167 " ReadTotalTimeoutMultiplier : %d\n"
1168 " ReadTotalTimeoutConstant : %d\n"
1169 " WriteTotalTimeoutMultiplier : %d\n"
1170 " WriteTotalTimeoutConstant : %d\n",
1171 lpctmo->ReadIntervalTimeout,
1172 lpctmo->ReadTotalTimeoutMultiplier,
1173 lpctmo->ReadTotalTimeoutConstant,
1174 lpctmo->WriteTotalTimeoutMultiplier,
1175 lpctmo->WriteTotalTimeoutConstant
1176 ));
1177
1178 memcpy( &pDevData->CommTOuts,
1179 lpctmo,
1180 sizeof(COMMTIMEOUTS));
1181
1182 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1183
1184 fbTimeOut = 0x02;
1185 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1186 {
1187 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1188 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1189 fbTimeOut = 0x05;
1190 else
1191 fbTimeOut = 0x04;
1192 }
1193 else
1194 {
1195 DWORD dwTimeout;
1196 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1197#if 0
1198 if(dwTimeout)
1199 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1200#endif
1201 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1202 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1203 }
1204 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF9) | fbTimeOut;
1205
1206 dprintf((" New DCB:\n"
1207 " WriteTimeout : %d\n"
1208 " ReadTimeout : %d\n"
1209 " CtlHandshake : 0x%x\n"
1210 " FlowReplace : 0x%x\n"
1211 " Timeout : 0x%x\n"
1212 " Error replacement Char : 0x%x\n"
1213 " Break replacement Char : 0x%x\n"
1214 " XON Char : 0x%x\n"
1215 " XOFF Char : 0x%x\n",
1216 os2dcb.usWriteTimeout,
1217 os2dcb.usReadTimeout,
1218 os2dcb.fbCtlHndShake,
1219 os2dcb.fbFlowReplace,
1220 os2dcb.fbTimeOut,
1221 os2dcb.bErrorReplacementChar,
1222 os2dcb.bBreakReplacementChar,
1223 os2dcb.bXONChar,
1224 os2dcb.bXOFFChar));
1225
1226 ulLen = sizeof(DCBINFO);
1227 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1228 IOCTL_ASYNC,
1229 ASYNC_SETDCBINFO,
1230 &os2dcb,ulLen,&ulLen,
1231 NULL,0,NULL);
1232 dprintf(("IOCRL returned %d",rc));
1233 return(0==rc);
1234}
1235//******************************************************************************
1236//******************************************************************************
1237BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData,
1238 CHAR cChar )
1239{
1240 APIRET rc;
1241 ULONG ulLen;
1242 USHORT COMErr;
1243
1244 dprintf(("HMDeviceCommClass::TransmitCommChar"));
1245 ulLen = sizeof(CHAR);
1246
1247 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1248 IOCTL_ASYNC,
1249 ASYNC_TRANSMITIMM,
1250 &cChar,ulLen,&ulLen,
1251 NULL,0,NULL);
1252
1253 return(rc==0);
1254}
1255//******************************************************************************
1256//******************************************************************************
1257BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData )
1258{
1259 APIRET rc;
1260 ULONG ulLen;
1261 USHORT COMErr;
1262
1263 dprintf(("HMDeviceCommClass::SetCommBreak"));
1264 ulLen = sizeof(USHORT);
1265
1266 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1267 IOCTL_ASYNC,
1268 ASYNC_SETBREAKON,
1269 0,0,0,
1270 &COMErr,2,&ulLen);
1271
1272 return(rc==0);
1273}
1274//******************************************************************************
1275//******************************************************************************
1276BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData)
1277{
1278 APIRET rc;
1279 ULONG ulLen;
1280 USHORT COMErr;
1281
1282 dprintf(("HMDeviceCommClass::ClearCommBreak"));
1283 ulLen = sizeof(USHORT);
1284
1285 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1286 IOCTL_ASYNC,
1287 ASYNC_SETBREAKOFF,
1288 0,0,0,
1289 &COMErr,2,&ulLen);
1290
1291 return(rc==0);
1292}
1293//******************************************************************************
1294//******************************************************************************
1295BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
1296 LPCOMMCONFIG lpCC,
1297 DWORD dwSize )
1298{
1299 dprintf(("HMDeviceCommClass::SetCommConfig NOT IMPLEMENTED"));
1300
1301 return(TRUE);
1302}
1303//******************************************************************************
1304//******************************************************************************
1305BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
1306 LPCOMMCONFIG lpCC,
1307 LPDWORD lpdwSize )
1308{
1309 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1310
1311 dprintf(("HMDeviceCommClass::GetCommConfig"));
1312
1313 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1314 *lpdwSize< sizeof(COMMCONFIG) )
1315 {
1316 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1317 *lpdwSize= sizeof(COMMCONFIG);
1318 return FALSE;
1319 }
1320
1321 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1322 {
1323 ::SetLastError(ERROR_INVALID_HANDLE);
1324 return FALSE;
1325 }
1326
1327 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1328 *lpdwSize = sizeof(COMMCONFIG);
1329 return(TRUE);
1330}
1331//******************************************************************************
1332//******************************************************************************
1333BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData,
1334 UINT dwFunc )
1335{
1336 APIRET rc;
1337 ULONG ulDLen,ulPLen;
1338 USHORT COMErr;
1339 MODEMSTATUS mdm;
1340
1341 dprintf(("HMDeviceCommClass::EscapeCommFunction %x", dwFunc));
1342
1343 ulDLen = sizeof(USHORT);
1344 ulPLen = sizeof(MODEMSTATUS);
1345 switch(dwFunc)
1346 {
1347 case CLRDTR:
1348 mdm.fbModemOn = 0x00;
1349 mdm.fbModemOff = 0XFE;
1350 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1351 IOCTL_ASYNC,
1352 ASYNC_SETMODEMCTRL,
1353 &mdm,ulPLen,&ulPLen,
1354 &COMErr,ulDLen,&ulDLen);
1355 dprintf(("CLRDTR rc = %d Comerror = 0x%x",rc,COMErr));
1356 rc = COMErr;
1357 if(rc==0)
1358 {
1359 BYTE bModem;
1360 ulDLen = sizeof(BYTE);
1361 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1362 IOCTL_ASYNC,
1363 ASYNC_GETMODEMOUTPUT,
1364 NULL,0,NULL,
1365 &bModem,ulDLen,&ulDLen);
1366 dprintf(("Check DTR rc = %d Flags = 0x%x",rc,bModem));
1367 rc = bModem & 0x01;
1368 }
1369 break;
1370 case CLRRTS:
1371 mdm.fbModemOn = 0x00;
1372 mdm.fbModemOff = 0XFD;
1373 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1374 IOCTL_ASYNC,
1375 ASYNC_SETMODEMCTRL,
1376 &mdm,ulPLen,&ulPLen,
1377 &COMErr,ulDLen,&ulDLen);
1378 dprintf(("CLRRTS: rc = %d, Comm error %x", rc, COMErr));
1379 break;
1380 case SETDTR:
1381 mdm.fbModemOn = 0x01;
1382 mdm.fbModemOff = 0XFF;
1383 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1384 IOCTL_ASYNC,
1385 ASYNC_SETMODEMCTRL,
1386 &mdm,ulPLen,&ulPLen,
1387 &COMErr,ulDLen,&ulDLen);
1388 dprintf(("SETDTR: rc = %d, Comm error %x", rc, COMErr));
1389 break;
1390 case SETRTS:
1391 mdm.fbModemOn = 0x02;
1392 mdm.fbModemOff = 0XFF;
1393 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1394 IOCTL_ASYNC,
1395 ASYNC_SETMODEMCTRL,
1396 &mdm,ulPLen,&ulPLen,
1397 &COMErr,ulDLen,&ulDLen);
1398 dprintf(("SETRTS: rc = %d, Comm error %x", rc, COMErr));
1399 break;
1400 case SETXOFF:
1401 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1402 IOCTL_ASYNC,
1403 ASYNC_STOPTRANSMIT,
1404 0,0,0,
1405 0,0,0);
1406 dprintf(("SETXOFF: rc = %d", rc));
1407 break;
1408 case SETXON:
1409 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1410 IOCTL_ASYNC,
1411 ASYNC_STARTTRANSMIT,
1412 0,0,0,
1413 0,0,0);
1414 dprintf(("SETXON: rc = %d", rc));
1415 break;
1416 default:
1417 dprintf(("!ERROR!: EscapeCommFunction: unknown function"));
1418 ::SetLastError(ERROR_INVALID_PARAMETER);
1419 return(FALSE);
1420 }
1421
1422 return(rc==0);
1423}
1424//******************************************************************************
1425//******************************************************************************
1426BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1427 LPCOMMCONFIG lpCC,
1428 DWORD dwSize)
1429{
1430 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1431 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1432 {
1433 ::SetLastError(ERROR_INVALID_HANDLE);
1434 return FALSE;
1435 }
1436
1437 dprintf(("SetDefaultCommConfig %x %d", lpCC, dwSize));
1438 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
1439 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
1440
1441 return(TRUE);
1442}
1443//******************************************************************************
1444//******************************************************************************
1445BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
1446 LPCOMMCONFIG lpCC,
1447 LPDWORD lpdwSize)
1448{
1449 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1450
1451 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1452 *lpdwSize< sizeof(COMMCONFIG) )
1453 {
1454 ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
1455 *lpdwSize= sizeof(COMMCONFIG);
1456 return FALSE;
1457 }
1458
1459 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1460 {
1461 ::SetLastError(ERROR_INVALID_HANDLE);
1462 return FALSE;
1463 }
1464 dprintf(("GetDefaultCommConfig %x %x", lpCC, lpdwSize));
1465
1466 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1467 *lpdwSize = sizeof(COMMCONFIG);
1468 return(TRUE);
1469}
1470//******************************************************************************
1471//******************************************************************************
1472APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData,
1473 UCHAR ucSize,
1474 UCHAR ucParity,
1475 UCHAR ucStop)
1476{
1477 APIRET rc;
1478 ULONG ulLen;
1479 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1480 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1481 struct
1482 {
1483 UCHAR ucSize;
1484 UCHAR ucParity;
1485 UCHAR ucStop;
1486 UCHAR ucPadding;
1487 }Param;
1488
1489 ulLen = 3;
1490 Param.ucSize = ucSize;
1491 Param.ucParity = ucParity;
1492 Param.ucStop = ucStop;
1493
1494 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1495 IOCTL_ASYNC,
1496 ASYNC_SETLINECTRL,
1497 &Param,ulLen,&ulLen,
1498 NULL,0,NULL);
1499
1500 if(0==rc)
1501 {
1502 pCurDCB->ByteSize = ucSize;
1503 pCurDCB->Parity = ucParity;
1504 pCurDCB->StopBits = ucStop;
1505 }
1506 else {
1507 dprintf(("!ERROR! SetLine: OSLibDosDevIOCtl failed with rc %d", rc));
1508 }
1509 return rc;
1510}
1511//******************************************************************************
1512//******************************************************************************
1513APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData,
1514 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow,
1515 UCHAR ucDtrControl, BOOL fDsrSensitivity,
1516 BOOL fTXContinueOnXoff, BOOL fOutX,
1517 BOOL fInX, BOOL fErrorChar,
1518 BOOL fNull, UCHAR ucRtsControl,
1519 BOOL fAbortOnError, BYTE XonChar,
1520 BYTE XoffChar,BYTE ErrorChar)
1521{
1522 APIRET rc;
1523 ULONG ulLen;
1524 DCBINFO os2dcb;
1525 UCHAR fbTimeOut;
1526 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1527 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1528
1529 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1530 os2dcb.fbCtlHndShake = (ucDtrControl & 0x03) |
1531 (fOutxCtsFlow?0x08:0x00) |
1532 (fOutxDsrFlow?0x10:0x00) |
1533 // No DCD support in Win32 ?!
1534 (fDsrSensitivity?0x40:0x00);
1535 os2dcb.fbFlowReplace = (fOutX?0x01:0x00) |
1536 (fInX?0x02:0x00) |
1537 (fErrorChar?0x04:0x00)|
1538 (fNull?0x08:0x00)|
1539 (fTXContinueOnXoff?0x02:0x00)| // Not sure if thats the right flag to test
1540 (ucRtsControl<<6);
1541
1542 fbTimeOut = 0x02;
1543 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1544 {
1545 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1546 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1547 fbTimeOut = 0x05;
1548 else
1549 fbTimeOut = 0x04;
1550 }
1551 else
1552 {
1553 DWORD dwTimeout;
1554 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1555 if(dwTimeout)
1556 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1557 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1558 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1559 }
1560 os2dcb.fbTimeOut = (os2dcb.fbTimeOut & 0xF9) | fbTimeOut;
1561 os2dcb.bErrorReplacementChar = ErrorChar;
1562 os2dcb.bXONChar = XonChar;
1563 os2dcb.bXOFFChar = XoffChar;
1564 ulLen = sizeof(DCBINFO);
1565 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1566 IOCTL_ASYNC,
1567 ASYNC_SETDCBINFO,
1568 &os2dcb,ulLen,&ulLen,
1569 NULL,0,NULL);
1570
1571 if(0==rc)
1572 {
1573 memcpy(&pDevData->dcbOS2,&os2dcb,sizeof(DCBINFO));
1574 pCurDCB->fOutxCtsFlow = fOutxCtsFlow;
1575 pCurDCB->fOutxDsrFlow = fOutxDsrFlow;
1576 pCurDCB->fDtrControl = ucDtrControl;
1577 pCurDCB->fDsrSensitivity = fDsrSensitivity;
1578 pCurDCB->fTXContinueOnXoff = fTXContinueOnXoff;
1579 pCurDCB->fOutX = fOutX;
1580 pCurDCB->fInX = fInX;
1581 pCurDCB->fErrorChar = fErrorChar;
1582 pCurDCB->fNull = fNull;
1583 pCurDCB->fRtsControl = ucRtsControl;
1584 pCurDCB->fAbortOnError = fAbortOnError;
1585 pCurDCB->XonChar = XonChar;
1586 pCurDCB->XoffChar = XoffChar;
1587 pCurDCB->ErrorChar = ErrorChar;
1588 }
1589
1590 return rc;
1591
1592}
1593//******************************************************************************
1594//******************************************************************************
1595APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData,
1596 DWORD dwNewBaud)
1597{
1598 APIRET rc;
1599 ULONG ulLen;
1600 EXTBAUDSET SetBaud;
1601 EXTBAUDGET GetBaud;
1602 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1603
1604 ulLen = sizeof(SetBaud);
1605 SetBaud.ulBaud = dwNewBaud;
1606 SetBaud.ucFrac = 0;
1607 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1608 IOCTL_ASYNC,
1609 ASYNC_EXTSETBAUDRATE,
1610 &SetBaud,ulLen,&ulLen,
1611 NULL,0,NULL);
1612 if(0==rc)
1613 {
1614 ulLen = sizeof(GetBaud);
1615 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1616 IOCTL_ASYNC,
1617 ASYNC_EXTGETBAUDRATE,
1618 NULL,0,NULL,
1619 &GetBaud,ulLen,&ulLen);
1620 if(0==rc)
1621 {
1622 if(dwNewBaud != GetBaud.ulCurrBaud) {
1623 dprintf(("!WARNING! dwNewBaud (%d) != GetBaud.ulCurrBaud (%d)", dwNewBaud, GetBaud.ulCurrBaud));
1624 rc = 1; // ToDo set a proper Errorhandling
1625 }
1626 else
1627 {
1628 pDevData->CommCfg.dcb.BaudRate = dwNewBaud;
1629 }
1630 }
1631 else {
1632 dprintf(("!WARNING! SetBaud: (get) OSLibDosDevIOCtl failed with rc %d", rc));
1633 }
1634 }
1635 else {
1636 dprintf(("!WARNING! SetBaud: (set) OSLibDosDevIOCtl failed with rc %d", rc));
1637 }
1638 return rc;
1639}
1640//******************************************************************************
1641//******************************************************************************
1642
1643
Note: See TracBrowser for help on using the repository browser.