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
26 #include "../include/debug.h"
28 /* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */
32 /* Pointer to a callback that handles a particular parameter */
33 typedef BOOL (*COMMDCB_PARAM_CALLBACK
)(DCB
*, COMMTIMEOUTS
*, BOOL
*, LPWSTR
*);
35 /* Symbolic flag of any length */
36 typedef struct _COMMDCB_PARAM_STRFLAG
38 UNICODE_STRING String
;
40 } COMMDCB_PARAM_STRFLAG
, *PCOMMDCB_PARAM_STRFLAG
;
42 /* One char long symbolic flag */
43 typedef struct _COMMDCB_PARAM_CHARFLAG
47 } COMMDCB_PARAM_CHARFLAG
, *PCOMMDCB_PARAM_CHARFLAG
;
51 /* Declare a parameter handler */
52 #define COMMDCB_PARAM_HANDLER(__P__) \
53 BOOL COMMDCB_ ## __P__ ## Param \
56 COMMTIMEOUTS * Timeouts, \
63 Lookup a string flag and return its numerical value. The flags array must be
64 sorted - a dichotomycal search is performed
67 COMMDCB_LookupStrFlag(PUNICODE_STRING Flag
,
68 PCOMMDCB_PARAM_STRFLAG Flags
,
72 /* Lower and upper bound for dichotomycal search */
74 int nUpperBound
= FlagCount
- 1;
79 /* pick the element in the middle of the area of interest as the pivot */
80 int nCurFlag
= nLowerBound
+ (nUpperBound
- nLowerBound
) / 2;
82 /* compare the string with the pivot */
83 nComparison
= RtlCompareUnicodeString(Flag
,
84 &Flags
[nCurFlag
].String
,
90 /* return the flag's value */
91 *Value
= Flags
[nCurFlag
].Value
;
96 else if(nComparison
< 0)
99 * restrict the search to the first half of the current slice, minus the pivot
101 nUpperBound
= nCurFlag
- 1;
106 * restrict the search to the second half of the current slice, minus the pivot
108 nLowerBound
= nCurFlag
+ 1;
110 } while(nLowerBound
<= nUpperBound
);
112 /* string not found: failure */
118 Find the next character flag and return its numerical value. The flags array
119 must be sorted - a dichotomycal search is performed
122 COMMDCB_ParseCharFlag(LPWSTR
*StrTail
,
123 PCOMMDCB_PARAM_CHARFLAG Flags
,
127 /* Lower and upper bound for dichotomycal search */
129 int nUpperBound
= FlagCount
- 1;
130 /* get the first character as the flag */
131 WCHAR wcFlag
= (*StrTail
)[0];
133 /* premature end of string, or the character is whitespace */
134 if(!wcFlag
|| iswspace(wcFlag
))
137 /* uppercase the character for case-insensitive search */
138 wcFlag
= towupper(wcFlag
);
140 /* skip the character flag */
143 /* see COMMDCB_LookupStrFlag for a description of the algorithm */
147 int nCurFlag
= nLowerBound
+ (nUpperBound
- nLowerBound
) / 2;
149 nComparison
= wcFlag
- towupper(Flags
[nCurFlag
].Char
);
153 *Value
= Flags
[nCurFlag
].Value
;
157 else if(nComparison
< 0)
159 nUpperBound
= nCurFlag
- 1;
163 nLowerBound
= nCurFlag
+ 1;
165 } while(nUpperBound
>= nLowerBound
);
167 /* flag not found: failure */
172 Find the next string flag and return its numerical value. The flags array must
173 be sorted - a dichotomycal search is performed
176 COMMDCB_ParseStrFlag(LPWSTR
*StrTail
,
177 PCOMMDCB_PARAM_STRFLAG Flags
,
182 UNICODE_STRING wstrFlag
;
184 /* scan the string until the first space character or the terminating null */
185 for(pwcNewTail
= *StrTail
;
186 pwcNewTail
[0] && !iswspace(pwcNewTail
[0]);
189 /* string flag empty */
190 if(pwcNewTail
== *StrTail
)
193 /* build the UNICODE_STRING description of the string flag */
194 wstrFlag
.Buffer
= *StrTail
;
195 wstrFlag
.Length
= (pwcNewTail
- *StrTail
) * sizeof(WCHAR
);
196 wstrFlag
.MaximumLength
= wstrFlag
.Length
;
198 /* skip the string flag */
199 *StrTail
= pwcNewTail
;
201 /* lookup the string flag's value and return it */
202 return COMMDCB_LookupStrFlag(&wstrFlag
, Flags
, FlagCount
, Value
);
206 Parse a boolean value in the symbolic form on/off
209 COMMDCB_ParseBool(LPWSTR
*StrTail
,
214 static COMMDCB_PARAM_STRFLAG a_BoolFlags
[] = {
215 { RTL_CONSTANT_STRING(L
"off"), FALSE
},
216 { RTL_CONSTANT_STRING(L
"on"), TRUE
}
219 /* try to recognize the next flag as a boolean */
220 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
222 sizeof(a_BoolFlags
) / sizeof(a_BoolFlags
[0]),
230 *Value
= (nValue
? TRUE
: FALSE
);
235 Parse a decimal integer
238 COMMDCB_ParseInt(LPWSTR
*StrTail
,
241 LPWSTR pwcPrevTail
= *StrTail
;
242 DWORD nValue
= wcstoul(*StrTail
, StrTail
, 10);
244 /* no character was consumed: failure */
245 if(pwcPrevTail
== *StrTail
)
253 /* PARAMETER HANDLERS */
255 COMMDCB_PARAM_HANDLER(baud
)
261 /* parse the baudrate */
262 if(!COMMDCB_ParseInt(StrTail
, &nValue
))
267 /* documented abbreviations */
281 Dcb
->BaudRate
= 1200;
284 Dcb
->BaudRate
= 2400;
287 Dcb
->BaudRate
= 4800;
290 Dcb
->BaudRate
= 9600;
293 Dcb
->BaudRate
= 19200;
298 Dcb
->BaudRate
= nValue
;
302 /* if the stop bits haven't been specified explicitely */
305 /* default the stop bits to 2 for 110 baud */
306 if(Dcb
->BaudRate
== 110)
307 Dcb
->StopBits
= TWOSTOPBITS
;
308 /* else, default the stop bits to 1 */
310 Dcb
->StopBits
= ONESTOPBIT
;
318 COMMDCB_PARAM_HANDLER(data
)
325 /* parse the data bits */
326 if(!COMMDCB_ParseInt(StrTail
, &nValue
))
329 /* value out of range: failure */
330 if(nValue
< 5 || nValue
> 8)
334 Dcb
->ByteSize
= nValue
;
339 COMMDCB_PARAM_HANDLER(dtr
)
343 static COMMDCB_PARAM_STRFLAG a_DTRFlags
[] = {
344 { RTL_CONSTANT_STRING(L
"hs"), DTR_CONTROL_HANDSHAKE
},
345 { RTL_CONSTANT_STRING(L
"off"), DTR_CONTROL_DISABLE
},
346 { RTL_CONSTANT_STRING(L
"on"), DTR_CONTROL_ENABLE
}
353 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
355 sizeof(a_DTRFlags
) / sizeof(a_DTRFlags
[0]),
363 Dcb
->fDtrControl
= nValue
;
368 COMMDCB_PARAM_HANDLER(idsr
)
376 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
380 Dcb
->fDsrSensitivity
= bValue
;
385 COMMDCB_PARAM_HANDLER(octs
)
393 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
397 Dcb
->fOutxCtsFlow
= bValue
;
402 COMMDCB_PARAM_HANDLER(odsr
)
410 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
414 Dcb
->fOutxDsrFlow
= bValue
;
419 COMMDCB_PARAM_HANDLER(parity
)
423 static COMMDCB_PARAM_CHARFLAG a_ParityFlags
[] = {
424 { L
'e', EVENPARITY
},
425 { L
'm', MARKPARITY
},
428 { L
's', SPACEPARITY
}
435 bRetVal
= COMMDCB_ParseCharFlag(StrTail
,
437 sizeof(a_ParityFlags
) / sizeof(a_ParityFlags
[0]),
445 Dcb
->Parity
= nValue
;
450 COMMDCB_PARAM_HANDLER(rts
)
454 static COMMDCB_PARAM_STRFLAG a_RTSFlags
[] = {
455 { RTL_CONSTANT_STRING(L
"hs"), RTS_CONTROL_HANDSHAKE
},
456 { RTL_CONSTANT_STRING(L
"off"), RTS_CONTROL_DISABLE
},
457 { RTL_CONSTANT_STRING(L
"on"), RTS_CONTROL_ENABLE
},
458 { RTL_CONSTANT_STRING(L
"tg"), RTS_CONTROL_TOGGLE
}
465 nRetVal
= COMMDCB_ParseStrFlag(StrTail
,
467 sizeof(a_RTSFlags
) / sizeof(a_RTSFlags
[0]),
475 Dcb
->fRtsControl
= nValue
;
480 COMMDCB_PARAM_HANDLER(stop
)
484 static COMMDCB_PARAM_STRFLAG a_StopFlags
[] = {
485 { RTL_CONSTANT_STRING(L
"1"), ONESTOPBIT
},
486 { RTL_CONSTANT_STRING(L
"1.5"), ONE5STOPBITS
},
487 { RTL_CONSTANT_STRING(L
"2"), TWOSTOPBITS
}
493 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
495 sizeof(a_StopFlags
) / sizeof(a_StopFlags
[0]),
502 /* tell the baud= handler that the stop bits have been specified explicitely */
506 Dcb
->StopBits
= nValue
;
511 COMMDCB_PARAM_HANDLER(to
)
519 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
522 /* for BuildCommDCB(), Timeouts is NULL */
525 /* why? no idea. All values taken from Windows 2000 with experimentation */
526 Timeouts
->ReadIntervalTimeout
= 0;
527 Timeouts
->ReadTotalTimeoutMultiplier
= 0;
528 Timeouts
->ReadTotalTimeoutConstant
= 0;
529 Timeouts
->WriteTotalTimeoutMultiplier
= 0;
534 Timeouts
->WriteTotalTimeoutConstant
= 60000;
539 Timeouts
->WriteTotalTimeoutConstant
= 0;
548 COMMDCB_PARAM_HANDLER(xon
)
556 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
562 Dcb
->fInX
= Dcb
->fOutX
= TRUE
;
567 Dcb
->fInX
= Dcb
->fOutX
= FALSE
;
575 #define COMMDCB_PARAM(__P__) \
577 RTL_CONSTANT_STRING( L""#__P__ ), \
578 (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
586 BuildCommDCBAndTimeoutsW(LPCWSTR lpDef
,
588 LPCOMMTIMEOUTS lpCommTimeouts
)
590 /* tell the baud= handler that the stop bits should be defaulted */
591 BOOL bStopBitsSet
= FALSE
;
593 /* parameter validation */
594 if(lpDCB
->DCBlength
!= sizeof(DCB
))
598 lpDCB
->StopBits
= ONESTOPBIT
;
601 * The documentation for MODE says that data= defaults to 7, but BuildCommDCB
602 * doesn't seem to set it
604 /* lpDCB->ByteSize = 7; */
608 towupper(lpDef
[0]) == L
'C' &&
610 towupper(lpDef
[1]) == L
'O' &&
612 towupper(lpDef
[2]) == L
'M')
619 /* premature end of string */
624 if(!COMMDCB_ParseInt((LPWSTR
*)&lpDef
, &nDummy
))
632 /* skip leading whitespace */
633 while(lpDef
[0] && iswspace(lpDef
[0]))
636 /* repeat until the end of the string */
639 static COMMDCB_PARAM_STRFLAG a_Params
[] = {
646 COMMDCB_PARAM(parity
),
653 COMMDCB_PARAM_CALLBACK pCallback
;
654 UNICODE_STRING wstrParam
;
655 LPWSTR pwcPrevTail
= (LPWSTR
)lpDef
;
657 /* get the parameter */
658 while(lpDef
[0] && lpDef
[0] != L
'=')
661 /* premature end of string */
665 /* build the parameter's UNICODE_STRING */
666 wstrParam
.Buffer
= pwcPrevTail
;
667 wstrParam
.Length
= (lpDef
- pwcPrevTail
) * sizeof(WCHAR
);
668 wstrParam
.MaximumLength
= wstrParam
.Length
;
673 /* lookup the callback for the parameter */
674 bRetVal
= COMMDCB_LookupStrFlag(&wstrParam
,
676 sizeof(a_Params
) / sizeof(a_Params
[0]),
677 (ULONG_PTR
*)&pCallback
);
679 /* invalid parameter */
683 /* call the callback to parse the parameter's argument */
684 if(!pCallback(lpDCB
, lpCommTimeouts
, &bStopBitsSet
, (LPWSTR
*)&lpDef
))
687 /* skip trailing whitespace */
688 while(lpDef
[0] && iswspace(lpDef
[0]))
696 SetLastError(ERROR_INVALID_PARAMETER
);
706 BuildCommDCBAndTimeoutsA(LPCSTR lpDef
,
708 LPCOMMTIMEOUTS lpCommTimeouts
)
713 UNICODE_STRING wstrDef
;
715 RtlInitAnsiString(&strDef
, (LPSTR
)lpDef
);
717 Status
= RtlAnsiStringToUnicodeString(&wstrDef
, &strDef
, TRUE
);
719 if(!NT_SUCCESS(Status
))
721 SetLastErrorByStatus(Status
);
725 bRetVal
= BuildCommDCBAndTimeoutsW(wstrDef
.Buffer
, lpDCB
, lpCommTimeouts
);
727 RtlFreeUnicodeString(&wstrDef
);
737 BuildCommDCBA(LPCSTR lpDef
, LPDCB lpDCB
)
739 return BuildCommDCBAndTimeoutsA(lpDef
, lpDCB
, NULL
);
748 BuildCommDCBW(LPCWSTR lpDef
, LPDCB lpDCB
)
750 return BuildCommDCBAndTimeoutsW(lpDef
, lpDCB
, NULL
);
759 ClearCommBreak(HANDLE hFile
)
761 DWORD dwBytesReturned
;
762 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_OFF
,
763 NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
772 ClearCommError(HANDLE hFile
, LPDWORD lpErrors
, LPCOMSTAT lpComStat
)
775 DWORD dwBytesReturned
;
776 SERIAL_STATUS SerialStatus
;
778 status
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_COMMSTATUS
, NULL
, 0,
779 &SerialStatus
, sizeof(SERIAL_STATUS
), &dwBytesReturned
, NULL
);
781 if(!NT_SUCCESS(status
))
789 if(SerialStatus
.Errors
& SERIAL_ERROR_BREAK
)
790 *lpErrors
|= CE_BREAK
;
791 if(SerialStatus
.Errors
& SERIAL_ERROR_FRAMING
)
792 *lpErrors
|= CE_FRAME
;
793 if(SerialStatus
.Errors
& SERIAL_ERROR_OVERRUN
)
794 *lpErrors
|= CE_OVERRUN
;
795 if(SerialStatus
.Errors
& SERIAL_ERROR_QUEUEOVERRUN
)
796 *lpErrors
|= CE_RXOVER
;
797 if(SerialStatus
.Errors
& SERIAL_ERROR_PARITY
)
798 *lpErrors
|= CE_RXPARITY
;
803 ZeroMemory(lpComStat
, sizeof(COMSTAT
));
805 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_CTS
)
806 lpComStat
->fCtsHold
= TRUE
;
807 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_DSR
)
808 lpComStat
->fDsrHold
= TRUE
;
809 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_DCD
)
810 lpComStat
->fRlsdHold
= TRUE
;
811 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_FOR_XON
)
812 lpComStat
->fXoffHold
= TRUE
;
813 if(SerialStatus
.HoldReasons
& SERIAL_TX_WAITING_XOFF_SENT
)
814 lpComStat
->fXoffSent
= TRUE
;
816 if(SerialStatus
.EofReceived
)
817 lpComStat
->fEof
= TRUE
;
819 if(SerialStatus
.WaitForImmediate
)
820 lpComStat
->fTxim
= TRUE
;
822 lpComStat
->cbInQue
= SerialStatus
.AmountInInQueue
;
823 lpComStat
->cbOutQue
= SerialStatus
.AmountInOutQueue
;
834 CommConfigDialogA(LPCSTR lpszName
, HWND hWnd
, LPCOMMCONFIG lpCC
)
839 /* don't use the static thread buffer so operations in serialui
840 don't overwrite the string */
841 if(!(NameW
= FilenameA2W(lpszName
, TRUE
)))
846 result
= CommConfigDialogW(NameW
, hWnd
, lpCC
);
848 RtlFreeHeap(RtlGetProcessHeap(), 0, NameW
);
859 CommConfigDialogW(LPCWSTR lpszName
, HWND hWnd
, LPCOMMCONFIG lpCC
)
861 BOOL (STDCALL
*drvCommDlgW
)(LPCWSTR
, HWND
, LPCOMMCONFIG
);
862 HMODULE hSerialuiDll
;
865 //FIXME: Get dll name from registry. (setupapi needed)
866 if(!(hSerialuiDll
= LoadLibraryW(L
"serialui.dll")))
868 DPRINT("CommConfigDialogW: serialui.dll not found.\n");
872 drvCommDlgW
= GetProcAddress(hSerialuiDll
, "drvCommConfigDialogW");
876 DPRINT("CommConfigDialogW: serialui does not export drvCommConfigDialogW\n");
877 FreeLibrary(hSerialuiDll
);
881 result
= drvCommDlgW(lpszName
, hWnd
, lpCC
);
882 FreeLibrary(hSerialuiDll
);
892 EscapeCommFunction(HANDLE hFile
, DWORD dwFunc
)
895 DWORD dwBytesReturned
;
898 case CLRDTR
: // Clears the DTR (data-terminal-ready) signal.
899 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_CLR_DTR
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
901 case CLRRTS
: // Clears the RTS (request-to-send) signal.
902 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_CLR_RTS
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
904 case SETDTR
: // Sends the DTR (data-terminal-ready) signal.
905 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_DTR
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
907 case SETRTS
: // Sends the RTS (request-to-send) signal.
908 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_RTS
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
910 case SETXOFF
: // Causes transmission to act as if an XOFF character has been received.
911 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_XOFF
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
913 case SETXON
: // Causes transmission to act as if an XON character has been received.
914 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_XON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
916 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.
917 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_ON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
919 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.
920 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_OFF
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
923 DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
924 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
936 GetCommConfig(HANDLE hCommDev
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
938 BOOL ReturnValue
= FALSE
;
939 LPCOMMPROP lpComPort
;
941 DPRINT("GetCommConfig(%d, %p, %p)\n", hCommDev
, lpCC
, lpdwSize
);
943 lpComPort
= RtlAllocateHeap( hProcessHeap
,
945 sizeof(COMMPROP
) + 0x100 );
947 if(NULL
== lpComPort
) {
948 DPRINT("GetCommConfig() - ERROR_NOT_ENOUGH_MEMORY\n");
949 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
953 if( (NULL
== lpdwSize
)
954 || (NULL
== lpCC
) ) {
955 DPRINT("GetCommConfig() - invalid parameter\n");
956 SetLastError(ERROR_INVALID_PARAMETER
);
961 lpComPort
->wPacketLength
= sizeof(COMMPROP
) + 0x100;
962 lpComPort
->dwProvSpec1
= COMMPROP_INITIALIZED
;
963 ReturnValue
= GetCommProperties(hCommDev
, lpComPort
);
966 lpCC
->dwSize
= sizeof(COMMCONFIG
);
969 lpCC
->dwProviderSubType
= lpComPort
->dwProvSubType
;
970 lpCC
->dwProviderSize
= lpComPort
->dwProvSpec2
;
971 *lpdwSize
= lpCC
->dwSize
+lpCC
->dwProviderSize
;
972 if( 0 == lpComPort
->dwProvSpec2
) {
973 lpCC
->dwProviderOffset
= 0;
975 lpCC
->dwProviderOffset
= (ULONG_PTR
)&lpCC
->wcProviderData
[0] - (ULONG_PTR
)lpCC
;
977 if( (lpCC
->dwProviderSize
+lpCC
->dwSize
) > *lpdwSize
) {
978 DPRINT("GetCommConfig() - ERROR_INSUFFICIENT_BUFFER\n");
979 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
982 RtlCopyMemory(lpCC
->wcProviderData
, lpComPort
->wcProvChar
, lpCC
->dwProviderSize
);
983 ReturnValue
= GetCommState(hCommDev
, &lpCC
->dcb
);
988 RtlFreeHeap(hProcessHeap
, 0, lpComPort
);
989 return (ReturnValue
);
998 GetCommMask(HANDLE hFile
, LPDWORD lpEvtMask
)
1000 DWORD dwBytesReturned
;
1001 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_WAIT_MASK
,
1002 NULL
, 0, lpEvtMask
, sizeof(DWORD
), &dwBytesReturned
, NULL
);
1011 GetCommModemStatus(HANDLE hFile
, LPDWORD lpModemStat
)
1013 DWORD dwBytesReturned
;
1015 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_MODEMSTATUS
,
1016 NULL
, 0, lpModemStat
, sizeof(DWORD
), &dwBytesReturned
, NULL
);
1025 GetCommProperties(HANDLE hFile
, LPCOMMPROP lpCommProp
)
1027 DWORD dwBytesReturned
;
1028 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_PROPERTIES
, 0, 0,
1029 lpCommProp
, sizeof(COMMPROP
), &dwBytesReturned
, 0);
1038 GetCommState(HANDLE hFile
, LPDCB lpDCB
)
1040 BOOL result
= FALSE
;
1041 DWORD dwBytesReturned
;
1043 SERIAL_BAUD_RATE BaudRate
;
1044 SERIAL_HANDFLOW HandFlow
;
1045 SERIAL_CHARS SpecialChars
;
1046 SERIAL_LINE_CONTROL LineControl
;
1048 DPRINT("GetCommState(%d, %p)\n", hFile
, lpDCB
);
1050 if (lpDCB
== NULL
) {
1051 DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
1055 lpDCB
->DCBlength
= sizeof(DCB
);
1057 /* FIXME: need to fill following fields (1 bit):
1058 * fBinary: binary mode, no EOF check
1059 * fParity: enable parity checking
1060 * fOutX : XON/XOFF out flow control
1061 * fInX : XON/XOFF in flow control
1064 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_BAUD_RATE
,
1065 NULL
, 0, &BaudRate
, sizeof(BaudRate
),&dwBytesReturned
, NULL
);
1066 if (!NT_SUCCESS(result
)) {
1067 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n");
1070 lpDCB
->BaudRate
= BaudRate
.BaudRate
;
1072 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_HANDFLOW
,
1073 NULL
, 0, &HandFlow
, sizeof(HandFlow
), &dwBytesReturned
, NULL
);
1074 if (!NT_SUCCESS(result
)) {
1075 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n");
1078 if (HandFlow
.ControlHandShake
& SERIAL_CTS_HANDSHAKE
) {
1079 lpDCB
->fOutxCtsFlow
= 1;
1081 if (HandFlow
.ControlHandShake
& SERIAL_DSR_HANDSHAKE
) {
1082 lpDCB
->fOutxDsrFlow
= 1;
1084 if (HandFlow
.ControlHandShake
& SERIAL_DTR_CONTROL
) {
1085 lpDCB
->fDtrControl
= 1;
1087 if (HandFlow
.ControlHandShake
& SERIAL_DTR_HANDSHAKE
) {
1088 lpDCB
->fDtrControl
= 2;
1090 if (HandFlow
.ControlHandShake
& SERIAL_RTS_CONTROL
) {
1091 lpDCB
->fRtsControl
= 1;
1093 if (HandFlow
.ControlHandShake
& SERIAL_RTS_HANDSHAKE
) {
1094 lpDCB
->fRtsControl
= 2;
1096 if (HandFlow
.ControlHandShake
& SERIAL_DSR_SENSITIVITY
) {
1097 lpDCB
->fDsrSensitivity
= 1;
1099 if (HandFlow
.ControlHandShake
& SERIAL_ERROR_ABORT
) {
1100 lpDCB
->fAbortOnError
= 1;
1103 if (HandFlow
.FlowReplace
& SERIAL_ERROR_CHAR
) {
1104 lpDCB
->fErrorChar
= 1;
1106 if (HandFlow
.FlowReplace
& SERIAL_NULL_STRIPPING
) {
1109 if (HandFlow
.FlowReplace
& SERIAL_XOFF_CONTINUE
) {
1110 lpDCB
->fTXContinueOnXoff
= 1;
1112 lpDCB
->XonLim
= HandFlow
.XonLimit
;
1113 lpDCB
->XoffLim
= HandFlow
.XoffLimit
;
1115 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_CHARS
,
1116 NULL
, 0, &SpecialChars
, sizeof(SpecialChars
), &dwBytesReturned
, NULL
);
1117 if (!NT_SUCCESS(result
)) {
1118 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n");
1122 lpDCB
->EofChar
= SpecialChars
.EofChar
;
1123 lpDCB
->ErrorChar
= SpecialChars
.ErrorChar
;
1124 // = SpecialChars.BreakChar;
1125 lpDCB
->EvtChar
= SpecialChars
.EventChar
;
1126 lpDCB
->XonChar
= SpecialChars
.XonChar
;
1127 lpDCB
->XoffChar
= SpecialChars
.XoffChar
;
1129 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_LINE_CONTROL
,
1130 NULL
, 0, &LineControl
, sizeof(LineControl
), &dwBytesReturned
, NULL
);
1131 if (!NT_SUCCESS(result
)) {
1132 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n");
1135 lpDCB
->StopBits
= LineControl
.StopBits
;
1136 lpDCB
->Parity
= LineControl
.Parity
;
1137 lpDCB
->ByteSize
= LineControl
.WordLength
;
1138 DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1148 GetCommTimeouts(HANDLE hFile
, LPCOMMTIMEOUTS lpCommTimeouts
)
1150 DWORD dwBytesReturned
;
1152 if (lpCommTimeouts
== NULL
) {
1156 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_TIMEOUTS
,
1158 lpCommTimeouts
, sizeof(COMMTIMEOUTS
),
1159 &dwBytesReturned
, NULL
);
1168 GetDefaultCommConfigW(LPCWSTR lpszName
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
1170 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1180 GetDefaultCommConfigA(LPCSTR lpszName
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
1182 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1192 PurgeComm(HANDLE hFile
, DWORD dwFlags
)
1194 DWORD dwBytesReturned
;
1196 return DeviceIoControl(hFile
, IOCTL_SERIAL_PURGE
,
1197 &dwFlags
, sizeof(DWORD
), NULL
, 0, &dwBytesReturned
, NULL
);
1206 SetCommBreak(HANDLE hFile
)
1208 DWORD dwBytesReturned
;
1210 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_ON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
1219 SetCommConfig(HANDLE hCommDev
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1221 BOOL ReturnValue
= FALSE
;
1223 DPRINT("SetCommConfig(%d, %p, %d)\n", hCommDev
, lpCC
, dwSize
);
1227 DPRINT("SetCommConfig() - invalid parameter\n");
1228 SetLastError(ERROR_INVALID_PARAMETER
);
1229 ReturnValue
= FALSE
;
1233 ReturnValue
= SetCommState(hCommDev
, &lpCC
->dcb
);
1245 SetCommMask(HANDLE hFile
, DWORD dwEvtMask
)
1247 DWORD dwBytesReturned
;
1249 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_WAIT_MASK
,
1250 &dwEvtMask
, sizeof(DWORD
), NULL
, 0, &dwBytesReturned
, NULL
);
1259 SetCommState(HANDLE hFile
, LPDCB lpDCB
)
1261 BOOL result
= FALSE
;
1262 DWORD dwBytesReturned
;
1264 SERIAL_BAUD_RATE BaudRate
;
1265 SERIAL_HANDFLOW HandFlow
;
1266 SERIAL_CHARS SpecialChars
;
1267 SERIAL_LINE_CONTROL LineControl
;
1269 DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile
, lpDCB
);
1271 if (lpDCB
== NULL
) {
1272 DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
1276 BaudRate
.BaudRate
= lpDCB
->BaudRate
;
1277 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BAUD_RATE
,
1278 &BaudRate
, sizeof(BaudRate
), NULL
, 0, &dwBytesReturned
, NULL
);
1279 if (!NT_SUCCESS(result
)) {
1280 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n");
1284 #define SERIAL_DTR_MASK ((ULONG)0x03)
1285 #define SERIAL_DTR_CONTROL ((ULONG)0x01)
1286 #define SERIAL_DTR_HANDSHAKE ((ULONG)0x02)
1287 #define SERIAL_CTS_HANDSHAKE ((ULONG)0x08)
1288 #define SERIAL_DSR_HANDSHAKE ((ULONG)0x10)
1289 #define SERIAL_DCD_HANDSHAKE ((ULONG)0x20)
1290 #define SERIAL_OUT_HANDSHAKEMASK ((ULONG)0x38)
1291 #define SERIAL_DSR_SENSITIVITY ((ULONG)0x40)
1292 #define SERIAL_ERROR_ABORT ((ULONG)0x80000000)
1293 #define SERIAL_CONTROL_INVALID ((ULONG)0x7fffff84)
1295 HandFlow
.ControlHandShake
= 0;
1297 if (lpDCB
->fOutxCtsFlow
) {
1298 HandFlow
.ControlHandShake
|= SERIAL_CTS_HANDSHAKE
;
1300 if (lpDCB
->fOutxDsrFlow
) {
1301 HandFlow
.ControlHandShake
|= SERIAL_DSR_HANDSHAKE
;
1303 if (lpDCB
->fDtrControl
) {
1304 HandFlow
.ControlHandShake
|= SERIAL_DTR_CONTROL
;
1306 if (lpDCB
->fDtrControl
) {
1307 HandFlow
.ControlHandShake
|= SERIAL_DTR_HANDSHAKE
;
1309 if (lpDCB
->fRtsControl
) {
1310 HandFlow
.ControlHandShake
|= SERIAL_RTS_CONTROL
;
1312 if (lpDCB
->fRtsControl
) {
1313 HandFlow
.ControlHandShake
|= SERIAL_RTS_HANDSHAKE
;
1315 if (lpDCB
->fDsrSensitivity
) {
1316 HandFlow
.ControlHandShake
|= SERIAL_DSR_SENSITIVITY
;
1318 if (lpDCB
->fAbortOnError
) {
1319 HandFlow
.ControlHandShake
|= SERIAL_ERROR_ABORT
;
1322 #define SERIAL_AUTO_TRANSMIT ((ULONG)0x01)
1323 #define SERIAL_AUTO_RECEIVE ((ULONG)0x02)
1324 #define SERIAL_ERROR_CHAR ((ULONG)0x04)
1325 #define SERIAL_NULL_STRIPPING ((ULONG)0x08)
1326 #define SERIAL_BREAK_CHAR ((ULONG)0x10)
1327 #define SERIAL_RTS_MASK ((ULONG)0xc0)
1328 #define SERIAL_RTS_CONTROL ((ULONG)0x40)
1329 #define SERIAL_RTS_HANDSHAKE ((ULONG)0x80)
1330 #define SERIAL_TRANSMIT_TOGGLE ((ULONG)0xc0)
1331 #define SERIAL_XOFF_CONTINUE ((ULONG)0x80000000)
1332 #define SERIAL_FLOW_INVALID ((ULONG)0x7fffff20)
1334 HandFlow
.FlowReplace
= 0;
1335 if (lpDCB
->fErrorChar
) {
1336 HandFlow
.FlowReplace
|= SERIAL_ERROR_CHAR
;
1339 HandFlow
.FlowReplace
|= SERIAL_NULL_STRIPPING
;
1341 if (lpDCB
->fTXContinueOnXoff
) {
1342 HandFlow
.FlowReplace
|= SERIAL_XOFF_CONTINUE
;
1344 HandFlow
.XonLimit
= lpDCB
->XonLim
;
1345 HandFlow
.XoffLimit
= lpDCB
->XoffLim
;
1346 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_HANDFLOW
,
1347 &HandFlow
, sizeof(HandFlow
), NULL
, 0, &dwBytesReturned
, NULL
);
1348 if (!NT_SUCCESS(result
)) {
1349 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n");
1353 SpecialChars
.EofChar
= lpDCB
->EofChar
;
1354 SpecialChars
.ErrorChar
= lpDCB
->ErrorChar
;
1355 SpecialChars
.BreakChar
= 0;
1356 SpecialChars
.EventChar
= lpDCB
->EvtChar
;
1357 SpecialChars
.XonChar
= lpDCB
->XonChar
;
1358 SpecialChars
.XoffChar
= lpDCB
->XoffChar
;
1359 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_CHARS
,
1360 &SpecialChars
, sizeof(SpecialChars
), NULL
, 0, &dwBytesReturned
, NULL
);
1361 if (!NT_SUCCESS(result
)) {
1362 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n");
1366 LineControl
.StopBits
= lpDCB
->StopBits
;
1367 LineControl
.Parity
= lpDCB
->Parity
;
1368 LineControl
.WordLength
= lpDCB
->ByteSize
;
1369 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_LINE_CONTROL
,
1370 &LineControl
, sizeof(LineControl
), NULL
, 0, &dwBytesReturned
, NULL
);
1371 if (!NT_SUCCESS(result
)) {
1372 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n");
1376 DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1386 SetCommTimeouts(HANDLE hFile
, LPCOMMTIMEOUTS lpCommTimeouts
)
1388 DWORD dwBytesReturned
;
1389 SERIAL_TIMEOUTS Timeouts
;
1391 if (lpCommTimeouts
== NULL
) {
1394 Timeouts
.ReadIntervalTimeout
= lpCommTimeouts
->ReadIntervalTimeout
;
1395 Timeouts
.ReadTotalTimeoutMultiplier
= lpCommTimeouts
->ReadTotalTimeoutMultiplier
;
1396 Timeouts
.ReadTotalTimeoutConstant
= lpCommTimeouts
->ReadTotalTimeoutConstant
;
1397 Timeouts
.WriteTotalTimeoutMultiplier
= lpCommTimeouts
->WriteTotalTimeoutMultiplier
;
1398 Timeouts
.WriteTotalTimeoutConstant
= lpCommTimeouts
->WriteTotalTimeoutConstant
;
1400 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_TIMEOUTS
,
1401 &Timeouts
, sizeof(Timeouts
), NULL
, 0, &dwBytesReturned
, NULL
);
1410 SetDefaultCommConfigA(LPCSTR lpszName
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1412 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1422 SetDefaultCommConfigW(LPCWSTR lpszName
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1424 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1434 SetupComm(HANDLE hFile
, DWORD dwInQueue
, DWORD dwOutQueue
)
1436 DWORD dwBytesReturned
;
1437 SERIAL_QUEUE_SIZE QueueSize
;
1439 QueueSize
.InSize
= dwInQueue
;
1440 QueueSize
.OutSize
= dwOutQueue
;
1441 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_QUEUE_SIZE
,
1442 &QueueSize
, sizeof(QueueSize
), NULL
, 0, &dwBytesReturned
, NULL
);
1451 TransmitCommChar(HANDLE hFile
, char cChar
)
1453 DWORD dwBytesReturned
;
1454 return DeviceIoControl(hFile
, IOCTL_SERIAL_IMMEDIATE_CHAR
,
1455 &cChar
, sizeof(cChar
), NULL
, 0, &dwBytesReturned
, NULL
);
1464 WaitCommEvent(HANDLE hFile
, LPDWORD lpEvtMask
, LPOVERLAPPED lpOverlapped
)
1466 DWORD dwBytesReturned
;
1468 if (lpEvtMask
== NULL
) {
1472 return DeviceIoControl(hFile
, IOCTL_SERIAL_WAIT_ON_MASK
,
1473 NULL
, 0, lpEvtMask
, sizeof(DWORD
), &dwBytesReturned
, lpOverlapped
);