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

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

device name fixes

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