2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/comm.c
5 * PURPOSE: Comm functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
8 * Robert Dickenson (robd@mok.lvcom.com)
9 * Saveliy Tretiakov (saveliyt@mail.ru)
10 * Dmitry Philippov (shedon@mail.ru)
13 * RDD (30/09/2002) implemented many function bodies to call serial driver.
14 * KJK (11/02/2003) implemented BuildCommDCB & BuildCommDCBAndTimeouts
15 * ST (21/03/2005) implemented GetCommProperties
16 * ST (24/03/2005) implemented ClearCommError. Corrected many functions.
17 * ST (05/04/2005) implemented CommConfigDialog
18 * DP (11/06/2005) implemented GetCommConfig
19 * DP (12/06/2005) implemented SetCommConfig
24 #undef SERIAL_LSRMST_ESCAPE
25 #undef SERIAL_LSRMST_LSR_DATA
26 #undef SERIAL_LSRMST_LSR_NODATA
27 #undef SERIAL_LSRMST_MST
28 #undef SERIAL_IOC_FCR_FIFO_ENABLE
29 #undef SERIAL_IOC_FCR_RCVR_RESET
30 #undef SERIAL_IOC_FCR_XMIT_RESET
31 #undef SERIAL_IOC_FCR_DMA_MODE
32 #undef SERIAL_IOC_FCR_RES1
33 #undef SERIAL_IOC_FCR_RES2
34 #undef SERIAL_IOC_FCR_RCVR_TRIGGER_LSB
35 #undef SERIAL_IOC_FCR_RCVR_TRIGGER_MSB
36 #undef SERIAL_IOC_MCR_DTR
37 #undef SERIAL_IOC_MCR_RTS
38 #undef SERIAL_IOC_MCR_OUT1
39 #undef SERIAL_IOC_MCR_OUT2
40 #undef SERIAL_IOC_MCR_LOOP
44 #include "../include/debug.h"
46 /* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */
50 /* Pointer to a callback that handles a particular parameter */
51 typedef BOOL (*COMMDCB_PARAM_CALLBACK
)(DCB
*, COMMTIMEOUTS
*, BOOL
*, LPWSTR
*);
53 /* Symbolic flag of any length */
54 typedef struct _COMMDCB_PARAM_STRFLAG
56 UNICODE_STRING String
;
58 } COMMDCB_PARAM_STRFLAG
, *PCOMMDCB_PARAM_STRFLAG
;
60 /* One char long symbolic flag */
61 typedef struct _COMMDCB_PARAM_CHARFLAG
65 } COMMDCB_PARAM_CHARFLAG
, *PCOMMDCB_PARAM_CHARFLAG
;
69 /* Declare a parameter handler */
70 #define COMMDCB_PARAM_HANDLER(__P__) \
71 BOOL COMMDCB_ ## __P__ ## Param \
74 COMMTIMEOUTS * Timeouts, \
81 Lookup a string flag and return its numerical value. The flags array must be
82 sorted - a dichotomycal search is performed
85 COMMDCB_LookupStrFlag(PUNICODE_STRING Flag
,
86 PCOMMDCB_PARAM_STRFLAG Flags
,
90 /* Lower and upper bound for dichotomycal search */
92 int nUpperBound
= FlagCount
- 1;
97 /* pick the element in the middle of the area of interest as the pivot */
98 int nCurFlag
= nLowerBound
+ (nUpperBound
- nLowerBound
) / 2;
100 /* compare the string with the pivot */
101 nComparison
= RtlCompareUnicodeString(Flag
,
102 &Flags
[nCurFlag
].String
,
105 /* string is equal */
108 /* return the flag's value */
109 *Value
= Flags
[nCurFlag
].Value
;
114 else if(nComparison
< 0)
117 * restrict the search to the first half of the current slice, minus the pivot
119 nUpperBound
= nCurFlag
- 1;
124 * restrict the search to the second half of the current slice, minus the pivot
126 nLowerBound
= nCurFlag
+ 1;
128 } while(nLowerBound
<= nUpperBound
);
130 /* string not found: failure */
136 Find the next character flag and return its numerical value. The flags array
137 must be sorted - a dichotomycal search is performed
140 COMMDCB_ParseCharFlag(LPWSTR
*StrTail
,
141 PCOMMDCB_PARAM_CHARFLAG Flags
,
145 /* Lower and upper bound for dichotomycal search */
147 int nUpperBound
= FlagCount
- 1;
148 /* get the first character as the flag */
149 WCHAR wcFlag
= (*StrTail
)[0];
151 /* premature end of string, or the character is whitespace */
152 if(!wcFlag
|| iswspace(wcFlag
))
155 /* uppercase the character for case-insensitive search */
156 wcFlag
= towupper(wcFlag
);
158 /* skip the character flag */
161 /* see COMMDCB_LookupStrFlag for a description of the algorithm */
165 int nCurFlag
= nLowerBound
+ (nUpperBound
- nLowerBound
) / 2;
167 nComparison
= wcFlag
- towupper(Flags
[nCurFlag
].Char
);
171 *Value
= Flags
[nCurFlag
].Value
;
175 else if(nComparison
< 0)
177 nUpperBound
= nCurFlag
- 1;
181 nLowerBound
= nCurFlag
+ 1;
183 } while(nUpperBound
>= nLowerBound
);
185 /* flag not found: failure */
190 Find the next string flag and return its numerical value. The flags array must
191 be sorted - a dichotomycal search is performed
194 COMMDCB_ParseStrFlag(LPWSTR
*StrTail
,
195 PCOMMDCB_PARAM_STRFLAG Flags
,
200 UNICODE_STRING wstrFlag
;
202 /* scan the string until the first space character or the terminating null */
203 for(pwcNewTail
= *StrTail
;
204 pwcNewTail
[0] && !iswspace(pwcNewTail
[0]);
207 /* string flag empty */
208 if(pwcNewTail
== *StrTail
)
211 /* build the UNICODE_STRING description of the string flag */
212 wstrFlag
.Buffer
= *StrTail
;
213 wstrFlag
.Length
= (pwcNewTail
- *StrTail
) * sizeof(WCHAR
);
214 wstrFlag
.MaximumLength
= wstrFlag
.Length
;
216 /* skip the string flag */
217 *StrTail
= pwcNewTail
;
219 /* lookup the string flag's value and return it */
220 return COMMDCB_LookupStrFlag(&wstrFlag
, Flags
, FlagCount
, Value
);
224 Parse a boolean value in the symbolic form on/off
227 COMMDCB_ParseBool(LPWSTR
*StrTail
,
232 static COMMDCB_PARAM_STRFLAG a_BoolFlags
[] = {
233 { RTL_CONSTANT_STRING(L
"off"), FALSE
},
234 { RTL_CONSTANT_STRING(L
"on"), TRUE
}
237 /* try to recognize the next flag as a boolean */
238 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
240 sizeof(a_BoolFlags
) / sizeof(a_BoolFlags
[0]),
248 *Value
= (nValue
? TRUE
: FALSE
);
253 Parse a decimal integer
256 COMMDCB_ParseInt(LPWSTR
*StrTail
,
259 LPWSTR pwcPrevTail
= *StrTail
;
260 DWORD nValue
= wcstoul(*StrTail
, StrTail
, 10);
262 /* no character was consumed: failure */
263 if(pwcPrevTail
== *StrTail
)
271 /* PARAMETER HANDLERS */
273 COMMDCB_PARAM_HANDLER(baud
)
279 /* parse the baudrate */
280 if(!COMMDCB_ParseInt(StrTail
, &nValue
))
285 /* documented abbreviations */
299 Dcb
->BaudRate
= 1200;
302 Dcb
->BaudRate
= 2400;
305 Dcb
->BaudRate
= 4800;
308 Dcb
->BaudRate
= 9600;
311 Dcb
->BaudRate
= 19200;
316 Dcb
->BaudRate
= nValue
;
320 /* if the stop bits haven't been specified explicitely */
323 /* default the stop bits to 2 for 110 baud */
324 if(Dcb
->BaudRate
== 110)
325 Dcb
->StopBits
= TWOSTOPBITS
;
326 /* else, default the stop bits to 1 */
328 Dcb
->StopBits
= ONESTOPBIT
;
336 COMMDCB_PARAM_HANDLER(data
)
343 /* parse the data bits */
344 if(!COMMDCB_ParseInt(StrTail
, &nValue
))
347 /* value out of range: failure */
348 if(nValue
< 5 || nValue
> 8)
352 Dcb
->ByteSize
= (BYTE
)nValue
;
357 COMMDCB_PARAM_HANDLER(dtr
)
361 static COMMDCB_PARAM_STRFLAG a_DTRFlags
[] = {
362 { RTL_CONSTANT_STRING(L
"hs"), DTR_CONTROL_HANDSHAKE
},
363 { RTL_CONSTANT_STRING(L
"off"), DTR_CONTROL_DISABLE
},
364 { RTL_CONSTANT_STRING(L
"on"), DTR_CONTROL_ENABLE
}
371 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
373 sizeof(a_DTRFlags
) / sizeof(a_DTRFlags
[0]),
381 Dcb
->fDtrControl
= nValue
;
386 COMMDCB_PARAM_HANDLER(idsr
)
394 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
398 Dcb
->fDsrSensitivity
= bValue
;
403 COMMDCB_PARAM_HANDLER(octs
)
411 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
415 Dcb
->fOutxCtsFlow
= bValue
;
420 COMMDCB_PARAM_HANDLER(odsr
)
428 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
432 Dcb
->fOutxDsrFlow
= bValue
;
437 COMMDCB_PARAM_HANDLER(parity
)
441 static COMMDCB_PARAM_CHARFLAG a_ParityFlags
[] = {
442 { L
'e', EVENPARITY
},
443 { L
'm', MARKPARITY
},
446 { L
's', SPACEPARITY
}
453 bRetVal
= COMMDCB_ParseCharFlag(StrTail
,
455 sizeof(a_ParityFlags
) / sizeof(a_ParityFlags
[0]),
463 Dcb
->Parity
= (BYTE
)nValue
;
468 COMMDCB_PARAM_HANDLER(rts
)
472 static COMMDCB_PARAM_STRFLAG a_RTSFlags
[] = {
473 { RTL_CONSTANT_STRING(L
"hs"), RTS_CONTROL_HANDSHAKE
},
474 { RTL_CONSTANT_STRING(L
"off"), RTS_CONTROL_DISABLE
},
475 { RTL_CONSTANT_STRING(L
"on"), RTS_CONTROL_ENABLE
},
476 { RTL_CONSTANT_STRING(L
"tg"), RTS_CONTROL_TOGGLE
}
483 nRetVal
= COMMDCB_ParseStrFlag(StrTail
,
485 sizeof(a_RTSFlags
) / sizeof(a_RTSFlags
[0]),
493 Dcb
->fRtsControl
= nValue
;
498 COMMDCB_PARAM_HANDLER(stop
)
502 static COMMDCB_PARAM_STRFLAG a_StopFlags
[] = {
503 { RTL_CONSTANT_STRING(L
"1"), ONESTOPBIT
},
504 { RTL_CONSTANT_STRING(L
"1.5"), ONE5STOPBITS
},
505 { RTL_CONSTANT_STRING(L
"2"), TWOSTOPBITS
}
511 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
513 sizeof(a_StopFlags
) / sizeof(a_StopFlags
[0]),
520 /* tell the baud= handler that the stop bits have been specified explicitely */
524 Dcb
->StopBits
= (BYTE
)nValue
;
529 COMMDCB_PARAM_HANDLER(to
)
537 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
540 /* for BuildCommDCB(), Timeouts is NULL */
543 /* why? no idea. All values taken from Windows 2000 with experimentation */
544 Timeouts
->ReadIntervalTimeout
= 0;
545 Timeouts
->ReadTotalTimeoutMultiplier
= 0;
546 Timeouts
->ReadTotalTimeoutConstant
= 0;
547 Timeouts
->WriteTotalTimeoutMultiplier
= 0;
552 Timeouts
->WriteTotalTimeoutConstant
= 60000;
557 Timeouts
->WriteTotalTimeoutConstant
= 0;
566 COMMDCB_PARAM_HANDLER(xon
)
574 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
580 Dcb
->fInX
= Dcb
->fOutX
= TRUE
;
585 Dcb
->fInX
= Dcb
->fOutX
= FALSE
;
593 #define COMMDCB_PARAM(__P__) \
595 RTL_CONSTANT_STRING(L""UNICODIZE(#__P__ )), \
596 (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
604 BuildCommDCBAndTimeoutsW(LPCWSTR lpDef
,
606 LPCOMMTIMEOUTS lpCommTimeouts
)
608 /* tell the baud= handler that the stop bits should be defaulted */
609 BOOL bStopBitsSet
= FALSE
;
611 /* parameter validation */
612 if(lpDCB
->DCBlength
!= sizeof(DCB
))
616 lpDCB
->StopBits
= ONESTOPBIT
;
619 * The documentation for MODE says that data= defaults to 7, but BuildCommDCB
620 * doesn't seem to set it
622 /* lpDCB->ByteSize = 7; */
626 towupper(lpDef
[0]) == L
'C' &&
628 towupper(lpDef
[1]) == L
'O' &&
630 towupper(lpDef
[2]) == L
'M')
637 /* premature end of string */
642 if(!COMMDCB_ParseInt((LPWSTR
*)&lpDef
, &nDummy
))
650 /* skip leading whitespace */
651 while(lpDef
[0] && iswspace(lpDef
[0]))
654 /* repeat until the end of the string */
657 static COMMDCB_PARAM_STRFLAG a_Params
[] = {
664 COMMDCB_PARAM(parity
),
671 COMMDCB_PARAM_CALLBACK pCallback
;
672 UNICODE_STRING wstrParam
;
673 LPWSTR pwcPrevTail
= (LPWSTR
)lpDef
;
675 /* get the parameter */
676 while(lpDef
[0] && lpDef
[0] != L
'=')
679 /* premature end of string */
683 /* build the parameter's UNICODE_STRING */
684 wstrParam
.Buffer
= pwcPrevTail
;
685 wstrParam
.Length
= (lpDef
- pwcPrevTail
) * sizeof(WCHAR
);
686 wstrParam
.MaximumLength
= wstrParam
.Length
;
691 /* lookup the callback for the parameter */
692 bRetVal
= COMMDCB_LookupStrFlag(&wstrParam
,
694 sizeof(a_Params
) / sizeof(a_Params
[0]),
695 (ULONG_PTR
*)&pCallback
);
697 /* invalid parameter */
701 /* call the callback to parse the parameter's argument */
702 if(!pCallback(lpDCB
, lpCommTimeouts
, &bStopBitsSet
, (LPWSTR
*)&lpDef
))
705 /* skip trailing whitespace */
706 while(lpDef
[0] && iswspace(lpDef
[0]))
714 SetLastError(ERROR_INVALID_PARAMETER
);
724 BuildCommDCBAndTimeoutsA(LPCSTR lpDef
,
726 LPCOMMTIMEOUTS lpCommTimeouts
)
731 UNICODE_STRING wstrDef
;
733 RtlInitAnsiString(&strDef
, (LPSTR
)lpDef
);
735 Status
= RtlAnsiStringToUnicodeString(&wstrDef
, &strDef
, TRUE
);
737 if(!NT_SUCCESS(Status
))
739 SetLastErrorByStatus(Status
);
743 bRetVal
= BuildCommDCBAndTimeoutsW(wstrDef
.Buffer
, lpDCB
, lpCommTimeouts
);
745 RtlFreeUnicodeString(&wstrDef
);
755 BuildCommDCBA(LPCSTR lpDef
, LPDCB lpDCB
)
757 return BuildCommDCBAndTimeoutsA(lpDef
, lpDCB
, NULL
);
766 BuildCommDCBW(LPCWSTR lpDef
, LPDCB lpDCB
)
768 return BuildCommDCBAndTimeoutsW(lpDef
, lpDCB
, NULL
);
777 ClearCommBreak(HANDLE hFile
)
779 DWORD dwBytesReturned
;
780 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_OFF
,
781 NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
790 ClearCommError(HANDLE hFile
, LPDWORD lpErrors
, LPCOMSTAT lpComStat
)
793 DWORD dwBytesReturned
;
794 SERIAL_STATUS SerialStatus
;
796 status
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_COMMSTATUS
, NULL
, 0,
797 &SerialStatus
, sizeof(SERIAL_STATUS
), &dwBytesReturned
, NULL
);
799 if(!NT_SUCCESS(status
))
807 if(SerialStatus
.Errors
& SERIAL_ERROR_BREAK
)
808 *lpErrors
|= CE_BREAK
;
809 if(SerialStatus
.Errors
& SERIAL_ERROR_FRAMING
)
810 *lpErrors
|= CE_FRAME
;
811 if(SerialStatus
.Errors
& SERIAL_ERROR_OVERRUN
)
812 *lpErrors
|= CE_OVERRUN
;
813 if(SerialStatus
.Errors
& SERIAL_ERROR_QUEUEOVERRUN
)
814 *lpErrors
|= CE_RXOVER
;
815 if(SerialStatus
.Errors
& SERIAL_ERROR_PARITY
)
816 *lpErrors
|= CE_RXPARITY
;
821 ZeroMemory(lpComStat
, sizeof(COMSTAT
));
823 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_CTS
)
824 lpComStat
->fCtsHold
= TRUE
;
825 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_DSR
)
826 lpComStat
->fDsrHold
= TRUE
;
827 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_DCD
)
828 lpComStat
->fRlsdHold
= TRUE
;
829 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_XON
)
830 lpComStat
->fXoffHold
= TRUE
;
831 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_XOFF_SENT
)
832 lpComStat
->fXoffSent
= TRUE
;
834 if(SerialStatus
.EofReceived
)
835 lpComStat
->fEof
= TRUE
;
837 if(SerialStatus
.WaitForImmediate
)
838 lpComStat
->fTxim
= TRUE
;
840 lpComStat
->cbInQue
= SerialStatus
.AmountInInQueue
;
841 lpComStat
->cbOutQue
= SerialStatus
.AmountInOutQueue
;
852 CommConfigDialogA(LPCSTR lpszName
, HWND hWnd
, LPCOMMCONFIG lpCC
)
857 /* don't use the static thread buffer so operations in serialui
858 don't overwrite the string */
859 if(!(NameW
= FilenameA2W(lpszName
, TRUE
)))
864 result
= CommConfigDialogW(NameW
, hWnd
, lpCC
);
866 RtlFreeHeap(RtlGetProcessHeap(), 0, NameW
);
877 CommConfigDialogW(LPCWSTR lpszName
, HWND hWnd
, LPCOMMCONFIG lpCC
)
879 DWORD (STDCALL
*drvCommDlgW
)(LPCWSTR
, HWND
, LPCOMMCONFIG
);
880 HMODULE hSerialuiDll
;
883 //FIXME: Get dll name from registry. (setupapi needed)
884 if(!(hSerialuiDll
= LoadLibraryW(L
"serialui.dll")))
886 DPRINT("CommConfigDialogW: serialui.dll not found.\n");
890 drvCommDlgW
= (DWORD (STDCALL
*)(LPCWSTR
, HWND
, LPCOMMCONFIG
))
891 GetProcAddress(hSerialuiDll
, "drvCommConfigDialogW");
895 DPRINT("CommConfigDialogW: serialui does not export drvCommConfigDialogW\n");
896 FreeLibrary(hSerialuiDll
);
900 result
= drvCommDlgW(lpszName
, hWnd
, lpCC
);
901 SetLastError(result
);
902 FreeLibrary(hSerialuiDll
);
904 return (result
== ERROR_SUCCESS
? TRUE
: FALSE
);
913 EscapeCommFunction(HANDLE hFile
, DWORD dwFunc
)
916 DWORD dwBytesReturned
;
919 case CLRDTR
: // Clears the DTR (data-terminal-ready) signal.
920 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_CLR_DTR
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
922 case CLRRTS
: // Clears the RTS (request-to-send) signal.
923 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_CLR_RTS
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
925 case SETDTR
: // Sends the DTR (data-terminal-ready) signal.
926 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_DTR
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
928 case SETRTS
: // Sends the RTS (request-to-send) signal.
929 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_RTS
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
931 case SETXOFF
: // Causes transmission to act as if an XOFF character has been received.
932 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_XOFF
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
934 case SETXON
: // Causes transmission to act as if an XON character has been received.
935 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_XON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
937 case SETBREAK
: // Suspends character transmission and places the transmission line in a break state until the ClearCommBreak function is called (or EscapeCommFunction is called with the CLRBREAK extended function code). The SETBREAK extended function code is identical to the SetCommBreak function. Note that this extended function does not flush data that has not been transmitted.
938 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_ON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
940 case CLRBREAK
: // Restores character transmission and places the transmission line in a nonbreak state. The CLRBREAK extended function code is identical to the ClearCommBreak function.
941 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_OFF
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
944 DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
945 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
957 GetCommConfig(HANDLE hCommDev
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
959 BOOL ReturnValue
= FALSE
;
960 LPCOMMPROP lpComPort
;
962 DPRINT("GetCommConfig(%d, %p, %p)\n", hCommDev
, lpCC
, lpdwSize
);
964 lpComPort
= RtlAllocateHeap( hProcessHeap
,
966 sizeof(COMMPROP
) + 0x100 );
968 if(NULL
== lpComPort
) {
969 DPRINT("GetCommConfig() - ERROR_NOT_ENOUGH_MEMORY\n");
970 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
974 if( (NULL
== lpdwSize
)
975 || (NULL
== lpCC
) ) {
976 DPRINT("GetCommConfig() - invalid parameter\n");
977 SetLastError(ERROR_INVALID_PARAMETER
);
982 lpComPort
->wPacketLength
= sizeof(COMMPROP
) + 0x100;
983 lpComPort
->dwProvSpec1
= COMMPROP_INITIALIZED
;
984 ReturnValue
= GetCommProperties(hCommDev
, lpComPort
);
987 lpCC
->dwSize
= sizeof(COMMCONFIG
);
990 lpCC
->dwProviderSubType
= lpComPort
->dwProvSubType
;
991 lpCC
->dwProviderSize
= lpComPort
->dwProvSpec2
;
992 if( 0 == lpComPort
->dwProvSpec2
) {
993 lpCC
->dwProviderOffset
= 0;
995 lpCC
->dwProviderOffset
= (ULONG_PTR
)&lpCC
->wcProviderData
[0] - (ULONG_PTR
)lpCC
;
997 if( (lpCC
->dwProviderSize
+lpCC
->dwSize
) > *lpdwSize
) {
998 DPRINT("GetCommConfig() - ERROR_INSUFFICIENT_BUFFER\n");
999 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1000 ReturnValue
= FALSE
;
1002 RtlCopyMemory(lpCC
->wcProviderData
, lpComPort
->wcProvChar
, lpCC
->dwProviderSize
);
1003 ReturnValue
= GetCommState(hCommDev
, &lpCC
->dcb
);
1005 *lpdwSize
= lpCC
->dwSize
+lpCC
->dwProviderSize
;
1009 RtlFreeHeap(hProcessHeap
, 0, lpComPort
);
1010 return (ReturnValue
);
1019 GetCommMask(HANDLE hFile
, LPDWORD lpEvtMask
)
1021 DWORD dwBytesReturned
;
1022 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_WAIT_MASK
,
1023 NULL
, 0, lpEvtMask
, sizeof(DWORD
), &dwBytesReturned
, NULL
);
1032 GetCommModemStatus(HANDLE hFile
, LPDWORD lpModemStat
)
1034 DWORD dwBytesReturned
;
1036 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_MODEMSTATUS
,
1037 NULL
, 0, lpModemStat
, sizeof(DWORD
), &dwBytesReturned
, NULL
);
1046 GetCommProperties(HANDLE hFile
, LPCOMMPROP lpCommProp
)
1048 DWORD dwBytesReturned
;
1049 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_PROPERTIES
, 0, 0,
1050 lpCommProp
, sizeof(COMMPROP
), &dwBytesReturned
, 0);
1059 GetCommState(HANDLE hFile
, LPDCB lpDCB
)
1061 BOOL result
= FALSE
;
1062 DWORD dwBytesReturned
;
1064 SERIAL_BAUD_RATE BaudRate
;
1065 SERIAL_HANDFLOW HandFlow
;
1066 SERIAL_CHARS SpecialChars
;
1067 SERIAL_LINE_CONTROL LineControl
;
1069 DPRINT("GetCommState(%d, %p)\n", hFile
, lpDCB
);
1071 if (lpDCB
== NULL
) {
1072 DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
1076 lpDCB
->DCBlength
= sizeof(DCB
);
1078 /* FIXME: need to fill following fields (1 bit):
1079 * fBinary: binary mode, no EOF check
1080 * fParity: enable parity checking
1081 * fOutX : XON/XOFF out flow control
1082 * fInX : XON/XOFF in flow control
1085 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_BAUD_RATE
,
1086 NULL
, 0, &BaudRate
, sizeof(BaudRate
),&dwBytesReturned
, NULL
);
1087 if (!NT_SUCCESS(result
)) {
1088 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n");
1091 lpDCB
->BaudRate
= BaudRate
.BaudRate
;
1093 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_HANDFLOW
,
1094 NULL
, 0, &HandFlow
, sizeof(HandFlow
), &dwBytesReturned
, NULL
);
1095 if (!NT_SUCCESS(result
)) {
1096 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n");
1099 if (HandFlow
.ControlHandShake
& SERIAL_CTS_HANDSHAKE
) {
1100 lpDCB
->fOutxCtsFlow
= 1;
1102 if (HandFlow
.ControlHandShake
& SERIAL_DSR_HANDSHAKE
) {
1103 lpDCB
->fOutxDsrFlow
= 1;
1105 if (HandFlow
.ControlHandShake
& SERIAL_DTR_CONTROL
) {
1106 lpDCB
->fDtrControl
= 1;
1108 if (HandFlow
.ControlHandShake
& SERIAL_DTR_HANDSHAKE
) {
1109 lpDCB
->fDtrControl
= 2;
1111 if (HandFlow
.ControlHandShake
& SERIAL_RTS_CONTROL
) {
1112 lpDCB
->fRtsControl
= 1;
1114 if (HandFlow
.ControlHandShake
& SERIAL_RTS_HANDSHAKE
) {
1115 lpDCB
->fRtsControl
= 2;
1117 if (HandFlow
.ControlHandShake
& SERIAL_DSR_SENSITIVITY
) {
1118 lpDCB
->fDsrSensitivity
= 1;
1120 if (HandFlow
.ControlHandShake
& SERIAL_ERROR_ABORT
) {
1121 lpDCB
->fAbortOnError
= 1;
1124 if (HandFlow
.FlowReplace
& SERIAL_ERROR_CHAR
) {
1125 lpDCB
->fErrorChar
= 1;
1127 if (HandFlow
.FlowReplace
& SERIAL_NULL_STRIPPING
) {
1130 if (HandFlow
.FlowReplace
& SERIAL_XOFF_CONTINUE
) {
1131 lpDCB
->fTXContinueOnXoff
= 1;
1133 lpDCB
->XonLim
= (WORD
)HandFlow
.XonLimit
;
1134 lpDCB
->XoffLim
= (WORD
)HandFlow
.XoffLimit
;
1136 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_CHARS
,
1137 NULL
, 0, &SpecialChars
, sizeof(SpecialChars
), &dwBytesReturned
, NULL
);
1138 if (!NT_SUCCESS(result
)) {
1139 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n");
1143 lpDCB
->EofChar
= SpecialChars
.EofChar
;
1144 lpDCB
->ErrorChar
= SpecialChars
.ErrorChar
;
1145 // = SpecialChars.BreakChar;
1146 lpDCB
->EvtChar
= SpecialChars
.EventChar
;
1147 lpDCB
->XonChar
= SpecialChars
.XonChar
;
1148 lpDCB
->XoffChar
= SpecialChars
.XoffChar
;
1150 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_LINE_CONTROL
,
1151 NULL
, 0, &LineControl
, sizeof(LineControl
), &dwBytesReturned
, NULL
);
1152 if (!NT_SUCCESS(result
)) {
1153 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n");
1156 lpDCB
->StopBits
= LineControl
.StopBits
;
1157 lpDCB
->Parity
= LineControl
.Parity
;
1158 lpDCB
->ByteSize
= LineControl
.WordLength
;
1159 DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1169 GetCommTimeouts(HANDLE hFile
, LPCOMMTIMEOUTS lpCommTimeouts
)
1171 DWORD dwBytesReturned
;
1173 if (lpCommTimeouts
== NULL
) {
1177 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_TIMEOUTS
,
1179 lpCommTimeouts
, sizeof(COMMTIMEOUTS
),
1180 &dwBytesReturned
, NULL
);
1189 GetDefaultCommConfigW(LPCWSTR lpszName
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
1191 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1201 GetDefaultCommConfigA(LPCSTR lpszName
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
1203 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1213 PurgeComm(HANDLE hFile
, DWORD dwFlags
)
1215 DWORD dwBytesReturned
;
1217 return DeviceIoControl(hFile
, IOCTL_SERIAL_PURGE
,
1218 &dwFlags
, sizeof(DWORD
), NULL
, 0, &dwBytesReturned
, NULL
);
1227 SetCommBreak(HANDLE hFile
)
1229 DWORD dwBytesReturned
;
1231 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_ON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
1240 SetCommConfig(HANDLE hCommDev
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1242 BOOL ReturnValue
= FALSE
;
1244 DPRINT("SetCommConfig(%d, %p, %d)\n", hCommDev
, lpCC
, dwSize
);
1248 DPRINT("SetCommConfig() - invalid parameter\n");
1249 SetLastError(ERROR_INVALID_PARAMETER
);
1250 ReturnValue
= FALSE
;
1254 ReturnValue
= SetCommState(hCommDev
, &lpCC
->dcb
);
1266 SetCommMask(HANDLE hFile
, DWORD dwEvtMask
)
1268 DWORD dwBytesReturned
;
1270 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_WAIT_MASK
,
1271 &dwEvtMask
, sizeof(DWORD
), NULL
, 0, &dwBytesReturned
, NULL
);
1280 SetCommState(HANDLE hFile
, LPDCB lpDCB
)
1282 BOOL result
= FALSE
;
1283 DWORD dwBytesReturned
;
1285 SERIAL_BAUD_RATE BaudRate
;
1286 SERIAL_HANDFLOW HandFlow
;
1287 SERIAL_CHARS SpecialChars
;
1288 SERIAL_LINE_CONTROL LineControl
;
1290 DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile
, lpDCB
);
1292 if (lpDCB
== NULL
) {
1293 DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
1297 BaudRate
.BaudRate
= lpDCB
->BaudRate
;
1298 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BAUD_RATE
,
1299 &BaudRate
, sizeof(BaudRate
), NULL
, 0, &dwBytesReturned
, NULL
);
1300 if (!NT_SUCCESS(result
)) {
1301 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n");
1305 #define SERIAL_DTR_MASK ((ULONG)0x03)
1306 #define SERIAL_DTR_CONTROL ((ULONG)0x01)
1307 #define SERIAL_DTR_HANDSHAKE ((ULONG)0x02)
1308 #define SERIAL_CTS_HANDSHAKE ((ULONG)0x08)
1309 #define SERIAL_DSR_HANDSHAKE ((ULONG)0x10)
1310 #define SERIAL_DCD_HANDSHAKE ((ULONG)0x20)
1311 #define SERIAL_OUT_HANDSHAKEMASK ((ULONG)0x38)
1312 #define SERIAL_DSR_SENSITIVITY ((ULONG)0x40)
1313 #define SERIAL_ERROR_ABORT ((ULONG)0x80000000)
1314 #define SERIAL_CONTROL_INVALID ((ULONG)0x7fffff84)
1316 HandFlow
.ControlHandShake
= 0;
1318 if (lpDCB
->fOutxCtsFlow
) {
1319 HandFlow
.ControlHandShake
|= SERIAL_CTS_HANDSHAKE
;
1321 if (lpDCB
->fOutxDsrFlow
) {
1322 HandFlow
.ControlHandShake
|= SERIAL_DSR_HANDSHAKE
;
1324 if (lpDCB
->fDtrControl
) {
1325 HandFlow
.ControlHandShake
|= SERIAL_DTR_CONTROL
;
1327 if (lpDCB
->fDtrControl
) {
1328 HandFlow
.ControlHandShake
|= SERIAL_DTR_HANDSHAKE
;
1330 if (lpDCB
->fRtsControl
) {
1331 HandFlow
.ControlHandShake
|= SERIAL_RTS_CONTROL
;
1333 if (lpDCB
->fRtsControl
) {
1334 HandFlow
.ControlHandShake
|= SERIAL_RTS_HANDSHAKE
;
1336 if (lpDCB
->fDsrSensitivity
) {
1337 HandFlow
.ControlHandShake
|= SERIAL_DSR_SENSITIVITY
;
1339 if (lpDCB
->fAbortOnError
) {
1340 HandFlow
.ControlHandShake
|= SERIAL_ERROR_ABORT
;
1343 #define SERIAL_AUTO_TRANSMIT ((ULONG)0x01)
1344 #define SERIAL_AUTO_RECEIVE ((ULONG)0x02)
1345 #define SERIAL_ERROR_CHAR ((ULONG)0x04)
1346 #define SERIAL_NULL_STRIPPING ((ULONG)0x08)
1347 #define SERIAL_BREAK_CHAR ((ULONG)0x10)
1348 #define SERIAL_RTS_MASK ((ULONG)0xc0)
1349 #define SERIAL_RTS_CONTROL ((ULONG)0x40)
1350 #define SERIAL_RTS_HANDSHAKE ((ULONG)0x80)
1351 #define SERIAL_TRANSMIT_TOGGLE ((ULONG)0xc0)
1352 #define SERIAL_XOFF_CONTINUE ((ULONG)0x80000000)
1353 #define SERIAL_FLOW_INVALID ((ULONG)0x7fffff20)
1355 HandFlow
.FlowReplace
= 0;
1356 if (lpDCB
->fErrorChar
) {
1357 HandFlow
.FlowReplace
|= SERIAL_ERROR_CHAR
;
1360 HandFlow
.FlowReplace
|= SERIAL_NULL_STRIPPING
;
1362 if (lpDCB
->fTXContinueOnXoff
) {
1363 HandFlow
.FlowReplace
|= SERIAL_XOFF_CONTINUE
;
1365 HandFlow
.XonLimit
= lpDCB
->XonLim
;
1366 HandFlow
.XoffLimit
= lpDCB
->XoffLim
;
1367 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_HANDFLOW
,
1368 &HandFlow
, sizeof(HandFlow
), NULL
, 0, &dwBytesReturned
, NULL
);
1369 if (!NT_SUCCESS(result
)) {
1370 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n");
1374 SpecialChars
.EofChar
= lpDCB
->EofChar
;
1375 SpecialChars
.ErrorChar
= lpDCB
->ErrorChar
;
1376 SpecialChars
.BreakChar
= 0;
1377 SpecialChars
.EventChar
= lpDCB
->EvtChar
;
1378 SpecialChars
.XonChar
= lpDCB
->XonChar
;
1379 SpecialChars
.XoffChar
= lpDCB
->XoffChar
;
1380 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_CHARS
,
1381 &SpecialChars
, sizeof(SpecialChars
), NULL
, 0, &dwBytesReturned
, NULL
);
1382 if (!NT_SUCCESS(result
)) {
1383 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n");
1387 LineControl
.StopBits
= lpDCB
->StopBits
;
1388 LineControl
.Parity
= lpDCB
->Parity
;
1389 LineControl
.WordLength
= lpDCB
->ByteSize
;
1390 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_LINE_CONTROL
,
1391 &LineControl
, sizeof(LineControl
), NULL
, 0, &dwBytesReturned
, NULL
);
1392 if (!NT_SUCCESS(result
)) {
1393 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n");
1397 DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1407 SetCommTimeouts(HANDLE hFile
, LPCOMMTIMEOUTS lpCommTimeouts
)
1409 DWORD dwBytesReturned
;
1410 SERIAL_TIMEOUTS Timeouts
;
1412 if (lpCommTimeouts
== NULL
) {
1415 Timeouts
.ReadIntervalTimeout
= lpCommTimeouts
->ReadIntervalTimeout
;
1416 Timeouts
.ReadTotalTimeoutMultiplier
= lpCommTimeouts
->ReadTotalTimeoutMultiplier
;
1417 Timeouts
.ReadTotalTimeoutConstant
= lpCommTimeouts
->ReadTotalTimeoutConstant
;
1418 Timeouts
.WriteTotalTimeoutMultiplier
= lpCommTimeouts
->WriteTotalTimeoutMultiplier
;
1419 Timeouts
.WriteTotalTimeoutConstant
= lpCommTimeouts
->WriteTotalTimeoutConstant
;
1421 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_TIMEOUTS
,
1422 &Timeouts
, sizeof(Timeouts
), NULL
, 0, &dwBytesReturned
, NULL
);
1431 SetDefaultCommConfigA(LPCSTR lpszName
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1433 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1443 SetDefaultCommConfigW(LPCWSTR lpszName
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1445 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1455 SetupComm(HANDLE hFile
, DWORD dwInQueue
, DWORD dwOutQueue
)
1457 DWORD dwBytesReturned
;
1458 SERIAL_QUEUE_SIZE QueueSize
;
1460 QueueSize
.InSize
= dwInQueue
;
1461 QueueSize
.OutSize
= dwOutQueue
;
1462 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_QUEUE_SIZE
,
1463 &QueueSize
, sizeof(QueueSize
), NULL
, 0, &dwBytesReturned
, NULL
);
1472 TransmitCommChar(HANDLE hFile
, char cChar
)
1474 DWORD dwBytesReturned
;
1475 return DeviceIoControl(hFile
, IOCTL_SERIAL_IMMEDIATE_CHAR
,
1476 &cChar
, sizeof(cChar
), NULL
, 0, &dwBytesReturned
, NULL
);
1485 WaitCommEvent(HANDLE hFile
, LPDWORD lpEvtMask
, LPOVERLAPPED lpOverlapped
)
1487 DWORD dwBytesReturned
;
1489 if (lpEvtMask
== NULL
) {
1493 return DeviceIoControl(hFile
, IOCTL_SERIAL_WAIT_ON_MASK
,
1494 NULL
, 0, lpEvtMask
, sizeof(DWORD
), &dwBytesReturned
, lpOverlapped
);