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

Last change on this file since 4865 was 4862, checked in by sandervl, 25 years ago

implemented ReadFile/WriteFile for COM devices

File size: 36.1 KB
Line 
1/* $Id: hmcomm.cpp,v 1.7 2000-12-31 12:28:53 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 *
10 */
11
12
13
14#include <os2win.h>
15#include <string.h>
16#include <handlemanager.h>
17#include <heapstring.h>
18#include "hmdevice.h"
19#include "hmcomm.h"
20#include "oslibdos.h"
21
22#define DBG_LOCALLOG DBG_hmcomm
23#include "dbglocal.h"
24
25#define MAGIC_COM 0x12abcd34
26
27#define IOCTL_ASYNC 0x01
28#define ASYNC_GETDCBINFO 0x73
29#define ASYNC_SETDCBINFO 0x53
30#define ASYNC_SETLINECTRL 0x42
31#define ASYNC_GETCOMMEVENT 0x72
32#define ASYNC_EXTGETBAUDRATE 0x63
33#define ASYNC_EXTSETBAUDRATE 0x43
34#define ASYNC_GETCOMMERROR 0x6D
35#define ASYNC_GETCOMMSTATUS 0x65
36#define ASYNC_GETINQUECOUNT 0x68
37#define ASYNC_GETOUTQUECOUNT 0x69
38#define ASYNC_GETMODEMINPUT 0x67
39#define ASYNC_TRANSMITIMM 0x44
40#define ASYNC_SETBREAKON 0x4B
41#define ASYNC_SETBREAKOFF 0x45
42#define ASYNC_SETMODEMCTRL 0x46
43#define ASYNC_STARTTRANSMIT 0x48
44#define ASYNC_STOPTRANSMIT 0x47
45
46
47
48#pragma pack(1)
49typedef struct _DCBINFO
50{
51 USHORT usWriteTimeout; /* Time period used for Write Timeout processing. */
52 USHORT usReadTimeout; /* Time period used for Read Timeout processing. */
53 BYTE fbCtlHndShake; /* HandShake Control flag. */
54 BYTE fbFlowReplace; /* Flow Control flag. */
55 BYTE fbTimeOut; /* Timeout flag. */
56 BYTE bErrorReplacementChar; /* Error Replacement Character. */
57 BYTE bBreakReplacementChar; /* Break Replacement Character. */
58 BYTE bXONChar; /* Character XON. */
59 BYTE bXOFFChar; /* Character XOFF. */
60} DCBINFO;
61typedef DCBINFO *PDCBINFO;
62
63
64typedef struct _RXQUEUE
65{
66 USHORT cch; /* Number of characters in the queue. */
67 USHORT cb; /* Size of receive/transmit queue. */
68} RXQUEUE;
69
70typedef RXQUEUE *PRXQUEUE;
71
72
73typedef struct _MODEMSTATUS
74{
75 BYTE fbModemOn; /* Modem Control Signals ON Mask. */
76 BYTE fbModemOff; /* Modem Control Signals OFF Mask. */
77} MODEMSTATUS;
78
79typedef MODEMSTATUS *PMODEMSTATUS;
80
81
82#pragma pack()
83
84
85
86
87
88typedef struct _HMDEVCOMDATA
89{
90 ULONG ulMagic;
91 // Win32 Device Control Block
92 COMMCONFIG CommCfg;
93 COMMTIMEOUTS CommTOuts;
94 DWORD dwInBuffer, dwOutBuffer;
95 DWORD dwEventMask;
96 //OS/2 Device Control Block
97 DCBINFO dcbOS2;
98} HMDEVCOMDATA, *PHMDEVCOMDATA;
99
100VOID *CreateDevData()
101{
102 PHMDEVCOMDATA pData;
103 pData = new HMDEVCOMDATA();
104 if(NULL!=pData)
105 {
106 memset(pData,0,sizeof(HMDEVCOMDATA));
107 pData->ulMagic = MAGIC_COM;
108 pData->CommCfg.dwSize = sizeof(COMMCONFIG);
109 pData->CommCfg.wVersion = 1;
110 pData->CommCfg.dwProviderSubType = PST_RS232;
111 pData->CommCfg.dcb.DCBlength = sizeof(DCB);
112 pData->CommCfg.dcb.BaudRate = CBR_1200;
113 pData->CommCfg.dcb.ByteSize = 8;
114 pData->CommCfg.dcb.Parity = NOPARITY;
115 pData->CommCfg.dcb.StopBits = ONESTOPBIT;
116 pData->dwInBuffer = 16;
117 pData->dwOutBuffer = 16;
118 }
119 return pData;
120}
121
122HMDeviceCommClass::HMDeviceCommClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName)
123{
124 VOID *pData;
125 dprintf(("HMDeviceCommClass: Register COM1 to COM8 with Handle Manager\n"));
126 pData = CreateDevData();
127 if(pData!= NULL)
128 HMDeviceRegisterEx("COM1", this, pData);
129}
130
131/*****************************************************************************
132 * Name : HMDeviceCommClass::FindDevice
133 * Purpose : Checks if lpDeviceName belongs to this device class
134 * Parameters: LPCSTR lpClassDevName
135 * LPCSTR lpDeviceName
136 * int namelength
137 * Variables :
138 * Result : checks if name is COMx or COMx: (x=1..8)
139 * Remark :
140 * Status :
141 *
142 * Author : SvL
143 *****************************************************************************/
144BOOL HMDeviceCommClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
145{
146 if(namelength > 5)
147 return FALSE; //can't be com name
148
149 //first 3 letters 'COM'?
150 if(lstrncmpiA(lpDeviceName, lpClassDevName, 3) != 0) {
151 return FALSE;
152 }
153
154 if(namelength == 5 && lpDeviceName[4] != ':') {
155 return FALSE;
156 }
157 switch(lpDeviceName[3]) {
158 case '1':
159 case '2':
160 case '3':
161 case '4':
162 case '5':
163 case '6':
164 case '7':
165 case '8':
166 return TRUE; //we support up to COM8
167 }
168 return FALSE;
169}
170
171DWORD HMDeviceCommClass::CreateFile(LPCSTR lpFileName,
172 PHMHANDLEDATA pHMHandleData,
173 PVOID lpSecurityAttributes,
174 PHMHANDLEDATA pHMHandleDataTemplate)
175{
176 char comname[6];
177
178 dprintf(("HMComm: Serial communication port %s open request\n", lpFileName));
179
180 if(strlen(lpFileName) > 5) {
181 return -1; //safety check (unnecessary..)
182 }
183 pHMHandleData->hHMHandle = 0;
184
185 strcpy(comname, lpFileName);
186 comname[4] = 0; //get rid of : (if present) (eg COM1:)
187
188 //AH: TODO parse Win32 security handles
189 OSLibDosDisableHardError(TRUE);
190 pHMHandleData->hHMHandle = OSLibDosOpen(comname,
191 OSLIB_ACCESS_READWRITE |
192 OSLIB_ACCESS_SHAREDENYREAD |
193 OSLIB_ACCESS_SHAREDENYWRITE);
194 OSLibDosDisableHardError(FALSE);
195 if (pHMHandleData->hHMHandle != 0)
196 {
197 ULONG ulLen;
198 APIRET rc;
199
200 pHMHandleData->lpHandlerData = new HMDEVCOMDATA();
201 // Init The handle instance with the default default device config
202 memcpy( pHMHandleData->lpHandlerData,
203 pHMHandleData->lpDeviceData,
204 sizeof(HMDEVCOMDATA));
205
206 ulLen = sizeof(DCBINFO);
207
208 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
209 IOCTL_ASYNC,
210 ASYNC_GETDCBINFO,
211 0,0,0,
212 &((PHMDEVCOMDATA)pHMHandleData->lpHandlerData)->dcbOS2,ulLen,&ulLen);
213
214 if(rc)
215 {
216 return -1;
217 }
218 return 0;
219 }
220 else
221 return -1;
222}
223
224
225 /* this is a handler method for calls to CloseHandle() */
226DWORD HMDeviceCommClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
227{
228 dprintf(("HMComm: Serial communication port close request\n"));
229 delete pHMHandleData->lpHandlerData;
230 return OSLibDosClose(pHMHandleData->hHMHandle);
231}
232
233/*****************************************************************************
234 * Name : DWORD HMDeviceHandler::SetupComm
235 * Purpose : set com port parameters (queue)
236 * Variables :
237 * Result :
238 * Remark :
239 * Status :
240 *
241 * Author : Achim Hasenmueller
242 *****************************************************************************/
243
244BOOL HMDeviceCommClass::SetupComm( PHMHANDLEDATA pHMHandleData,
245 DWORD dwInQueue,
246 DWORD dwOutQueue)
247{
248 dprintf(("HMDeviceCommClass::SetupComm "));
249 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
250 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
251 {
252 SetLastError(ERROR_INVALID_HANDLE);
253 return FALSE;
254 }
255 pDevData->dwInBuffer = dwInQueue;
256 pDevData->dwOutBuffer = dwOutQueue;
257
258 return(TRUE);
259}
260
261BOOL HMDeviceCommClass::WaitCommEvent( PHMHANDLEDATA pHMHandleData,
262 LPDWORD lpfdwEvtMask,
263 LPOVERLAPPED lpo)
264{
265 APIRET rc;
266 ULONG ulLen;
267 USHORT COMEvt;
268 DWORD dwEvent,dwMask;
269
270 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
271
272 dprintf(("HMDeviceCommClass::WaitCommEvent"));
273 ulLen = sizeof(CHAR);
274
275 dwEvent = 0;
276 rc = 0;
277 ulLen = sizeof(COMEvt);
278 dwMask = pDevData->dwEventMask;
279 while( (0==rc) &&
280 !(dwEvent & dwMask) &&
281 (dwMask ==pDevData->dwEventMask) ) // Exit if the Mask gets changed
282 {
283 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
284 IOCTL_ASYNC,
285 ASYNC_GETCOMMEVENT,
286 0,0,0,
287 &COMEvt,ulLen,&ulLen);
288 if(!rc)
289 {
290 dwEvent |= (COMEvt&0x0001)? EV_RXCHAR:0;
291 //dwEvent |= (COMEvt&0x0002)? 0:0;
292 dwEvent |= (COMEvt&0x0004)? EV_TXEMPTY:0;
293 dwEvent |= (COMEvt&0x0008)? EV_CTS:0;
294 dwEvent |= (COMEvt&0x0010)? EV_DSR:0;
295 //dwEvent |= (COMEvt&0x0020)? 0:0; DCS = RLSD?
296 dwEvent |= (COMEvt&0x0040)? EV_BREAK:0;
297 dwEvent |= (COMEvt&0x0080)? EV_ERR:0;
298 dwEvent |= (COMEvt&0x0100)? EV_RING:0;
299 }
300 DosSleep(100);
301 }
302 *lpfdwEvtMask = rc==0?dwEvent:0;
303 return(rc==0);
304}
305
306
307#pragma pack(1)
308typedef struct
309{
310 ULONG ulCurrBaud;
311 UCHAR ucCurrFrac;
312 ULONG ulMinBaud;
313 UCHAR ucMinFrac;
314 ULONG ulMaxBaud;
315 UCHAR ucMaxFrac;
316} EXTBAUDGET, *PEXTBAUDGET;
317
318typedef struct
319{
320 ULONG ulBaud;
321 UCHAR ucFrac;
322} EXTBAUDSET, *PEXTBAUDSET;
323#pragma pack()
324
325BAUDTABLEENTRY BaudTable[] =
326{
327 {75,BAUD_075},
328 {110,BAUD_110},
329 {134,BAUD_134_5},
330 {150,BAUD_150},
331 {300,BAUD_300},
332 {600,BAUD_600},
333 {1200,BAUD_1200},
334 {1800,BAUD_1800},
335 {2400,BAUD_2400},
336 {4800,BAUD_4800},
337 {7200,BAUD_7200},
338 {9600,BAUD_9600},
339 {14400,BAUD_14400},
340 {19200,BAUD_19200},
341 {38400,BAUD_38400},
342 {56000,BAUD_56K},
343 {57600,BAUD_57600},
344 {115200,BAUD_115200},
345 {128000,BAUD_128K}
346};
347
348#define BaudTableSize (sizeof(BaudTable)/sizeof(BAUDTABLEENTRY))
349
350BOOL HMDeviceCommClass::GetCommProperties( PHMHANDLEDATA pHMHandleData,
351 LPCOMMPROP lpcmmp)
352{
353 EXTBAUDGET BaudInfo;
354 APIRET rc;
355 ULONG ulLen;
356 USHORT COMErr;
357 int i;
358 dprintf(("HMDeviceCommClass::GetCommProperties"));
359
360 ulLen = sizeof(EXTBAUDGET);
361 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
362 IOCTL_ASYNC,
363 ASYNC_EXTGETBAUDRATE,
364 0,0,0,
365 &BaudInfo,ulLen,&ulLen);
366 memset(lpcmmp,0,sizeof(COMMPROP));
367 lpcmmp->wPacketLength = sizeof(COMMPROP);
368 lpcmmp->wPacketVersion = 1; //???
369 lpcmmp->dwServiceMask = SP_SERIALCOMM;
370 for(i=0;i<BaudTableSize && BaudInfo.ulMaxBaud <= BaudTable[i].dwBaudRate;i++);
371 lpcmmp->dwMaxBaud = BaudTable[i].dwBaudFlag;
372 lpcmmp->dwProvSubType = PST_RS232;
373 lpcmmp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK |
374 PCF_RTSCTS | PCF_SETXCHAR |
375 PCF_XONXOFF;
376 lpcmmp->dwSettableParams = SP_BAUD | SP_DATABITS |
377 SP_HANDSHAKEING | SP_PARITY |
378 SP_PARITY_CHECK | SP_STOPBIT;
379 lpcmmp->dwSettableBaud = 0;
380 for(i=0;i<BaudTableSize;i++)
381 {
382 if ( (BaudTable[i].dwBaudRate>=BaudInfo.ulMinBaud) &&
383 (BaudTable[i].dwBaudRate<=BaudInfo.ulMaxBaud) )
384 lpcmmp->dwSettableBaud |= BaudTable[i].dwBaudFlag;
385 }
386 lpcmmp->dwSettableBaud |= BAUD_USER;
387 lpcmmp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
388 lpcmmp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
389 PARITY_NONE | PARITY_ODD | PARITY_EVEN |
390 PARITY_MARK | PARITY_SPACE;
391 return(rc==0);
392}
393
394BOOL HMDeviceCommClass::GetCommMask( PHMHANDLEDATA pHMHandleData,
395 LPDWORD lpfdwEvtMask)
396{
397 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
398
399 dprintf(("HMDeviceCommClass::GetCommMask"));
400
401 *lpfdwEvtMask = pDevData->dwEventMask;
402 return(TRUE);
403}
404
405BOOL HMDeviceCommClass::SetCommMask( PHMHANDLEDATA pHMHandleData,
406 DWORD fdwEvtMask)
407{
408 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
409 dprintf(("HMDeviceCommClass::SetCommMask"));
410
411 pDevData->dwEventMask = fdwEvtMask & ~(EV_RLSD|EV_RXFLAG); // Clear the 2 not supported Flags.
412 return(TRUE);
413}
414
415BOOL HMDeviceCommClass::PurgeComm( PHMHANDLEDATA pHMHandleData,
416 DWORD fdwAction)
417{
418 dprintf(("HMDeviceCommClass::PurgeComm unimplemented stub!"));
419 // ToDo: find a way to stop the current transmision didn't find
420 // any clue how to in Control Program Guide and reference
421
422 return(TRUE);
423}
424BOOL HMDeviceCommClass::ClearCommError( PHMHANDLEDATA pHMHandleData,
425 LPDWORD lpdwErrors,
426 LPCOMSTAT lpcst)
427{
428 APIRET rc;
429 ULONG ulLen;
430 USHORT COMErr;
431
432 dprintf(("HMDeviceCommClass::ClearCommError"));
433 ulLen = sizeof(USHORT);
434
435 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
436 IOCTL_ASYNC,
437 ASYNC_GETCOMMERROR,
438 0,0,0,
439 &COMErr,2,&ulLen);
440 *lpdwErrors = 0;
441 *lpdwErrors |= (COMErr & 0x0001)?CE_OVERRUN:0;
442 *lpdwErrors |= (COMErr & 0x0002)?CE_RXOVER:0;
443 *lpdwErrors |= (COMErr & 0x0004)?CE_RXPARITY:0;
444 *lpdwErrors |= (COMErr & 0x0008)?CE_FRAME:0;
445
446 if(lpcst)
447 {
448 UCHAR ucStatus;
449 RXQUEUE qInfo;
450 ulLen = 1;
451 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
452 IOCTL_ASYNC,
453 ASYNC_GETCOMMSTATUS,
454 0,0,0,
455 &ucStatus,ulLen,&ulLen);
456 if(!rc)
457 {
458 lpcst->fCtsHold = ((ucStatus & 0x01)>0);
459 lpcst->fDsrHold = ((ucStatus & 0x02)>0);
460 lpcst->fRlsdHold = FALSE;//(ucStatus & 0x04)>0);
461 lpcst->fXoffHold = ((ucStatus & 0x08)>0);
462 lpcst->fXoffSend = ((ucStatus & 0x10)>0);
463 lpcst->fEof = ((ucStatus & 0x20)>0);// Is break = Eof ??
464 lpcst->fTxim = ((ucStatus & 0x40)>0);
465
466 ulLen = sizeof(qInfo);
467 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
468 IOCTL_ASYNC,
469 ASYNC_GETINQUECOUNT,
470 0,0,0,
471 &qInfo,ulLen,&ulLen);
472 if(!rc)
473 {
474 lpcst->cbInQue = qInfo.cch;
475 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
476 IOCTL_ASYNC,
477 ASYNC_GETOUTQUECOUNT,
478 0,0,0,
479 &qInfo,ulLen,&ulLen);
480 if(!rc)
481 lpcst->cbOutQue = qInfo.cch;
482 }
483 }
484 }
485
486 return(rc==0);
487}
488BOOL HMDeviceCommClass::SetCommState( PHMHANDLEDATA pHMHandleData,
489 LPDCB lpDCB)
490{
491 APIRET rc;
492 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
493 DCB *pCurDCB = &pDevData->CommCfg.dcb;
494 dprintf(("HMDeviceCommClass::SetCommState"));
495
496 rc = 0;
497 if(pCurDCB->BaudRate != lpDCB->BaudRate)
498 rc = SetBaud( pHMHandleData,
499 lpDCB->BaudRate);
500
501 if(!rc)
502 {
503 if( (pCurDCB->ByteSize != lpDCB->ByteSize) ||
504 (pCurDCB->Parity != lpDCB->Parity) ||
505 (pCurDCB->StopBits != lpDCB->StopBits))
506 rc = SetLine( pHMHandleData,
507 lpDCB->ByteSize,
508 lpDCB->Parity,
509 lpDCB->StopBits);
510 }
511
512 if(!rc)
513 {
514 if( (pCurDCB->fOutxCtsFlow != lpDCB->fOutxCtsFlow) ||
515 (pCurDCB->fOutxDsrFlow != lpDCB->fOutxDsrFlow) ||
516 (pCurDCB->fDtrControl != lpDCB->fDtrControl) ||
517 (pCurDCB->fDsrSensitivity != lpDCB->fDsrSensitivity) ||
518 (pCurDCB->fTXContinueOnXoff != lpDCB->fTXContinueOnXoff) ||
519 (pCurDCB->fOutX != lpDCB->fOutX) ||
520 (pCurDCB->fInX != lpDCB->fInX) ||
521 (pCurDCB->fErrorChar != lpDCB->fErrorChar) ||
522 (pCurDCB->fNull != lpDCB->fNull) ||
523 (pCurDCB->fRtsControl != lpDCB->fRtsControl) ||
524 (pCurDCB->fAbortOnError != lpDCB->fAbortOnError) ||
525 (pCurDCB->XonChar != lpDCB->XonChar) ||
526 (pCurDCB->XoffChar != lpDCB->XoffChar) ||
527 (pCurDCB->ErrorChar != lpDCB->ErrorChar))
528 SetOS2DCB( pHMHandleData,
529 lpDCB->fOutxCtsFlow, lpDCB->fOutxDsrFlow,
530 lpDCB->fDtrControl, lpDCB->fDsrSensitivity,
531 lpDCB->fTXContinueOnXoff, lpDCB->fOutX,
532 lpDCB->fInX, lpDCB->fErrorChar,
533 lpDCB->fNull, lpDCB->fRtsControl,
534 lpDCB->fAbortOnError, lpDCB->XonChar,
535 lpDCB->XoffChar,lpDCB->ErrorChar);
536 }
537
538 return(rc==0);
539}
540BOOL HMDeviceCommClass::GetCommState( PHMHANDLEDATA pHMHandleData,
541 LPDCB lpdcb)
542{
543 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
544
545 dprintf(("HMDeviceCommClass::GetCommState"));
546 memcpy(lpdcb,&pDevData->CommCfg.dcb,sizeof(DCB));
547
548 return(TRUE);
549}
550BOOL HMDeviceCommClass::GetCommModemStatus( PHMHANDLEDATA pHMHandleData,
551 LPDWORD lpModemStat )
552{
553 APIRET rc;
554 ULONG ulLen;
555 USHORT COMErr;
556 UCHAR ucStatus;
557
558 dprintf(("HMDeviceCommClass::TransmitCommChar partly implemented"));
559 ulLen = sizeof(CHAR);
560
561 ulLen = 1;
562 *lpModemStat = 0;
563
564 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
565 IOCTL_ASYNC,
566 ASYNC_GETMODEMINPUT,
567 0,0,0,
568 &ucStatus,ulLen,&ulLen);
569 if(!rc)
570 {
571 *lpModemStat |= (ucStatus & 0x10)? MS_CTS_ON:0;
572 *lpModemStat |= (ucStatus & 0x20)? MS_DSR_ON:0;
573 *lpModemStat |= (ucStatus & 0x40)? MS_RING_ON:0;
574 //*lpModemStat |= (ucStatus & 0x80)? MS_RSLD_ON:0;
575 }
576
577 return(rc==0);
578}
579
580BOOL HMDeviceCommClass::GetCommTimeouts( PHMHANDLEDATA pHMHandleData,
581 LPCOMMTIMEOUTS lpctmo)
582{
583 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
584
585 dprintf(("HMDeviceCommClass::GetCommTimeouts stub"));
586 memcpy( lpctmo,
587 &pDevData->CommTOuts,
588 sizeof(COMMTIMEOUTS));
589 return(TRUE);
590}
591BOOL HMDeviceCommClass::SetCommTimeouts( PHMHANDLEDATA pHMHandleData,
592 LPCOMMTIMEOUTS lpctmo)
593{
594 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
595 DCBINFO os2dcb;
596 ULONG ulLen;
597 APIRET rc;
598
599 memcpy( &pDevData->CommTOuts,
600 lpctmo,
601 sizeof(COMMTIMEOUTS));
602
603 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
604
605 os2dcb.fbTimeOut = 0x01;
606 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
607 {
608 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
609 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
610 os2dcb.fbTimeOut = 0x03;
611 else
612 os2dcb.fbTimeOut = 0x02;
613 }
614 else
615 {
616 DWORD dwTimeout;
617 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
618 if(dwTimeout)
619 dwTimeout--; // 0=10 ms unit is 10ms or .01s
620 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
621 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
622 }
623 ulLen = sizeof(DCBINFO);
624 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
625 IOCTL_ASYNC,
626 ASYNC_SETDCBINFO,
627 &os2dcb,ulLen,&ulLen,
628 NULL,0,NULL);
629
630 return(0==rc);
631}
632BOOL HMDeviceCommClass::TransmitCommChar( PHMHANDLEDATA pHMHandleData,
633 CHAR cChar )
634{
635 APIRET rc;
636 ULONG ulLen;
637 USHORT COMErr;
638
639 dprintf(("HMDeviceCommClass::TransmitCommChar"));
640 ulLen = sizeof(CHAR);
641
642 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
643 IOCTL_ASYNC,
644 ASYNC_TRANSMITIMM,
645 &cChar,ulLen,&ulLen,
646 NULL,0,NULL);
647
648 return(rc==0);
649}
650
651/*****************************************************************************
652 * Name : BOOL HMDeviceCommClass::WriteFile
653 * Purpose : write data to handle / device
654 * Parameters: PHMHANDLEDATA pHMHandleData,
655 * LPCVOID lpBuffer,
656 * DWORD nNumberOfBytesToWrite,
657 * LPDWORD lpNumberOfBytesWritten,
658 * LPOVERLAPPED lpOverlapped
659 * Variables :
660 * Result : Boolean
661 * Remark :
662 * Status :
663 *
664 * Author : SvL
665 *****************************************************************************/
666
667BOOL HMDeviceCommClass::WriteFile(PHMHANDLEDATA pHMHandleData,
668 LPCVOID lpBuffer,
669 DWORD nNumberOfBytesToWrite,
670 LPDWORD lpNumberOfBytesWritten,
671 LPOVERLAPPED lpOverlapped)
672{
673 dprintf(("KERNEL32:HMDeviceCommClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x)",
674 lpHMDeviceName,
675 pHMHandleData->hHMHandle,
676 lpBuffer,
677 nNumberOfBytesToWrite,
678 lpNumberOfBytesWritten,
679 lpOverlapped));
680
681 APIRET rc;
682 ULONG ulBytesWritten;
683
684 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
685 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
686 SetLastError(ERROR_INVALID_PARAMETER);
687 return FALSE;
688 }
689 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
690 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
691 }
692
693 rc = OSLibDosWrite(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToWrite,
694 &ulBytesWritten);
695
696 if(lpNumberOfBytesWritten) {
697 *lpNumberOfBytesWritten = (rc) ? 0 : ulBytesWritten;
698 }
699 return(rc==0);
700}
701
702/*****************************************************************************
703 * Name : BOOL WriteFileEx
704 * Purpose : The WriteFileEx function writes data to a file. It is designed
705 * solely for asynchronous operation, unlike WriteFile, which is
706 * designed for both synchronous and asynchronous operation.
707 * WriteFileEx reports its completion status asynchronously,
708 * calling a specified completion routine when writing is completed
709 * and the calling thread is in an alertable wait state.
710 * Parameters: HANDLE hFile handle of file to write
711 * LPVOID lpBuffer address of buffer
712 * DWORD nNumberOfBytesToRead number of bytes to write
713 * LPOVERLAPPED lpOverlapped address of offset
714 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
715 * Variables :
716 * Result : TRUE / FALSE
717 * Remark :
718 * Status : UNTESTED STUB
719 *
720 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
721 *****************************************************************************/
722
723BOOL HMDeviceCommClass::WriteFileEx(PHMHANDLEDATA pHMHandleData,
724 LPVOID lpBuffer,
725 DWORD nNumberOfBytesToWrite,
726 LPOVERLAPPED lpOverlapped,
727 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
728{
729 dprintf(("ERROR: WriteFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
730 lpHMDeviceName,
731 pHMHandleData->hHMHandle,
732 lpBuffer,
733 nNumberOfBytesToWrite,
734 lpOverlapped,
735 lpCompletionRoutine));
736
737 SetLastError(ERROR_INVALID_FUNCTION);
738 return FALSE;
739}
740
741/*****************************************************************************
742 * Name : BOOL HMDeviceCommClass::ReadFile
743 * Purpose : read data from handle / device
744 * Parameters: PHMHANDLEDATA pHMHandleData,
745 * LPCVOID lpBuffer,
746 * DWORD nNumberOfBytesToRead,
747 * LPDWORD lpNumberOfBytesRead,
748 * LPOVERLAPPED lpOverlapped
749 * Variables :
750 * Result : Boolean
751 * Remark :
752 * Status :
753 *
754 * Author : SvL
755 *****************************************************************************/
756
757BOOL HMDeviceCommClass::ReadFile(PHMHANDLEDATA pHMHandleData,
758 LPCVOID lpBuffer,
759 DWORD nNumberOfBytesToRead,
760 LPDWORD lpNumberOfBytesRead,
761 LPOVERLAPPED lpOverlapped)
762{
763 dprintf(("KERNEL32:HMDeviceCommClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
764 lpHMDeviceName,
765 pHMHandleData->hHMHandle,
766 lpBuffer,
767 nNumberOfBytesToRead,
768 lpNumberOfBytesRead,
769 lpOverlapped));
770
771 APIRET rc;
772 ULONG ulBytesRead;
773
774 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
775 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
776 SetLastError(ERROR_INVALID_PARAMETER);
777 return FALSE;
778 }
779 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
780 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
781 }
782
783 rc = OSLibDosRead(pHMHandleData->hHMHandle, (LPVOID)lpBuffer, nNumberOfBytesToRead,
784 &ulBytesRead);
785
786 if(lpNumberOfBytesRead) {
787 *lpNumberOfBytesRead = (rc) ? 0 : ulBytesRead;
788 }
789 return(rc==0);
790}
791
792/*****************************************************************************
793 * Name : BOOL ReadFileEx
794 * Purpose : The ReadFileEx function reads data from a file asynchronously.
795 * It is designed solely for asynchronous operation, unlike the
796 * ReadFile function, which is designed for both synchronous and
797 * asynchronous operation. ReadFileEx lets an application perform
798 * other processing during a file read operation.
799 * The ReadFileEx function reports its completion status asynchronously,
800 * calling a specified completion routine when reading is completed
801 * and the calling thread is in an alertable wait state.
802 * Parameters: HANDLE hFile handle of file to read
803 * LPVOID lpBuffer address of buffer
804 * DWORD nNumberOfBytesToRead number of bytes to read
805 * LPOVERLAPPED lpOverlapped address of offset
806 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
807 * Variables :
808 * Result : TRUE / FALSE
809 * Remark :
810 * Status : UNTESTED STUB
811 *
812 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
813 *****************************************************************************/
814BOOL HMDeviceCommClass::ReadFileEx(PHMHANDLEDATA pHMHandleData,
815 LPVOID lpBuffer,
816 DWORD nNumberOfBytesToRead,
817 LPOVERLAPPED lpOverlapped,
818 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
819{
820 dprintf(("ERROR: ReadFileEx %s (%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
821 lpHMDeviceName,
822 pHMHandleData->hHMHandle,
823 lpBuffer,
824 nNumberOfBytesToRead,
825 lpOverlapped,
826 lpCompletionRoutine));
827
828 SetLastError(ERROR_INVALID_FUNCTION);
829 return FALSE;
830}
831
832BOOL HMDeviceCommClass::SetCommBreak( PHMHANDLEDATA pHMHandleData )
833{
834 APIRET rc;
835 ULONG ulLen;
836 USHORT COMErr;
837
838 dprintf(("HMDeviceCommClass::SetCommBreak"));
839 ulLen = sizeof(USHORT);
840
841 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
842 IOCTL_ASYNC,
843 ASYNC_SETBREAKON,
844 0,0,0,
845 &COMErr,2,&ulLen);
846
847 return(rc==0);
848}
849
850BOOL HMDeviceCommClass::ClearCommBreak( PHMHANDLEDATA pHMHandleData)
851{
852 APIRET rc;
853 ULONG ulLen;
854 USHORT COMErr;
855
856 dprintf(("HMDeviceCommClass::ClearCommBreak"));
857 ulLen = sizeof(USHORT);
858
859 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
860 IOCTL_ASYNC,
861 ASYNC_SETBREAKOFF,
862 0,0,0,
863 &COMErr,2,&ulLen);
864
865 return(rc==0);
866}
867
868BOOL HMDeviceCommClass::SetCommConfig( PHMHANDLEDATA pHMHandleData,
869 LPCOMMCONFIG lpCC,
870 DWORD dwSize )
871{
872 dprintf(("HMDeviceCommClass::SetCommConfig"));
873
874
875 return(TRUE);
876}
877
878BOOL HMDeviceCommClass::GetCommConfig( PHMHANDLEDATA pHMHandleData,
879 LPCOMMCONFIG lpCC,
880 LPDWORD lpdwSize )
881{
882 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
883
884 dprintf(("HMDeviceCommClass::GetCommConfig"));
885
886 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
887 *lpdwSize< sizeof(COMMCONFIG) )
888 {
889 SetLastError(ERROR_INSUFFICIENT_BUFFER);
890 *lpdwSize= sizeof(COMMCONFIG);
891 return FALSE;
892 }
893
894 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
895 {
896 SetLastError(ERROR_INVALID_HANDLE);
897 return FALSE;
898 }
899
900 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
901 *lpdwSize = sizeof(COMMCONFIG);
902 return(TRUE);
903
904
905 return(TRUE);
906}
907
908BOOL HMDeviceCommClass::EscapeCommFunction( PHMHANDLEDATA pHMHandleData,
909 UINT dwFunc )
910{
911 APIRET rc;
912 ULONG ulDLen,ulPLen;
913 USHORT COMErr;
914 MODEMSTATUS mdm;
915
916 dprintf(("HMDeviceCommClass::EscapeCommFunction"));
917
918 ulDLen = sizeof(USHORT);
919 ulPLen = sizeof(MODEMSTATUS);
920 switch(dwFunc)
921 {
922 case CLRDTR:
923 mdm.fbModemOn = 0x00;
924 mdm.fbModemOff = 0XFE;
925 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
926 IOCTL_ASYNC,
927 ASYNC_SETMODEMCTRL,
928 &mdm,ulPLen,&ulPLen,
929 &COMErr,ulDLen,&ulDLen);
930 break;
931 case CLRRTS:
932 mdm.fbModemOn = 0x00;
933 mdm.fbModemOff = 0XFD;
934 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
935 IOCTL_ASYNC,
936 ASYNC_SETMODEMCTRL,
937 &mdm,ulPLen,&ulPLen,
938 &COMErr,ulDLen,&ulDLen);
939 break;
940 case SETDTR:
941 mdm.fbModemOn = 0x01;
942 mdm.fbModemOff = 0XFF;
943 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
944 IOCTL_ASYNC,
945 ASYNC_SETMODEMCTRL,
946 &mdm,ulPLen,&ulPLen,
947 &COMErr,ulDLen,&ulDLen);
948 break;
949 case SETRTS:
950 mdm.fbModemOn = 0x02;
951 mdm.fbModemOff = 0XFF;
952 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
953 IOCTL_ASYNC,
954 ASYNC_SETMODEMCTRL,
955 &mdm,ulPLen,&ulPLen,
956 &COMErr,ulDLen,&ulDLen);
957 break;
958 case SETXOFF:
959 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
960 IOCTL_ASYNC,
961 ASYNC_STOPTRANSMIT,
962 0,0,0,
963 0,0,0);
964 break;
965 case SETXON:
966 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
967 IOCTL_ASYNC,
968 ASYNC_STARTTRANSMIT,
969 0,0,0,
970 0,0,0);
971 break;
972 default:
973 SetLastError(ERROR_INVALID_PARAMETER);
974 return(FALSE);
975 }
976
977 return(rc==0);
978}
979
980BOOL HMDeviceCommClass::SetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
981 LPCOMMCONFIG lpCC,
982 DWORD dwSize)
983{
984 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
985 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
986 {
987 SetLastError(ERROR_INVALID_HANDLE);
988 return FALSE;
989 }
990 memset(&pDevData->CommCfg,0, sizeof(COMMCONFIG));
991 memcpy(&pDevData->CommCfg,lpCC,dwSize>sizeof(COMMCONFIG)?sizeof(COMMCONFIG):dwSize);
992
993 return(TRUE);
994}
995BOOL HMDeviceCommClass::GetDefaultCommConfig( PHMHANDLEDATA pHMHandleData,
996 LPCOMMCONFIG lpCC,
997 LPDWORD lpdwSize)
998{
999 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpDeviceData;
1000
1001 if( O32_IsBadWritePtr(lpCC,sizeof(COMMCONFIG)) ||
1002 *lpdwSize< sizeof(COMMCONFIG) )
1003 {
1004 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1005 *lpdwSize= sizeof(COMMCONFIG);
1006 return FALSE;
1007 }
1008
1009 if((NULL==pDevData) || (pDevData->ulMagic != MAGIC_COM) )
1010 {
1011 SetLastError(ERROR_INVALID_HANDLE);
1012 return FALSE;
1013 }
1014
1015 memcpy(lpCC,&pDevData->CommCfg,sizeof(COMMCONFIG));
1016 *lpdwSize = sizeof(COMMCONFIG);
1017 return(TRUE);
1018}
1019APIRET HMDeviceCommClass::SetLine( PHMHANDLEDATA pHMHandleData,
1020 UCHAR ucSize,
1021 UCHAR ucParity,
1022 UCHAR ucStop)
1023{
1024 APIRET rc;
1025 ULONG ulLen;
1026 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1027 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1028 struct
1029 {
1030 UCHAR ucSize;
1031 UCHAR ucParity;
1032 UCHAR ucStop;
1033 UCHAR ucPadding;
1034 }Param;
1035
1036 ulLen = 3;
1037 Param.ucSize = ucSize;
1038 Param.ucParity = ucParity;
1039 Param.ucStop = ucStop;
1040
1041 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1042 IOCTL_ASYNC,
1043 ASYNC_SETLINECTRL,
1044 &Param,ulLen,&ulLen,
1045 NULL,0,NULL);
1046
1047 if(0==rc)
1048 {
1049 pCurDCB->ByteSize = ucSize;
1050 pCurDCB->Parity = ucParity;
1051 pCurDCB->StopBits = ucStop;
1052 }
1053
1054 return rc;
1055}
1056
1057APIRET HMDeviceCommClass::SetOS2DCB( PHMHANDLEDATA pHMHandleData,
1058 BOOL fOutxCtsFlow, BOOL fOutxDsrFlow,
1059 UCHAR ucDtrControl, BOOL fDsrSensitivity,
1060 BOOL fTXContinueOnXoff, BOOL fOutX,
1061 BOOL fInX, BOOL fErrorChar,
1062 BOOL fNull, UCHAR ucRtsControl,
1063 BOOL fAbortOnError, BYTE XonChar,
1064 BYTE XoffChar,BYTE ErrorChar)
1065{
1066 APIRET rc;
1067 ULONG ulLen;
1068 DCBINFO os2dcb;
1069
1070 PHMDEVCOMDATA pDevData = (PHMDEVCOMDATA)pHMHandleData->lpHandlerData;
1071 DCB *pCurDCB = &pDevData->CommCfg.dcb;
1072
1073 memcpy(&os2dcb,&pDevData->dcbOS2,sizeof(DCBINFO));
1074 os2dcb.fbCtlHndShake = (ucDtrControl & 0x03) |
1075 (fOutxCtsFlow?0x08:0x00) |
1076 (fOutxDsrFlow?0x10:0x00) |
1077 // No DCD support in Win32 ?!
1078 (fDsrSensitivity?0x40:0x00);
1079 os2dcb.fbFlowReplace = (fOutX?0x01:0x00) |
1080 (fInX?0x02:0x00) |
1081 (fErrorChar?0x04:0x00)|
1082 (fNull?0x08:0x00)|
1083 (fTXContinueOnXoff?0x02:0x00)| // Not sure if thats the right flag to test
1084 (ucRtsControl<<6);
1085
1086 os2dcb.fbTimeOut = 0x01;
1087 if(MAXDWORD==pDevData->CommTOuts.ReadIntervalTimeout)
1088 {
1089 if( (0==pDevData->CommTOuts.ReadTotalTimeoutMultiplier) &&
1090 (0==pDevData->CommTOuts.ReadTotalTimeoutConstant))
1091 os2dcb.fbTimeOut = 0x03;
1092 else
1093 os2dcb.fbTimeOut = 0x02;
1094 }
1095 else
1096 {
1097 DWORD dwTimeout;
1098 dwTimeout = pDevData->CommTOuts.ReadIntervalTimeout/10;
1099 if(dwTimeout)
1100 dwTimeout--; // 0=10 ms unit is 10ms or .01s
1101 os2dcb.usWriteTimeout = 0x0000FFFF & dwTimeout;
1102 os2dcb.usReadTimeout = 0x0000FFFF & dwTimeout;
1103 }
1104 os2dcb.bErrorReplacementChar = ErrorChar;
1105 os2dcb.bXONChar = XonChar;
1106 os2dcb.bXOFFChar = XoffChar;
1107 ulLen = sizeof(DCBINFO);
1108 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1109 IOCTL_ASYNC,
1110 ASYNC_SETDCBINFO,
1111 &os2dcb,ulLen,&ulLen,
1112 NULL,0,NULL);
1113
1114 if(0==rc)
1115 {
1116 memcpy(&pDevData->dcbOS2,&os2dcb,sizeof(DCBINFO));
1117 pCurDCB->fOutxCtsFlow = fOutxCtsFlow;
1118 pCurDCB->fOutxDsrFlow = fOutxDsrFlow;
1119 pCurDCB->fDtrControl = ucDtrControl;
1120 pCurDCB->fDsrSensitivity = fDsrSensitivity;
1121 pCurDCB->fTXContinueOnXoff = fTXContinueOnXoff;
1122 pCurDCB->fOutX = fOutX;
1123 pCurDCB->fInX = fInX;
1124 pCurDCB->fErrorChar = fErrorChar;
1125 pCurDCB->fNull = fNull;
1126 pCurDCB->fRtsControl = ucRtsControl;
1127 pCurDCB->fAbortOnError = fAbortOnError;
1128 pCurDCB->XonChar = XonChar;
1129 pCurDCB->XoffChar = XoffChar;
1130 pCurDCB->ErrorChar = ErrorChar;
1131 }
1132
1133 return rc;
1134
1135}
1136
1137APIRET HMDeviceCommClass::SetBaud( PHMHANDLEDATA pHMHandleData,
1138 DWORD dwNewBaud)
1139{
1140 APIRET rc;
1141 ULONG ulLen;
1142 EXTBAUDSET SetBaud;
1143 EXTBAUDGET GetBaud;
1144 ulLen = sizeof(SetBaud);
1145 SetBaud.ulBaud = dwNewBaud;
1146 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1147 IOCTL_ASYNC,
1148 ASYNC_EXTSETBAUDRATE,
1149 &SetBaud,ulLen,&ulLen,
1150 NULL,0,NULL);
1151 if(0==rc)
1152 {
1153 ulLen = sizeof(GetBaud);
1154 rc = OSLibDosDevIOCtl( pHMHandleData->hHMHandle,
1155 IOCTL_ASYNC,
1156 ASYNC_EXTGETBAUDRATE,
1157 NULL,0,NULL,
1158 &GetBaud,ulLen,&ulLen);
1159 if(0==rc)
1160 {
1161 if(dwNewBaud !=GetBaud.ulCurrBaud)
1162 rc = 1; // ToDo set a proper Errorhandling
1163 else
1164 {
1165 ((PHMDEVCOMDATA)pHMHandleData->lpDeviceData)->CommCfg.dcb.BaudRate = dwNewBaud;
1166 ((PHMDEVCOMDATA)pHMHandleData->lpDeviceData)->CommCfg.dcb.BaudRate = dwNewBaud;
1167 }
1168 }
1169 }
1170 return rc;
1171}
1172
Note: See TracBrowser for help on using the repository browser.