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

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

preliminary work on overlapped serial comm IO

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