3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/comm.c
6 * PURPOSE: Comm functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
9 * Robert Dickenson (robd@mok.lvcom.com)
12 * RDD (30/09/2002) implemented many function bodies to call serial driver.
13 * KJK (11/02/2003) implemented BuildCommDCB & BuildCommDCBAndTimeouts
19 #include <kernel32/kernel32.h>
21 /* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */
25 /* Pointer to a callback that handles a particular parameter */
26 typedef BOOL (*COMMDCB_PARAM_CALLBACK)
34 /* Symbolic flag of any length */
35 typedef struct _COMMDCB_PARAM_STRFLAG
37 UNICODE_STRING String;
39 } COMMDCB_PARAM_STRFLAG;
41 /* One char long symbolic flag */
42 typedef struct _COMMDCB_PARAM_CHARFLAG
46 } COMMDCB_PARAM_CHARFLAG;
49 /* stupid Borland C++ requires this */
50 #define _L(__S__) L ## __S__
52 /* Declare a parameter handler */
53 #define COMMDCB_PARAM_HANDLER(__P__) \
54 BOOL COMMDCB_ ## __P__ ## Param \
57 COMMTIMEOUTS * Timeouts, \
64 Lookup a string flag and return its numerical value. The flags array must be
65 sorted - a dichotomycal search is performed
67 BOOL COMMDCB_LookupStrFlag
69 UNICODE_STRING * Flag,
70 COMMDCB_PARAM_STRFLAG * Flags,
75 /* Lower and upper bound for dichotomycal search */
77 int nUpperBound = FlagCount - 1;
82 /* pick the element in the middle of the area of interest as the pivot */
83 int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;
85 /* compare the string with the pivot */
86 nComparison = RtlCompareUnicodeString
89 &Flags[nCurFlag].String,
96 /* return the flag's value */
97 *Value = Flags[nCurFlag].Value;
102 /* string is less than */
103 else if(nComparison < 0)
106 restrict the search to the first half of the current slice, minus the pivot
108 nUpperBound = nCurFlag - 1;
112 /* string is greater than */
116 restrict the search to the second half of the current slice, minus the pivot
118 nLowerBound = nCurFlag + 1;
123 /* continue until the slice is empty */
124 while(nLowerBound <= nUpperBound);
126 /* string not found: failure */
132 Find the next character flag and return its numerical value. The flags array
133 must be sorted - a dichotomycal search is performed
135 BOOL COMMDCB_ParseCharFlag
138 COMMDCB_PARAM_CHARFLAG * Flags,
143 /* Lower and upper bound for dichotomycal search */
145 int nUpperBound = FlagCount - 1;
146 /* get the first character as the flag */
147 WCHAR wcFlag = (*StrTail)[0];
149 /* premature end of string, or the character is whitespace */
150 if(!wcFlag || iswspace(wcFlag))
154 /* uppercase the character for case-insensitive search */
155 wcFlag = towupper(wcFlag);
157 /* skip the character flag */
160 /* see COMMDCB_LookupStrFlag for a description of the algorithm */
164 int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;
166 nComparison = wcFlag - towupper(Flags[nCurFlag].Char);
170 *Value = Flags[nCurFlag].Value;
174 else if(nComparison < 0)
176 nUpperBound = nCurFlag - 1;
180 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
193 BOOL COMMDCB_ParseStrFlag
196 COMMDCB_PARAM_STRFLAG * Flags,
201 LPWSTR pwcNewTail = *StrTail;
202 UNICODE_STRING wstrFlag;
204 /* scan the string until the first space character or the terminating null */
205 while(pwcNewTail[0] && !iswspace(pwcNewTail[0]))
208 /* string flag empty */
209 if(pwcNewTail == *StrTail)
213 /* build the UNICODE_STRING description of the string flag */
214 wstrFlag.Buffer = *StrTail;
215 wstrFlag.Length = (pwcNewTail - *StrTail) * sizeof(WCHAR);
216 wstrFlag.MaximumLength = wstrFlag.Length;
218 /* skip the string flag */
219 *StrTail = pwcNewTail;
221 /* lookup the string flag's value and return it */
222 return COMMDCB_LookupStrFlag(&wstrFlag, Flags, FlagCount, Value);
226 Parse a boolean value in the symbolic form on/off
228 BOOL COMMDCB_ParseBool(LPWSTR * StrTail, BOOL * Value)
232 static COMMDCB_PARAM_STRFLAG a_BoolFlags[] =
234 { UNICODE_STRING_INITIALIZER(L"off"), FALSE },
235 { UNICODE_STRING_INITIALIZER(L"on"), TRUE }
238 /* try to recognize the next flag as a boolean */
239 bRetVal = COMMDCB_ParseStrFlag
243 sizeof(a_BoolFlags) / sizeof(a_BoolFlags[0]),
248 if(!bRetVal) return FALSE;
251 *Value = nValue ? TRUE : FALSE;
256 Parse a decimal integer
258 BOOL COMMDCB_ParseInt(LPWSTR * StrTail, DWORD * Value)
260 LPWSTR pwcPrevTail = *StrTail;
261 DWORD nValue = wcstoul(*StrTail, StrTail, 10);
263 /* no character was consumed: failure */
264 if(pwcPrevTail == *StrTail) return FALSE;
271 /* PARAMETER HANDLERS */
273 COMMDCB_PARAM_HANDLER(baud)
279 /* parse the baudrate */
280 if(!COMMDCB_ParseInt(StrTail, &nValue))
286 /* documented abbreviations */
287 case 11: Dcb->BaudRate = 110; break;
288 case 15: Dcb->BaudRate = 150; break;
289 case 30: Dcb->BaudRate = 300; break;
290 case 60: Dcb->BaudRate = 600; break;
291 case 12: Dcb->BaudRate = 1200; break;
292 case 24: Dcb->BaudRate = 2400; break;
293 case 48: Dcb->BaudRate = 4800; break;
294 case 96: Dcb->BaudRate = 9600; break;
295 case 19: Dcb->BaudRate = 19200; break;
297 default: Dcb->BaudRate = nValue; break;
300 /* if the stop bits haven't been specified explicitely */
303 /* default the stop bits to 2 for 110 baud */
304 if(Dcb->BaudRate == 110) Dcb->StopBits = TWOSTOPBITS;
305 /* else, default the stop bits to 1 */
306 else Dcb->StopBits = ONESTOPBIT;
314 COMMDCB_PARAM_HANDLER(data)
321 /* parse the data bits */
322 if(!COMMDCB_ParseInt(StrTail, &nValue))
326 /* value out of range: failure */
327 if(nValue < 5 || nValue > 8) return FALSE;
330 Dcb->ByteSize = nValue;
335 COMMDCB_PARAM_HANDLER(dtr)
339 static COMMDCB_PARAM_STRFLAG a_DTRFlags[] =
341 { UNICODE_STRING_INITIALIZER(L"hs"), DTR_CONTROL_HANDSHAKE },
342 { UNICODE_STRING_INITIALIZER(L"off"), DTR_CONTROL_DISABLE },
343 { UNICODE_STRING_INITIALIZER(L"on"), DTR_CONTROL_ENABLE }
350 bRetVal = COMMDCB_ParseStrFlag
354 sizeof(a_DTRFlags) / sizeof(a_DTRFlags[0]),
359 if(!bRetVal) return FALSE;
362 Dcb->fDtrControl = nValue;
367 COMMDCB_PARAM_HANDLER(idsr)
375 if(!COMMDCB_ParseBool(StrTail, &bValue))
380 Dcb->fDsrSensitivity = bValue;
385 COMMDCB_PARAM_HANDLER(octs)
393 if(!COMMDCB_ParseBool(StrTail, &bValue))
398 Dcb->fOutxCtsFlow = bValue;
403 COMMDCB_PARAM_HANDLER(odsr)
411 if(!COMMDCB_ParseBool(StrTail, &bValue))
416 Dcb->fOutxDsrFlow = bValue;
421 COMMDCB_PARAM_HANDLER(parity)
425 static COMMDCB_PARAM_CHARFLAG a_ParityFlags[] =
427 { L'e', EVENPARITY },
428 { L'm', MARKPARITY },
431 { L's', SPACEPARITY }
438 bRetVal = COMMDCB_ParseCharFlag
442 sizeof(a_ParityFlags) / sizeof(a_ParityFlags[0]),
447 if(!bRetVal) return FALSE;
450 Dcb->Parity = nValue;
455 COMMDCB_PARAM_HANDLER(rts)
459 static COMMDCB_PARAM_STRFLAG a_RTSFlags[] =
461 { UNICODE_STRING_INITIALIZER(L"hs"), RTS_CONTROL_HANDSHAKE },
462 { UNICODE_STRING_INITIALIZER(L"off"), RTS_CONTROL_DISABLE },
463 { UNICODE_STRING_INITIALIZER(L"on"), RTS_CONTROL_ENABLE },
464 { UNICODE_STRING_INITIALIZER(L"tg"), RTS_CONTROL_TOGGLE }
471 nRetVal = COMMDCB_ParseStrFlag
475 sizeof(a_RTSFlags) / sizeof(a_RTSFlags[0]),
480 if(!nRetVal) return FALSE;
483 Dcb->fRtsControl = nValue;
488 COMMDCB_PARAM_HANDLER(stop)
492 static COMMDCB_PARAM_STRFLAG a_StopFlags[] =
494 { UNICODE_STRING_INITIALIZER(L"1"), ONESTOPBIT },
495 { UNICODE_STRING_INITIALIZER(L"1.5"), ONE5STOPBITS },
496 { UNICODE_STRING_INITIALIZER(L"2"), TWOSTOPBITS }
502 bRetVal = COMMDCB_ParseStrFlag
506 sizeof(a_StopFlags) / sizeof(a_StopFlags[0]),
511 if(!bRetVal) return FALSE;
513 /* tell the baud= handler that the stop bits have been specified explicitely */
517 Dcb->StopBits = nValue;
522 COMMDCB_PARAM_HANDLER(to)
530 if(!COMMDCB_ParseBool(StrTail, &bValue))
534 /* for BuildCommDCB(), Timeouts is NULL */
537 /* why? no idea. All values taken from Windows 2000 with experimentation */
538 Timeouts->ReadIntervalTimeout = 0;
539 Timeouts->ReadTotalTimeoutMultiplier = 0;
540 Timeouts->ReadTotalTimeoutConstant = 0;
541 Timeouts->WriteTotalTimeoutMultiplier = 0;
544 if(bValue) Timeouts->WriteTotalTimeoutConstant = 60000;
546 else Timeouts->WriteTotalTimeoutConstant = 0;
554 COMMDCB_PARAM_HANDLER(xon)
562 if(!COMMDCB_ParseBool(StrTail, &bValue))
567 if(bValue) Dcb->fInX = Dcb->fOutX = TRUE;
569 else Dcb->fInX = Dcb->fOutX = FALSE;
576 #define COMMDCB_PARAM(__P__) \
578 UNICODE_STRING_INITIALIZER(_L(#__P__)), \
579 (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
587 BuildCommDCBAndTimeoutsW
591 LPCOMMTIMEOUTS lpCommTimeouts
594 /* tell the baud= handler that the stop bits should be defaulted */
595 BOOL bStopBitsSet = FALSE;
597 /* parameter validation */
598 if(lpDCB->DCBlength != sizeof(DCB)) goto InvalidParam;
601 lpDCB->StopBits = ONESTOPBIT;
604 The documentation for MODE says that data= defaults to 7, but BuildCommDCB
605 doesn't seem to set it
607 /* lpDCB->ByteSize = 7; */
613 towupper(lpDef[0]) == L'C' &&
615 towupper(lpDef[1]) == L'O' &&
617 towupper(lpDef[2]) == L'M'
625 /* premature end of string */
626 if(!lpDef[0]) goto InvalidParam;
629 if(!COMMDCB_ParseInt((LPWSTR *)&lpDef, &nDummy)) goto InvalidParam;
632 if(lpDef[0] == L':') ++ lpDef;
635 /* skip leading whitespace */
636 while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
638 /* repeat until the end of the string */
641 static COMMDCB_PARAM_STRFLAG a_Params[] =
649 COMMDCB_PARAM(parity),
656 COMMDCB_PARAM_CALLBACK pCallback;
657 UNICODE_STRING wstrParam;
658 LPWSTR pwcPrevTail = (LPWSTR)lpDef;
660 /* get the parameter */
661 while(lpDef[0] && lpDef[0] != L'=') ++ lpDef;
663 /* premature end of string */
664 if(!lpDef[0]) goto InvalidParam;
666 /* build the parameter's UNICODE_STRING */
667 wstrParam.Buffer = pwcPrevTail;
668 wstrParam.Length = (lpDef - pwcPrevTail) * sizeof(WCHAR);
669 wstrParam.MaximumLength = wstrParam.Length;
674 /* lookup the callback for the parameter */
675 bRetVal = COMMDCB_LookupStrFlag
679 sizeof(a_Params) / sizeof(a_Params[0]),
680 (ULONG_PTR *)&pCallback
683 /* invalid parameter */
684 if(!bRetVal) goto InvalidParam;
686 /* call the callback to parse the parameter's argument */
687 if(!pCallback(lpDCB, lpCommTimeouts, &bStopBitsSet, (LPWSTR *)&lpDef))
691 /* skip trailing whitespace */
692 while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
700 SetLastError(ERROR_INVALID_PARAMETER);
710 BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts)
715 UNICODE_STRING wstrDef;
717 RtlInitAnsiString(&strDef, (LPSTR)lpDef);
719 nErrCode = RtlAnsiStringToUnicodeString(&wstrDef, &strDef, TRUE);
721 if(!NT_SUCCESS(nErrCode))
723 SetLastErrorByStatus(nErrCode);
727 bRetVal = BuildCommDCBAndTimeoutsW(wstrDef.Buffer, lpDCB, lpCommTimeouts);
729 RtlFreeUnicodeString(&wstrDef);
739 BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
741 return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL);
750 BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
752 return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL);
761 ClearCommBreak(HANDLE hFile)
763 WINBOOL result = FALSE;
764 DWORD dwBytesReturned;
766 if (hFile == INVALID_HANDLE_VALUE) {
769 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
779 ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
781 WINBOOL result = FALSE;
782 DWORD dwBytesReturned;
784 if (hFile == INVALID_HANDLE_VALUE) {
785 //SetLastError(CE_MODE);
788 if (lpErrors == NULL) {
789 DPRINT("ERROR: GetCommState() - NULL Errors pointer\n");
792 // *lpErrors = CE_BREAK;
793 // *lpErrors = CE_FRAME;
794 // *lpErrors = CE_IOE;
795 // *lpErrors = CE_MODE;
796 // *lpErrors = CE_OVERRUN;
797 // *lpErrors = CE_RXOVER;
798 // *lpErrors = CE_RXPARITY;
799 // *lpErrors = CE_TXFULL;
801 CE_BREAK The hardware detected a break condition.
802 CE_FRAME The hardware detected a framing error.
803 CE_IOE An I/O error occurred during communications with the device.
804 CE_MODE The requested mode is not supported, or the hFile parameter is invalid. If this value is specified, it is the only valid error.
805 CE_OVERRUN A character-buffer overrun has occurred. The next character is lost.
806 CE_RXOVER An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character.
807 CE_RXPARITY The hardware detected a parity error.
808 CE_TXFULL The application tried to transmit a character, but the output buffer was full.
810 result = DeviceIoControl(hFile, IOCTL_SERIAL_RESET_DEVICE, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
812 if (lpStat != NULL) {
813 lpStat->fCtsHold = 0;
814 lpStat->fDsrHold = 0;
815 lpStat->fRlsdHold = 0;
816 lpStat->fXoffHold = 0;
817 lpStat->fXoffSent = 0;
821 lpStat->cbOutQue = 0;
832 CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
834 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
844 CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
846 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
856 EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
858 WINBOOL result = FALSE;
859 DWORD dwBytesReturned;
861 if (hFile == INVALID_HANDLE_VALUE) {
865 case CLRDTR: // Clears the DTR (data-terminal-ready) signal.
866 result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
868 case CLRRTS: // Clears the RTS (request-to-send) signal.
869 result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
871 case SETDTR: // Sends the DTR (data-terminal-ready) signal.
872 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
874 case SETRTS: // Sends the RTS (request-to-send) signal.
875 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
877 case SETXOFF: // Causes transmission to act as if an XOFF character has been received.
878 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XOFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
880 case SETXON: // Causes transmission to act as if an XON character has been received.
881 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
883 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.
884 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
886 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.
887 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
890 DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
891 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
903 GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
905 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
915 GetCommMask(HANDLE hFile, LPDWORD lpEvtMask)
917 WINBOOL result = FALSE;
918 DWORD dwBytesReturned;
920 if (hFile == INVALID_HANDLE_VALUE) {
923 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_WAIT_MASK,
924 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, NULL);
934 GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
936 WINBOOL result = FALSE;
937 DWORD dwBytesReturned;
939 if (hFile == INVALID_HANDLE_VALUE) {
942 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
943 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
953 GetCommProperties(HANDLE hFile, LPCOMMPROP lpCommProp)
955 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
965 GetCommState(HANDLE hFile, LPDCB lpDCB)
967 WINBOOL result = FALSE;
968 DWORD dwBytesReturned;
970 SERIAL_BAUD_RATE BaudRate;
971 SERIAL_HANDFLOW HandFlow;
972 SERIAL_CHARS SpecialChars;
973 SERIAL_LINE_CONTROL LineControl;
975 DPRINT("GetCommState(%d, %p)\n", hFile, lpDCB);
977 if (hFile == INVALID_HANDLE_VALUE) {
978 DPRINT("ERROR: GetCommState() - INVALID_HANDLE_VALUE\n");
982 DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
985 if (lpDCB->DCBlength != sizeof(DCB)) {
986 DPRINT("ERROR: GetCommState() - Invalid DCB size\n");
990 // DPRINT(" GetCommState() CALLING DeviceIoControl\n");
991 // result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
992 // DPRINT(" GetCommState() DeviceIoControl returned %d\n", result);
994 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_BAUD_RATE,
995 NULL, 0, &BaudRate, sizeof(BaudRate),&dwBytesReturned, NULL);
996 if (!NT_SUCCESS(result)) {
997 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n");
1000 lpDCB->BaudRate = BaudRate.BaudRate;
1002 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_HANDFLOW,
1003 NULL, 0, &HandFlow, sizeof(HandFlow), &dwBytesReturned, NULL);
1004 if (!NT_SUCCESS(result)) {
1005 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n");
1008 if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
1009 lpDCB->fOutxCtsFlow = 1;
1011 if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
1012 lpDCB->fOutxDsrFlow = 1;
1014 if (HandFlow.ControlHandShake & SERIAL_DTR_CONTROL) {
1015 lpDCB->fDtrControl = 1;
1017 if (HandFlow.ControlHandShake & SERIAL_DTR_HANDSHAKE) {
1018 lpDCB->fDtrControl = 2;
1020 if (HandFlow.ControlHandShake & SERIAL_RTS_CONTROL) {
1021 lpDCB->fRtsControl = 1;
1023 if (HandFlow.ControlHandShake & SERIAL_RTS_HANDSHAKE) {
1024 lpDCB->fRtsControl = 2;
1026 if (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
1027 lpDCB->fDsrSensitivity = 1;
1029 if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
1030 lpDCB->fAbortOnError = 1;
1033 if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
1034 lpDCB->fErrorChar = 1;
1036 if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) {
1039 if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) {
1040 lpDCB->fTXContinueOnXoff = 1;
1042 lpDCB->XonLim = HandFlow.XonLimit;
1043 lpDCB->XoffLim = HandFlow.XoffLimit;
1045 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_CHARS,
1046 NULL, 0, &SpecialChars, sizeof(SpecialChars), &dwBytesReturned, NULL);
1047 if (!NT_SUCCESS(result)) {
1048 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n");
1052 lpDCB->EofChar = SpecialChars.EofChar;
1053 lpDCB->ErrorChar = SpecialChars.ErrorChar;
1054 // = SpecialChars.BreakChar;
1055 lpDCB->EvtChar = SpecialChars.EventChar;
1056 lpDCB->XonChar = SpecialChars.XonChar;
1057 lpDCB->XoffChar = SpecialChars.XoffChar;
1059 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_LINE_CONTROL,
1060 NULL, 0, &LineControl, sizeof(LineControl), &dwBytesReturned, NULL);
1061 if (!NT_SUCCESS(result)) {
1062 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n");
1065 lpDCB->StopBits = LineControl.StopBits;
1066 lpDCB->Parity = LineControl.Parity;
1067 lpDCB->ByteSize = LineControl.WordLength;
1068 DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1078 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1080 WINBOOL result = FALSE;
1081 DWORD dwBytesReturned;
1083 if (hFile == INVALID_HANDLE_VALUE) {
1086 if (lpCommTimeouts == NULL) {
1089 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_TIMEOUTS,
1091 lpCommTimeouts, sizeof(COMMTIMEOUTS),
1092 &dwBytesReturned, NULL);
1102 GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1104 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1114 GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1116 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1126 PurgeComm(HANDLE hFile, DWORD dwFlags)
1128 WINBOOL result = FALSE;
1129 DWORD dwBytesReturned;
1131 if (hFile == INVALID_HANDLE_VALUE) {
1134 result = DeviceIoControl(hFile, IOCTL_SERIAL_PURGE,
1135 &dwFlags, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1145 SetCommBreak(HANDLE hFile)
1147 WINBOOL result = FALSE;
1148 DWORD dwBytesReturned;
1150 if (hFile == INVALID_HANDLE_VALUE) {
1153 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
1163 SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize)
1165 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1175 SetCommMask(HANDLE hFile, DWORD dwEvtMask)
1177 WINBOOL result = FALSE;
1178 DWORD dwBytesReturned;
1180 if (hFile == INVALID_HANDLE_VALUE) {
1183 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_WAIT_MASK,
1184 &dwEvtMask, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1194 SetCommState(HANDLE hFile, LPDCB lpDCB)
1196 WINBOOL result = FALSE;
1197 DWORD dwBytesReturned;
1199 SERIAL_BAUD_RATE BaudRate;
1200 SERIAL_HANDFLOW HandFlow;
1201 SERIAL_CHARS SpecialChars;
1202 SERIAL_LINE_CONTROL LineControl;
1204 DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile, lpDCB);
1206 if (hFile == INVALID_HANDLE_VALUE) {
1207 DPRINT("SetCommState() - ERROR: INVALID_HANDLE_VALUE\n");
1210 if (lpDCB == NULL) {
1211 DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
1215 BaudRate.BaudRate = lpDCB->BaudRate;
1216 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BAUD_RATE,
1217 &BaudRate, sizeof(BaudRate), NULL, 0, &dwBytesReturned, NULL);
1218 if (!NT_SUCCESS(result)) {
1219 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n");
1223 #define SERIAL_DTR_MASK ((ULONG)0x03)
1224 #define SERIAL_DTR_CONTROL ((ULONG)0x01)
1225 #define SERIAL_DTR_HANDSHAKE ((ULONG)0x02)
1226 #define SERIAL_CTS_HANDSHAKE ((ULONG)0x08)
1227 #define SERIAL_DSR_HANDSHAKE ((ULONG)0x10)
1228 #define SERIAL_DCD_HANDSHAKE ((ULONG)0x20)
1229 #define SERIAL_OUT_HANDSHAKEMASK ((ULONG)0x38)
1230 #define SERIAL_DSR_SENSITIVITY ((ULONG)0x40)
1231 #define SERIAL_ERROR_ABORT ((ULONG)0x80000000)
1232 #define SERIAL_CONTROL_INVALID ((ULONG)0x7fffff84)
1234 HandFlow.ControlHandShake = 0;
1236 if (lpDCB->fOutxCtsFlow) {
1237 HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
1239 if (lpDCB->fOutxDsrFlow) {
1240 HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
1242 if (lpDCB->fDtrControl) {
1243 HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL;
1245 if (lpDCB->fDtrControl) {
1246 HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
1248 if (lpDCB->fRtsControl) {
1249 HandFlow.ControlHandShake |= SERIAL_RTS_CONTROL;
1251 if (lpDCB->fRtsControl) {
1252 HandFlow.ControlHandShake |= SERIAL_RTS_HANDSHAKE;
1254 if (lpDCB->fDsrSensitivity) {
1255 HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
1257 if (lpDCB->fAbortOnError) {
1258 HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT;
1261 #define SERIAL_AUTO_TRANSMIT ((ULONG)0x01)
1262 #define SERIAL_AUTO_RECEIVE ((ULONG)0x02)
1263 #define SERIAL_ERROR_CHAR ((ULONG)0x04)
1264 #define SERIAL_NULL_STRIPPING ((ULONG)0x08)
1265 #define SERIAL_BREAK_CHAR ((ULONG)0x10)
1266 #define SERIAL_RTS_MASK ((ULONG)0xc0)
1267 #define SERIAL_RTS_CONTROL ((ULONG)0x40)
1268 #define SERIAL_RTS_HANDSHAKE ((ULONG)0x80)
1269 #define SERIAL_TRANSMIT_TOGGLE ((ULONG)0xc0)
1270 #define SERIAL_XOFF_CONTINUE ((ULONG)0x80000000)
1271 #define SERIAL_FLOW_INVALID ((ULONG)0x7fffff20)
1273 HandFlow.FlowReplace = 0;
1274 if (lpDCB->fErrorChar) {
1275 HandFlow.FlowReplace |= SERIAL_ERROR_CHAR;
1278 HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING;
1280 if (lpDCB->fTXContinueOnXoff) {
1281 HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE;
1283 HandFlow.XonLimit = lpDCB->XonLim;
1284 HandFlow.XoffLimit = lpDCB->XoffLim;
1285 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_HANDFLOW,
1286 &HandFlow, sizeof(HandFlow), NULL, 0, &dwBytesReturned, NULL);
1287 if (!NT_SUCCESS(result)) {
1288 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n");
1292 SpecialChars.EofChar = lpDCB->EofChar;
1293 SpecialChars.ErrorChar = lpDCB->ErrorChar;
1294 SpecialChars.BreakChar = 0;
1295 SpecialChars.EventChar = lpDCB->EvtChar;
1296 SpecialChars.XonChar = lpDCB->XonChar;
1297 SpecialChars.XoffChar = lpDCB->XoffChar;
1298 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_CHARS,
1299 &SpecialChars, sizeof(SpecialChars), NULL, 0, &dwBytesReturned, NULL);
1300 if (!NT_SUCCESS(result)) {
1301 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n");
1305 LineControl.StopBits = lpDCB->StopBits;
1306 LineControl.Parity = lpDCB->Parity;
1307 LineControl.WordLength = lpDCB->ByteSize;
1308 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_LINE_CONTROL,
1309 &LineControl, sizeof(LineControl), NULL, 0, &dwBytesReturned, NULL);
1310 if (!NT_SUCCESS(result)) {
1311 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n");
1315 DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1325 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1327 WINBOOL result = FALSE;
1328 DWORD dwBytesReturned;
1329 SERIAL_TIMEOUTS Timeouts;
1331 if (hFile == INVALID_HANDLE_VALUE) {
1334 if (lpCommTimeouts == NULL) {
1337 Timeouts.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout;
1338 Timeouts.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier;
1339 Timeouts.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant;
1340 Timeouts.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier;
1341 Timeouts.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant;
1342 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_TIMEOUTS,
1343 &Timeouts, sizeof(Timeouts), NULL, 0, &dwBytesReturned, NULL);
1353 SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1355 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1365 SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1367 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1377 SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
1379 WINBOOL result = FALSE;
1380 DWORD dwBytesReturned;
1381 SERIAL_QUEUE_SIZE QueueSize;
1383 if (hFile == INVALID_HANDLE_VALUE) {
1386 QueueSize.InSize = dwInQueue;
1387 QueueSize.OutSize = dwOutQueue;
1388 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_QUEUE_SIZE,
1389 &QueueSize, sizeof(QueueSize), NULL, 0, &dwBytesReturned, NULL);
1399 TransmitCommChar(HANDLE hFile, char cChar)
1401 WINBOOL result = FALSE;
1402 DWORD dwBytesReturned;
1404 if (hFile == INVALID_HANDLE_VALUE) {
1407 result = DeviceIoControl(hFile, IOCTL_SERIAL_IMMEDIATE_CHAR,
1408 &cChar, sizeof(cChar), NULL, 0, &dwBytesReturned, NULL);
1418 WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
1420 WINBOOL result = FALSE;
1421 DWORD dwBytesReturned;
1423 if (hFile == INVALID_HANDLE_VALUE) {
1426 if (lpEvtMask == NULL) {
1429 result = DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK,
1430 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, lpOverlapped);